From e44246951d2f1c67f6821b9ee5e083947910d7ae Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Wed, 28 Jan 2026 14:52:00 -0800 Subject: [PATCH] fix(spawn): prevent use-after-free in subprocess stdin cleanup When onProcessExit runs after the JSSink destructor has already freed the FileSink, the fromJS recovery path would read stale m_sinkPtr from the dead JSSink, accessing freed/reallocated memory. This could close file descriptors belonging to other subprocesses, corrupting their pipe communication. Guard the fromJS recovery with has_stdin_destructor_called to skip it when we know the FileSink has already been freed. --- src/bun.js/api/bun/subprocess.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 7de67a335f..661d32c762 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -591,7 +591,7 @@ pub fn onProcessExit(this: *Subprocess, process: *Process, status: bun.spawn.Sta if (this_jsvalue != .zero) { if (jsc.Codegen.JSSubprocess.stdinGetCached(this_jsvalue)) |existing_value| { if (existing_value.isCell()) { - if (stdin == null) { + if (stdin == null and !this.flags.has_stdin_destructor_called) { // TODO: review this cast stdin = @ptrCast(@alignCast(jsc.WebCore.FileSink.JSSink.fromJS(existing_value))); }