RESOLVED FIXED307229
BBQ JIT-compiled WebAssembly code crashes with ASSERTION FAILED: false in operationCrashDueToBBQStackOverflow() (WasmOperations.cpp:1694) due to unhandled stack overflow during recursive constructor invocation with a Wasm function used as a reduceRight ca
https://bugs.webkit.org/show_bug.cgi?id=307229
Summary BBQ JIT-compiled WebAssembly code crashes with ASSERTION FAILED: false in ope...
do young park
Reported 2026-02-07 02:47:41 PST
Created attachment 478276 [details] crash file A BBQ (Build Bytecode Quickly) JIT-compiled WebAssembly exported function crashes with ASSERTION FAILED: false in JSC::Wasm::operationCrashDueToBBQStackOverflow() when invoked after the JavaScript call stack has been nearly exhausted through recursive constructor invocation. The issue occurs because the BBQ-compiled Wasm code does not gracefully handle the stack overflow condition. Instead of throwing a catchable RangeError (stack overflow), the engine hits a fatal assertion and aborts the process with SIGABRT (signal 6). Steps to Reproduce: Save the following as test.js and run with JSC (with BBQ JIT thresholds lowered): jsc --validateOptions=true --thresholdForJITSoon=10 --thresholdForJITAfterWarmUp=10 --thresholdForOptimizeAfterWarmUp=100 --thresholdForOptimizeAfterLongWarmUp=100 --thresholdForOptimizeSoon=100 --thresholdForFTLOptimizeAfterWarmUp=1000 --thresholdForFTLOptimizeSoon=1000 --validateBCE=true test.js const v48 = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([ 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, 0x03, 0x4E, 0x01, 0x60, 0x00, 0x03, 0x63, 0x72, 0x7C, 0x7F, 0x4E, 0x01, 0x60, 0x04, 0x7F, 0x7F, 0x7E, 0x7F, 0x03, 0x63, 0x6F, 0x63, 0x72, 0x63, 0x71, 0x60, 0x00, 0x03, 0x63, 0x72, 0x7C, 0x7F, 0x03, 0x02, 0x01, 0x02, 0x04, 0x01, 0x00, 0x05, 0x01, 0x00, 0x06, 0x01, 0x00, 0x07, 0x06, 0x01, 0x02, 0x77, 0x30, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x21, 0x19, 0x6D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x63, 0x6F, 0x64, 0x65, 0x2E, 0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x5F, 0x68, 0x69, 0x6E, 0x74, 0x01, 0x00, 0x01, 0xE1, 0x01, 0x01, 0x00, 0x0A, 0xFA, 0x02, 0x01, 0xF7, 0x02, 0x27, 0x01, 0x7F, 0x01, 0x63, 0x72, 0x01, 0x7C, 0x01, 0x7F, 0x01, 0x7B, 0x01, 0x7F, 0x01, 0x7D, 0x01, 0x7B, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7E, 0x01, 0x7F, 0x01, 0x7E, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x63, 0x6F, 0x01, 0x63, 0x72, 0x01, 0x63, 0x71, 0x01, 0x63, 0x71, 0x01, 0x63, 0x72, 0x01, 0x63, 0x6F, 0x01, 0x7F, 0x01, 0x7C, 0x01, 0x63, 0x72, 0x01, 0x7C, 0x01, 0x7F, 0x01, 0x7C, 0x01, 0x63, 0x72, 0x01, 0x7F, 0x01, 0x7C, 0x01, 0x63, 0x72, 0x01, 0x7B, 0x01, 0x7F, 0x01, 0x7B, 0x01, 0x7F, 0x01, 0x7C, 0x01, 0x63, 0x72, 0x41, 0x7F, 0x21, 0x00, 0xD0, 0x72, 0x21, 0x01, 0x44, 0xE2, 0x3E, 0x4A, 0x79, 0xED, 0xA9, 0x7C, 0xC0, 0x21, 0x02, 0x41, 0x01, 0x21, 0x03, 0xFD, 0x0C, 0x3B, 0xF9, 0xA7, 0xAF, 0x1D, 0xBD, 0x60, 0x84, 0x14, 0x6F, 0x0B, 0x26, 0xFA, 0x1B, 0x7F, 0x76, 0x21, 0x04, 0x41, 0xFF, 0xB7, 0x09, 0x21, 0x05, 0x43, 0x70, 0xB0, 0xBA, 0x43, 0x21, 0x06, 0xFD, 0x0C, 0x83, 0x1A, 0x1E, 0x9E, 0x0B, 0x46, 0xAB, 0x63, 0x24, 0x8B, 0x0F, 0xEA, 0x2E, 0x66, 0x22, 0x3F, 0x21, 0x07, 0x20, 0x07, 0xFD, 0x64, 0x21, 0x08, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x20, 0x06, 0xA8, 0x21, 0x09, 0x41, 0x80, 0x78, 0x21, 0x0A, 0x20, 0x0A, 0xAC, 0x21, 0x0B, 0x20, 0x05, 0x20, 0x0A, 0x20, 0x0B, 0x20, 0x09, 0x03, 0x01, 0x21, 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x41, 0x01, 0x21, 0x10, 0x20, 0x0F, 0x20, 0x0F, 0x20, 0x0B, 0x20, 0x10, 0x20, 0x0F, 0x0D, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, 0xD0, 0x6F, 0x21, 0x11, 0xD0, 0x72, 0x21, 0x12, 0xD0, 0x71, 0x21, 0x13, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x0B, 0x21, 0x14, 0x21, 0x15, 0x21, 0x16, 0x02, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x0B, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xC0, 0x21, 0x1A, 0x20, 0x01, 0x20, 0x1A, 0x20, 0x00, 0x0B, 0x21, 0x1B, 0x21, 0x1C, 0x21, 0x1D, 0x20, 0x01, 0x20, 0x02, 0x20, 0x1B, 0x0B, 0x21, 0x1E, 0x21, 0x1F, 0x21, 0x20, 0xFD, 0x0C, 0xFB, 0xF2, 0x56, 0xC1, 0x79, 0x22, 0x78, 0x93, 0x41, 0x3C, 0xF8, 0xFB, 0xFB, 0xE5, 0x4C, 0x37, 0x21, 0x21, 0x20, 0x21, 0xFD, 0x16, 0x0C, 0x21, 0x22, 0xFD, 0x0C, 0xE4, 0x50, 0xFA, 0x59, 0x27, 0x63, 0x41, 0x23, 0x1A, 0xC4, 0x36, 0xB7, 0xA4, 0x70, 0x13, 0x84, 0x21, 0x23, 0x20, 0x01, 0x20, 0x02, 0x20, 0x22, 0x0B, 0x21, 0x24, 0x21, 0x25, 0x21, 0x26, 0x20, 0x01, 0x20, 0x02, 0x20, 0x00, 0x0B, 0x0B, 0x01, 0x00, ]))); const v49 = v48.exports; function F50(a52, a53, a54, ...a55) { if (!new.target) { throw 'must be called with new'; } const v56 = this.constructor; try { const v57 = new v56(); } catch (e) {} const v58 = v49.w0(); } const v59 = new F50(v48, v48, v48, F50, v48, F50); gc(); Expected Result: The Wasm function call should either: Complete successfully, or Throw a catchable JavaScript RangeError (stack overflow) that propagates normally through the JS call stack. The engine should never crash or abort due to a stack overflow in user-supplied WebAssembly code. Actual Result: The process aborts with SIGABRT (signal 6) due to a failed assertion: ASSERTION FAILED: false /home/adawn/WebKit/Source/JavaScriptCore/wasm/WasmOperations.cpp(1694) : void JSC::Wasm::operationCrashDueToBBQStackOverflow() Analysis: The root cause appears to be an insufficient stack overflow check in BBQ JIT-compiled WebAssembly code. The sequence of events is: The constructor F50 is invoked via new F50(...). Inside the constructor, new v56() recursively calls the same constructor, rapidly consuming the JavaScript call stack. The recursion is wrapped in a try/catch, so the eventual RangeError (stack overflow) is caught, and execution continues. At this point, the call stack is nearly exhausted. The constructor then calls v49.w0(), which is a BBQ JIT-compiled WebAssembly exported function. The Wasm function body contains nested blocks, loops, and numerous local variables (39 locals), requiring significant stack frame space. The BBQ-compiled code's stack overflow check either does not fire before entry, or does not account for the full frame size needed. Execution proceeds into the Wasm function and overflows the stack, hitting the fatal assertion in operationCrashDueToBBQStackOverflow(). The Wasm module uses GC reference types (externref, nullexternref, nullref), SIMD v128 operations, and the branch hinting custom section. The combination of a large number of typed locals and nested control flow likely amplifies the stack space requirement, making the insufficient stack check exploitable. Security Impact: This is a denial-of-service (process crash) that can be triggered by any web page loading a crafted WebAssembly module and calling its exported function with a near-exhausted stack. In a release build without assertions, the behavior may differ — potentially leading to an uncontrolled stack overflow which could have further security implications (e.g., stack corruption). Environment: - Platform: Linux x86_64 - Build: WebKit trunk (commit 0f81753fdddc1035077ec0ed7a8c21b23477ee27, 2026-02-03) - Found by: Fuzzilli fuzzer (multi-engine mode, --wasm enabled)
Attachments
crash file (7.03 KB, text/javascript)
2026-02-07 02:47 PST, do young park
no flags
Radar WebKit Bug Importer
Comment 1 2026-02-07 02:47:49 PST
Shu-yu Guo
Comment 2 2026-02-09 16:04:52 PST
Thanks for your bug report. This is a controlled stack exhaustion crash and is not a security bug.
Shu-yu Guo
Comment 3 2026-02-09 16:05:44 PST
EWS
Comment 4 2026-02-10 09:33:01 PST
Committed 307181@main (e5391ad90f47): <https://commits.webkit.org/307181@main> Reviewed commits have been landed. Closing PR #58251 and removing active labels.
bigsean123
Comment 5 2026-02-11 06:19:59 PST
*** Bug 306865 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.