CVE-2025-43438
Overview
Background
- SpeculatedType
- A bitset the DFG/FTL use to represent the possible types of a value and to guard specialized code.
- SpecObjectOther
- A generic ‘some other object’ speculated-type bucket that does not distinguish specific object kinds.
- JSMapIterator / JSSetIterator
- Distinct engine objects with different internal layouts backing Map/Set iteration.
- Speculation check / type confusion
- A JIT guard that, if too coarse, lets a value of the wrong concrete type pass and be misinterpreted.
Root Cause Analysis
The DFG/FTL JIT tracks value types with SpeculatedType bitsets and inserts speculation checks that guard type-specialized code. JSMapIterator and JSSetIterator objects were both mapped to the generic bucket SpecObjectOther rather than to distinct speculated types: speculationFromJSType returned SpecObjectOther for both iterator JSTypes, and speculateMapIteratorObject/speculateSetObject (in DFGSpeculativeJIT and FTLLowerDFGToB3) checked against SpecObjectOther. Because both iterators shared the same speculated type, the abstract interpreter and speculation checks could not distinguish a Map iterator from a Set iterator (nor from other SpecObjectOther objects): a node speculated to operate on a Map iterator would accept a Set iterator that passed the same SpecObjectOther check, so type-specialized code then accessed the wrong iterator’s internal layout – a type confusion between JSMapIterator and JSSetIterator. Operating on one iterator’s fields as if it were the other corrupts memory (advisory class UAF/crash).
The fix introduces distinct SpeculatedType bits SpecMapIteratorObject and SpecSetIteratorObject, returns them from speculationFromJSType for the respective JSTypes, and updates the speculation checks/UseKinds to use the specific type, so a Map-iterator speculation rejects a Set iterator and vice versa.
The restored invariant is that Map and Set iterators are distinct speculated types, so the JIT’s iterator type checks are precise.
Attack Path
- Warm up iterator code in the JIT Run JS that uses Map and Set iterators so the DFG/FTL compiles iterator-specialized nodes speculating on iterator type.
- Confuse the speculation Pre-patch both iterators are SpecObjectOther, so a Map-iterator-speculated node accepts a Set iterator (or vice versa) that passes the same check.
- Access wrong iterator layout The type-specialized code treats one iterator kind as the other, reading/writing the wrong internal fields.
- Corrupt memory The iterator type confusion yields memory corruption in the WebContent process.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
speculationFromJSTypeSource/JavaScriptCore/bytecode/SpeculatedType.cpp |
modified | Returns distinct SpecMapIteratorObject / SpecSetIteratorObject for the Map/Set iterator JSTypes instead of the shared SpecObjectOther. |
SpecMapIteratorObject / SpecSetIteratorObject bitsSource/JavaScriptCore/bytecode/SpeculatedType.h |
modified | Adds dedicated SpeculatedType bits so Map and Set iterators are distinguishable in speculation. |
SpeculativeJIT::speculateMapIteratorObject / speculateSetObjectSource/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp |
modified | Speculation checks now use the specific iterator SpeculatedType, so the wrong iterator kind fails the check. |
FTLLowerDFGToB3 iterator checksSource/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp |
modified | FTL type checks for Map/Set iterators use the distinct speculated types (UseKinds updated in DFGUseKind.h). |
Files Changed
JSTests/stress/map-set-iterator-speculated-types.jsSource/JavaScriptCore/bytecode/SpeculatedType.cppSource/JavaScriptCore/bytecode/SpeculatedType.hSource/JavaScriptCore/dfg/DFGSpeculativeJIT.cppSource/JavaScriptCore/dfg/DFGUseKind.hSource/JavaScriptCore/ftl/FTLLowerDFGToB3.cppSource/JavaScriptCore/runtime/JSType.h
Audit Directions
- Other objects lumped into SpecObjectOthergrep for speculationFromJSType returning SpecObjectOther for concrete JSTypes whose specialized code assumes a specific layout.
- Iterator speculation coverageAudit DFG/FTL nodes handling Map/Set/Array iterators to ensure each checks the precise iterator SpeculatedType.
- UseKind / speculateCellType precisionReview speculateCellType call sites that pass a broad SpeculatedType with a specific JSType, which can admit the wrong concrete type.