CVE-2026-65336
Overview
Background
- ref.test / ref.cast (WASM GC)
- Instructions that test/cast a reference to a target heap type, with an allowNull flag deciding whether null matches.
- In-Place Interpreter (IPInt)
- JSC’s low-level WASM interpreter driven by metadata; it must read instruction operands from validated metadata, not ad-hoc bytecode offsets.
- RefTestCastMetadata
- The per-instruction metadata for ref cast/test; it must carry allowNull so the interpreter uses the correct semantics.
Root Cause Analysis
This fixes a WebAssembly GC type-confusion in the In-Place Interpreter (IPInt) where the ‘allow null’ flag for ref.test/ref.cast/br_on_cast was read from the wrong place. ref.test/ref.cast (and br_on_cast/br_on_cast_fail) check whether a reference matches a target heap type, parameterized by allowNull (whether a null reference satisfies the cast).
Pre-patch, the IPInt generator (addRefTest/addRefCast/addBranchCast) IGNORED the allowNull argument and did not store it in RefTestCastMetadata, and the interpreter (InPlaceInterpreter64.asm) instead tried to recover the null bit directly from the bytecode stream — loadb 2[PC] then rshifti 1 (bit 1) — a fragile, incorrect read of a flags byte at a fixed PC offset. As a result the effective allowNull used at runtime could be wrong, so a null reference could be accepted by a non-nullable cast (or a nullable cast mis-evaluated), yielding a value of the wrong nullability/type where a valid typed reference is expected — a type confusion.
The fix threads allowNull properly: RefTestCastMetadata gains a uint8_t allowNull field, the generator stores static_cast<uint8_t>(allowNull) for ref.test/ref.cast/br_on_cast, and the interpreter loads it from validated metadata (loadb IPInt::RefTestCastMetadata::allowNull[MC]) instead of the ad-hoc 2[PC] bit-shift.
The restored invariant is that the null-allowed semantics of a ref cast/test come from the validated metadata emitted by the generator, not a mis-derived bytecode byte.
Attack Path
- Run a ref.cast/ref.test in IPInt Execute WASM GC casts (ref.cast/ref.test/br_on_cast) under the In-Place Interpreter.
- Exploit the mis-read null flag Because the interpreter derived allowNull from the wrong bytecode byte, arrange a cast whose effective nullability is wrong.
- Slip a null / wrong-typed ref through A null (or wrong-nullability) reference is accepted by a cast that should reject it, or a non-null cast is mis-evaluated.
- Type confusion The mistyped reference is used as a valid typed reference, a memory-safety violation crashing the WebContent process.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
IPIntGenerator::addRefTest / addRefCast / addBranchCastSource/JavaScriptCore/wasm/WasmIPIntGenerator.cpp |
modified | Store the allowNull flag into RefTestCastMetadata instead of ignoring it. |
RefTestCastMetadataSource/JavaScriptCore/wasm/WasmIPIntGenerator.h |
modified | Adds a uint8_t allowNull field carrying the validated null-allowed semantics. |
ipintOp _br_on_cast / _br_on_cast_fail (and ref.test/cast)Source/JavaScriptCore/llint/InPlaceInterpreter64.asm |
modified | Reads allowNull from RefTestCastMetadata (loadb ...::allowNull[MC]) instead of the fragile loadb 2[PC]/rshifti-1 bytecode bit. |
Files Changed
JSTests/wasm/stress/br-on-cast-fail-overlong-leb128.jsJSTests/wasm/stress/br-on-cast-overlong-leb128.jsSource/JavaScriptCore/llint/InPlaceInterpreter64.asmSource/JavaScriptCore/wasm/WasmIPIntGenerator.cppSource/JavaScriptCore/wasm/WasmIPIntGenerator.h
Audit Directions
- Operand provenance in IPIntAudit InPlaceInterpreter*.asm for operands recovered via loadb N[PC]/bit-shifts rather than named metadata fields; each is a chance to read the wrong byte.
- Generator/interpreter metadata parityGrep IPIntGenerator for instruction args (flags) that are accepted but not stored into the corresponding *Metadata the interpreter reads.