asan: keep MarkedArgumentBuffer inline storage on the real stack
What
Fixes an intermittent UBSan crash in release-asan CI under BUN_GARBAGE_COLLECTOR_LEVEL=1:
Structure.h:1138:25: runtime error: member call on null pointer of type 'JSC::ClassInfo'
seen in test/js/bun/md/md-edge-cases.test.ts (and reproducible deterministically with Bun.markdown.react("a\n\nb") in a loop with Bun.gc(false)).
Why
MarkedArgumentBuffer.wrap allocates a JSC::MarkedArgumentBuffer on the stack inside MarkedArgumentBuffer__run. The first 8 entries live in inline storage that JSC keeps alive via conservative stack scanning. ASAN's detect_stack_use_after_return relocates that local to a heap-backed fake stack the conservative scan does not visit, so values in the inline buffer were unprotected and got collected mid-render.
detect_stack_use_after_return was supposed to be off — src/asan-config.c defined __asan_default_options to disable it — but in CI's split build the C objects are archived into libbun.a, and clang places the ASAN runtime (which already weak-defines that symbol) before user inputs, so an archive member that only provides this symbol is never extracted and the override silently doesn't apply. The disassembled __asan_default_options in CI's release-asan binary returns "".
How
SUPPRESS_ASANonMarkedArgumentBuffer__runkeepsargson the real stack regardless of the runtime option (defense in depth — fixes the crash on its own even withdetect_stack_use_after_return=1forced).__asan_default_optionsmoves tosrc/asan.zigso it lands inbun-zig.o, a direct link input, where the strong definition reliably overrides the runtime's weak default in both full and split builds.src/asan-config.cis removed.
Verification
- Deterministic repro (looped
Markdown.react+Bun.gc(false)): crashed 100% before, passes now — including withdetect_stack_use_after_return=1forced on. md-edge-cases.test.tsunder exact CI env (GC level 1, integrity audit 1.0, leak detection on withtest/leaksan.supp): 10/10 clean runs.- All 1021 markdown tests pass.
nmconfirms__asan_default_optionsis exported frombun-zig.o; ASANverbosity=1confirms FakeStack is no longer created at startup.