[3] [JSC FTL] Fix indexing-type mismatch in OSR exit array materialization during bad time
Rated High because the diff fixes a type confusion between a SlowPutArrayStorage Structure and a contiguous butterfly on a script-visible JSArray produced by FTL OSR exit; the resulting cell is read/written through ArrayStorage codepaths over contiguous memory, yielding controlled out-of-bounds against adjacent heap.
operationMaterializeObjectInOSR is changed to choose the rematerialized array's structure via originalArrayStructureForIndexingType (preserves contiguous structure regardless of bad-time state), populate the butterfly, then call switchToSlowPutArrayStorage(vm) only after the butterfly is consistent. operationPopulateObjectInOSR gains a hasAnyArrayStorage branch for hole fixup after the migration.
Source/JavaScriptCore/ftl/FTLOperations.cpp
Type confusion between a SlowPutArrayStorage Structure and a contiguous-shaped butterfly during FTL OSR materialization of a sunk array.
Patch Details
PhantomNewArrayWithButterfly rematerialization no longer queries arrayStructureForIndexingTypeDuringAllocation; it uses originalArrayStructureForIndexingType. After the butterfly is filled (contiguous slots, public/vector length set as for contiguous), the array is migrated to SlowPutArrayStorage via the dedicated transition. operationPopulateObjectInOSR learns to fix holes on either the contiguous or ArrayStorage shape.
Background
FTL OSR exit reconstructs objects whose materialization the optimizer sunk. For PhantomNewArrayWithButterfly the runtime allocates a fresh JSArray, picks a Structure, allocates a butterfly, and fills it. JSC's "bad time" mode — entered when indexed accessors are installed on Array.prototype / Object.prototype — switches the global object's default array structures to SlowPutArrayStorage, which has a different butterfly header (m_vector, m_numValuesInVector, m_sparseMap) and slot layout from contiguous.
Analysis
Pre-fix, the structure was queried via arrayStructureForIndexingTypeDuringAllocation — which returns the current default for the indexing type, i.e. the bad-time substitute when applicable. The butterfly fill code was hard-wired for contiguous: it wrote into butterfly->contiguous().atUnsafe(index) and set the contiguous public/vector length. The resulting JSArray advertised SlowPutArrayStorage via its Structure while its butterfly was a contiguous shape with no ArrayStorage header.
Any subsequent dispatch on the indexing type — including operationPopulateObjectInOSR's own hole fixup writing JSValue() sentinels through contiguous().atUnsafe(index).setStartingValue(), and any later script-visible load/store on the array — interprets contiguous slots as ArrayStorage vector entries. The header fields aliased into the contiguous payload (m_vector lands where contiguous slots begin) drive reads past the contiguous extent and writes into adjacent memory, producing a controlled OOB read/write primitive on the heap.
The fix orders the operations: build the array contiguous-shaped, fill the butterfly consistently, then migrate to SlowPutArrayStorage through the real transition that rebuilds the header. The new hasAnyArrayStorage branch handles the post-migration hole fixup correctly.
This weakens the JSC array shape invariant during FTL deoptimization. The exploit primitive is type-confused indexed access on a script-reachable JSArray, the canonical seed for JIT exploitation chains.
Audit directions
- Other OSR materialization sites that query "current" structures. Grep
arrayStructureForIndexingTypeDuringAllocationacrossSource/JavaScriptCore/ftlandSource/JavaScriptCore/dfg; any rematerialization path that picks a Structure under bad time must useoriginalArrayStructureForIndexingTypeand explicitly migrate. - Phantom node materializations that allocate a butterfly without re-checking bad-time state. Each
PhantomNew*lowering pair (Object, RegExpObject, Array variants) should be examined for the same race against bad time. switchToSlowPutArrayStorage(vm)callers. Confirm every caller is invoked only when the source butterfly is in a coherent shape; an interrupt between population and transition could leave the same inconsistency.