mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 06:12:08 +00:00
fix(shell): fix use-after-free in shell interpreter error path on Windows
When `runFromJS()` encounters an IO setup failure, it was calling `#deinitFromExec()` which directly frees the interpreter via `allocator.destroy(this)`. However, in the JS code path the interpreter is a GC-managed object — the GC finalizer (`deinitFromFinalizer`) will later attempt to access and free the already-freed memory, causing a use-after-free / segfault. Replace `#deinitFromExec()` with `#derefRootShellAndIOIfNeeded(true)` which properly cleans up only runtime resources (IO, shell env) and marks `cleanup_state = .runtime_cleaned`, allowing the GC finalizer to safely handle the final destruction of the interpreter object. Closes #26836 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1154,7 +1154,11 @@ pub const Interpreter = struct {
|
||||
_ = callframe; // autofix
|
||||
|
||||
if (this.setupIOBeforeRun().asErr()) |e| {
|
||||
defer this.#deinitFromExec();
|
||||
// Clean up runtime resources but NOT the interpreter itself —
|
||||
// this is a GC-managed object, so let the finalizer handle destruction.
|
||||
// Using #deinitFromExec() here would call allocator.destroy(this),
|
||||
// causing a use-after-free when the GC later runs deinitFromFinalizer().
|
||||
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