-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
How can we reproduce the crash?
Summary
Bun.spawn with stdin: new Response(data) causes heap corruption (segfault / pas panic) when concurrent Bun.file().exists() calls and another Bun.spawn stdout read are happening. 100% reproducible.
Environment
- Bun 1.3.9, macOS arm64 (Apple Silicon)
- Exit code 133 (SIGTRAP) or 139 (SIGSEGV)
Reproduction
Save as repro.ts and run with bun repro.ts. Couldn't reproduce on Replit/CodeAndbox so suspect it might be macOS only.
export {};
async function run() {
const fileOps = Array.from({ length: 10 }, () => Bun.file("/tmp/nope").exists());
const outer = Bun.spawn(["bash", "-c", 'for j in $(seq 1 100); do echo "padding padding padding"; done'], {
stdout: "pipe",
stderr: "pipe"
});
const outerText = new Response(outer.stdout as ReadableStream).text();
const inner = Bun.spawn(["cat"], {
stdin: new Response("x".repeat(20000)),
stdout: "pipe"
});
await new Response(inner.stdout as ReadableStream).text();
await inner.exited;
await outerText;
await outer.exited;
await Promise.all(fileOps);
}
await run();
await run();
console.log("OK");Crash rate: 100% (10/10 runs).
Crash output
Manifests as one of two forms depending on timing:
panic(main thread): Segmentation fault at address 0x11213BA080000
pas panic: deallocation did fail ... Alloc bit not set in pas_segregated_page_deallocate_with_page
Both are heap corruption — the first is a corrupted pointer dereference, the second is the allocator's assertion catching an invalid free.
Three required ingredients
All three must be concurrent. Removing any one prevents the crash:
| Ingredient | What | Threshold |
|---|---|---|
Bun.file().exists() |
Concurrent file existence checks | >= 10 calls |
Bun.spawn stdout |
Read via new Response(stdout).text() |
>= ~100 lines of output |
Bun.spawn stdin |
stdin: new Response(data) |
data >= 11,757 bytes |
What does NOT crash
stdin: "pipe"with manual.write()/.end()— never crashesstdin: "ignore"orstdin: "inherit"— never crashes- Fewer than 10 concurrent
Bun.file().exists()calls — never crashes stdin: new Response()data smaller than 11,757 bytes — never crashes- Replacing
Bun.file().exists()withsetTimeoutor other async work — never crashes - Two spawns without any
Bun.file()calls — never crashes
Workaround
Write to a temp file instead of using stdin: new Response():
// CRASHES:
const proc = Bun.spawn(["dot", "-Tsvg"], {
stdin: new Response(code),
stdout: "pipe"
});
// WORKS:
const tmp = `/tmp/input-${Date.now()}.dot`;
await Bun.write(tmp, code);
const proc = Bun.spawn(["dot", "-Tsvg", tmp], {
stdin: "ignore",
stdout: "pipe"
});Relevant log output
============================================================
Bun v1.3.9 (cf6cdbbb) macOS Silicon
macOS v15.7.3
CPU: fp aes crc32 atomics
Args: "bun" "run" "tests/repro.ts"
Features: jsc spawn(4) tsconfig
Builtins: "bun:main"
Elapsed: 18ms | User: 10ms | Sys: 7ms
RSS: 29.26MB | Peak: 29.26MB | Commit: 1.07GB | Faults: 51 | Machine: 51.54GB
panic(main thread): Segmentation fault at address 0x10F137A080000
oh no: Bun has crashed. This indicates a bug in Bun, not your code.Stack Trace (bun.report)
Bun v1.3.9 (cf6cdbb) on macos aarch64 [AutoCommand]
Segmentation fault at address 0x10D12B6600010
- 1 unknown/js code
Heap.cpp:2893:JSC::Heap::collectIfNecessaryOrDeferHeap.cpp:2893:JSC::Heap::collectIfNecessaryOrDeferLazyPropertyInlines.h:107:JSC::JSString* JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSString>::callFunc<Bun::MarkdownTagStrings::initialize()::$_7>Assertions.h:977:operationPutByValDirectBeyondArrayBoundsStrict- 6 unknown/js code
JSGlobalObject.zig:553:bun.js.node.util.validators.throwErrInvalidArgTypeWithMessageVector.h:122:WTF::UniqueRef<JSC::ChainedWatchpoint>* WTF::Vector<WTF::UniqueRef<JSC::ChainedWatchpoint>, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>::expandCapacity<(...)0>pair.h:467:WTF::HashTableIterator<WTF::HashTable<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::KeyValuePairKeyExtractor<WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > > >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashMap<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::HashTableTraits, (...)0, WTF::FastMalloc>::KeyValuePairTraits, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::FastMalloc>, std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::KeyValuePairKeyExtractor<WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > > >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashMap<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::HashTableTraits, (...)0, WTF::FastMalloc>::KeyValuePairTraits, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> > > WTF::HashTable<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::KeyValuePairKeyExtractor<WTF::KeyValuePair<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > > >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashMap<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::HashTableTraits, (...)0, WTF::FastMalloc>::KeyValuePairTraits, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::FastMalloc>::find<WTF::IdentityHashTranslator<WTF::HashMap<std::__1::pair<JSC::Structure*, JSC::JSCell*>, WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> >, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<std::__1::pair<JSC::Structure*, JSC::JSCell*> >, WTF::HashTraits<WTF::RefPtr<JSC::StructureShape, WTF::RawPtrTraits<JSC::StructureShape>, WTF::DefaultRefDerefTraits<JSC::StructureShape> > >, WTF::HashTableTraits, (...)0, WTF::FastMalloc>::KeyValuePairTraits, WTF::DefaultHash<std::__1::pair<JSC::Structure*, JSC::JSCell*> > >, (...)0, std::__1::pair<JSC::Structure*, JSC::JSCell*> >ZigGlobalObject.h:346:Zig::GlobalObject::GlobalObjectVirtualMachine.zig:2576:bun.js.VirtualMachine.printStackTracefs.zig:1681:Watcher.addFileRuntimeTranspilerStore.zig:585:bun.js.RuntimeTranspilerStore.RuntimeTranspilerStore.TranspilerJob.runFromWorkerThreadimmutable.zig:1060:array_hash_map.ArrayHashMapUnmanagedsegment.c:228:mi_segment_span_free_coalesce
Features: spawn, tsconfig, jsc