mirror of
https://github.com/oven-sh/bun
synced 2026-02-18 06:41:50 +00:00
fix(shell): use-after-free in runFromJS when setupIOBeforeRun fails (#26920)
## Summary - Fixes #26918 — segfault at address `0x28189480080` caused by use-after-free in the shell interpreter - When `setupIOBeforeRun()` fails (e.g., stdout handle unavailable on Windows), the `runFromJS` error path called `deinitFromExec()` which directly freed the GC-managed interpreter object with `allocator.destroy(this)`. When the GC later swept and called `deinitFromFinalizer()` on the already-freed memory, it caused a segfault. - Replaced `deinitFromExec()` with `derefRootShellAndIOIfNeeded(true)` which properly cleans up runtime resources (IO handles, shell environment) while leaving final object destruction to the GC finalizer — matching the pattern already used in `finish()`. ## Test plan - [x] Added regression test in `test/regression/issue/26918.test.ts` that verifies the shell interpreter handles closed stdout gracefully without crashing - [x] Test passes with `bun bd test test/regression/issue/26918.test.ts` - [ ] The actual crash is primarily reproducible on Windows where stdout handles can be truly unavailable — CI Windows tests should validate the fix 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
@@ -1154,7 +1154,7 @@ pub const Interpreter = struct {
|
||||
_ = callframe; // autofix
|
||||
|
||||
if (this.setupIOBeforeRun().asErr()) |e| {
|
||||
defer this.#deinitFromExec();
|
||||
defer this.#derefRootShellAndIOIfNeeded(true);
|
||||
const shellerr = bun.shell.ShellErr.newSys(e);
|
||||
return try throwShellErr(&shellerr, .{ .js = globalThis.bunVM().event_loop });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user