Medium CVSS 4.3 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected Safari crash
ComponentJSC FTL
Bug ClassType Confusion
Tracker311883
Fix commiteba64ef44de3 (WebKit/WebKit) +57/-1
CWECWE-119, CWE-416 (Buffer bounds error, Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedArtem Dinaburg of Trail of Bits via Anthropic CVD
Disclosed2026-05-11

Background

FTL OSR exit / object sinking
The FTL JIT can defer (‘sink’) an object allocation and rematerialize it only if execution bails out (OSR exit) to the baseline.
PhantomNewArrayWithButterfly
A sunk array-with-butterfly allocation node the OSR machinery must rebuild with the correct indexing type and butterfly.
Having a bad time
A VM state entered when indexed accessors are defined on Array/Object prototypes, after which arrays are forced to SlowPutArrayStorage.
Indexing type / butterfly / ArrayStorage
An array’s storage shape (Int32/Double/Contiguous/ArrayStorage) and the backing butterfly memory; SlowPutArrayStorage handles prototype indexed setters.

Root Cause Analysis

This is an FTL OSR-exit object-materialization bug in JavaScriptCore’s handling of a PhantomNewArrayWithButterfly sink. When the FTL sinks an array allocation and later has to rematerialize it during an OSR exit, operationMaterializeObjectInOSR chose the array Structure via globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType). The invariant it relied on is that the indexing type observed at FTL compile time still describes the layout to build at exit time. But the global object can enter ‘having a bad time’ (isHavingABadTime — triggered when an indexed property is defined on Array.prototype/Object.prototype) between FTL compilation and the rematerialization; once that happens, arrayStructureForIndexingTypeDuringAllocation returns a SlowPutArrayStorage structure for every indexing type. The code then rematerialized the butterfly assuming a contiguous/non-ArrayStorage layout while the Structure said SlowPutArrayStorage — a layout mismatch. Writing rematerialized elements (and, in operationPopulateObjectInOSR, clearing ‘hole’ empty JSValues) into the wrong layout corrupts the object/butterfly.

The fix rematerializes with originalArrayStructureForIndexingType (the non-bad-time structure matching how the butterfly is built), and then, if isHavingABadTime(), explicitly calls result->switchToSlowPutArrayStorage(vm) so the final object is converted consistently; correspondingly, operationPopulateObjectInOSR adds a branch to clear a hole in arrayStorage()->m_vector[index] when the indexing type is any ArrayStorage.

The restored invariant is that materialization builds the butterfly and the Structure with a single consistent layout even if a bad-time transition raced the exit.

Key insight
OSR-exit array materialization assumed the compile-time indexing type still held, but a ‘having a bad time’ transition racing the exit switched arrays to SlowPutArrayStorage, creating a Structure/butterfly layout mismatch; materialization must pick the layout consistently and convert if bad-time is active.

Attack Path

  1. Warm up FTL Repeatedly run a function that allocates and fills a typed (e.g. double) array so the FTL compiles it and sinks the allocation as PhantomNewArrayWithButterfly.
  2. Arm a bad-time trigger Prepare code (an Object.defineProperty on Array.prototype[0]) that will put the VM into ‘having a bad time’ during the optimized run.
  3. Force an OSR exit after bad time Trigger the prototype getter (isHavingABadTime becomes true) and cause an OSR exit that rematerializes the sunk array.
  4. Layout mismatch Pre-patch, the array is built with a bad-time SlowPutArrayStorage structure but populated as contiguous, so element writes/hole clears hit the wrong layout — memory corruption or a crash in WebContent.

Impact Assessment

A JIT correctness bug that produces an array whose Structure and butterfly disagree on layout, i.e. attacker-influenced memory corruption in the WebContent process rather than a mere logic error; the observable in the test is a crash. Building a strong primitive requires precise control of the bad-time timing across an OSR exit, but layout-confusion of a JS array is a classic stepping stone toward type confusion and RW. Confined to WebContent. Rated medium.

Changed Functions

FunctionChangeNotes
operationMaterializeObjectInOSR (PhantomNewArrayWithButterfly case)
Source/JavaScriptCore/ftl/FTLOperations.cpp
modified Uses originalArrayStructureForIndexingType to build the array, then switchToSlowPutArrayStorage(vm) when isHavingABadTime(), avoiding a butterfly/Structure layout mismatch.
operationPopulateObjectInOSR
Source/JavaScriptCore/ftl/FTLOperations.cpp
modified Adds a branch to clear a hole via arrayStorage()->m_vector[index].clear() when the array has any ArrayStorage indexing type, matching the rematerialized SlowPutArrayStorage layout.

Files Changed

  • JSTests/stress/ftl-osr-exit-phantom-new-array-with-butterfly-having-a-bad-time.js
  • Source/JavaScriptCore/ftl/FTLOperations.cpp

Audit Directions

  • Other materialization cases
    Review the other Phantom* cases in operationMaterializeObjectInOSR (PhantomNewArrayBuffer, PhantomNewObject, spreads) for the same arrayStructureForIndexingTypeDuringAllocation-vs-original assumption across a possible bad-time transition.
  • isHavingABadTime races
    grep JSC for arrayStructureForIndexingTypeDuringAllocation and haveABadTime()/isHavingABadTime() to find code caching an indexing-type-derived structure across points where script can run.
  • Hole-clearing by layout
    Audit places that write empty JSValue holes into a butterfly to ensure they branch on the actual indexing type (contiguous vs ArrayStorage) as populateObjectInOSR now does.

Original Bug Report

The reporter's bug is still restricted on the tracker.