diff options
author | 2023-10-31 01:06:38 +0530 | |
---|---|---|
committer | 2023-10-30 12:36:38 -0700 | |
commit | cbc5ca770bd427ffff29c748f9da60b83b621a00 (patch) | |
tree | e5ccfe3dc64b7563871391006f3bb316682363f8 | |
parent | 2972cfadfb7904d6e0e13f586ffc13bac784e52b (diff) | |
download | bun-cbc5ca770bd427ffff29c748f9da60b83b621a00.tar.gz bun-cbc5ca770bd427ffff29c748f9da60b83b621a00.tar.zst bun-cbc5ca770bd427ffff29c748f9da60b83b621a00.zip |
fix: Macro segmentation faults (#6756)
* Fix for seg faults when using macros
* Update src/js_ast.zig to reflect review suggestions
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* add test for checking non-zero exitcodes under macros. regression, issue 3830
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
-rw-r--r-- | src/js_ast.zig | 15 | ||||
-rw-r--r-- | src/js_parser.zig | 2 | ||||
-rw-r--r-- | test/regression/issue/03830.test.ts | 30 |
3 files changed, 42 insertions, 5 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig index 3b17240c0..8b745742b 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -7278,8 +7278,9 @@ pub const Macro = struct { exception_holder = Zig.ZigException.Holder.init(); var js_args: []JSC.JSValue = &.{}; + var js_processed_args_len: usize = 0; defer { - for (js_args[0 .. js_args.len - @as(usize, @intFromBool(!javascript_object.isEmpty()))]) |arg| { + for (js_args[0..js_processed_args_len -| @as(usize, @intFromBool(!javascript_object.isEmpty()))]) |arg| { arg.unprotect(); } @@ -7292,12 +7293,18 @@ pub const Macro = struct { .e_call => |call| { const call_args: []Expr = call.args.slice(); js_args = try allocator.alloc(JSC.JSValue, call_args.len + @as(usize, @intFromBool(!javascript_object.isEmpty()))); + js_processed_args_len = js_args.len; - for (call_args, js_args[0..call_args.len]) |in, *out| { - const value = try in.toJS( + for (0.., call_args, js_args[0..call_args.len]) |i, in, *out| { + const value = in.toJS( allocator, globalObject, - ); + ) catch |e| { + // Keeping a separate variable instead of modifying js_args.len + // due to allocator.free call in defer + js_processed_args_len = i; + return e; + }; value.protect(); out.* = value; } diff --git a/src/js_parser.zig b/src/js_parser.zig index fce928a6e..f569f515f 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -16389,7 +16389,7 @@ fn NewParser_( p.log.addError(p.source, expr.loc, "macro threw exception") catch unreachable; } } else { - p.log.addErrorFmt(p.source, expr.loc, p.allocator, "{s} error in macro", .{@errorName(err)}) catch unreachable; + p.log.addErrorFmt(p.source, expr.loc, p.allocator, "\"{s}\" error in macro", .{@errorName(err)}) catch unreachable; } return expr; }; diff --git a/test/regression/issue/03830.test.ts b/test/regression/issue/03830.test.ts new file mode 100644 index 000000000..e0689474c --- /dev/null +++ b/test/regression/issue/03830.test.ts @@ -0,0 +1,30 @@ +// test/regression/issue/03830.test.ts + +import { it, expect } from "bun:test"; +import { bunEnv, bunExe } from "harness"; +import { mkdirSync, rmSync, writeFileSync, readFileSync, mkdtempSync } from "fs"; +import { tmpdir } from "os"; +import { join } from "path"; + +it("macros should not lead to seg faults under any given input", async () => { + // this test code follows the same structure as and + // is based on the code for testing issue 4893 + + const testDir = mkdtempSync(join(tmpdir(), "issue3830-")); + + // Clean up from prior runs if necessary + rmSync(testDir, { recursive: true, force: true }); + + // Create a directory with our test file + mkdirSync(testDir, { recursive: true }); + writeFileSync(join(testDir, "macro.ts"), 'export function fn(str) { return str; }'); + writeFileSync(join(testDir, "index.ts"), "import { fn } from './macro' assert { type: 'macro' };\nfn(`©${''}`);"); + + const { stdout, exitCode } = Bun.spawnSync({ + cmd: [bunExe(), "build", join(testDir, "index.ts")], + env: bunEnv, + stderr: "inherit", + }); + + expect(exitCode).toBe(0); +});
\ No newline at end of file |