[1] DFG proto-fold type confusion via TOCTOU race in GetByStatus condition validation
Severity: High | Component: JSC DFG JIT | 3330a93
Rated High because the observable effect is a DFG speculation failure producing a type-confused property access reachable from web content, and the primitive (controlled read/write over confused backing storage) is projected with confidence 0.92 from the structure-check elision demonstrated in the regression test — unverified claims concern downstream consumer behavior in DFGConstantFoldingPhase.cpp and DFGAbstractInterpreterInlines.h, which are not shown in the diff but do not weaken the core trigger.
ObjectPropertyCondition entries in the condition set used for DFG prototype property folding are now re-validated against the current structure of each condition's object. The fix adds four bail-out checks in GetByStatus::computeFor: null object, overridesGetOwnPropertySlot, non-cacheable property accesses, and hasPolyProto. These checks prevent objects swapped into the prototype chain after condition creation from introducing structures with incompatible property lookup semantics.
Source/JavaScriptCore/bytecode/GetByStatus.cpp
for (auto& condition : conditionSet) {
+ auto* object = condition.object();
+ if (!object)
+ return std::nullopt;
+
+ auto* currentStructure = object->structure();
+ if (currentStructure->typeInfo().overridesGetOwnPropertySlot())
+ return std::nullopt;
+
+ if (!currentStructure->propertyAccessesAreCacheable())
+ return std::nullopt;
+
if ((i + 1) == totalSize) {
// The last condition
if (condition.kind() != PropertyCondition::Presence)
...
}
+ if (currentStructure->hasPolyProto())
+ return std::nullopt;
+
if (condition.kind() != PropertyCondition::Absence)
return std::nullopt;
JSTests/stress/dfg-proto-fold-invalidate3.js
+ const objectX = createClonedArguments();
+ Object.setPrototypeOf(objectX, objectD);
+ ...
+ // Before: A -> B -> C -> D -> E
+ // After: A -> B -> X -> D -> E
+ Reflect.setPrototypeOf(objectD, objectE);
+ Reflect.setPrototypeOf(objectB, objectX);
+
+ await sleep(1000);
+
+ opt(objectA, /* exitEarly */ false);
+
+ shouldBe(createClonedArguments[0], 2.3023e-320);
Patch Details
The patch adds four new guard checks inside the for (auto& condition : conditionSet) loop in GetByStatus::computeFor. For each ObjectPropertyCondition, the fix retrieves the condition's object and its current structure, then returns std::nullopt (aborting the status computation) if: (1) the object is null, (2) the structure's typeInfo().overridesGetOwnPropertySlot() is true, (3) the structure's propertyAccessesAreCacheable() is false, or (4) the structure hasPolyProto(). These checks occur before the existing Absence/Presence kind validation.
Before: After:
for (condition : conditionSet) for (condition : conditionSet)
└─► check Absence/Presence kind ├─► get object->structure()
└─► build status ├─► bail if overridesGetOwnPropertySlot
├─► bail if !propertyAccessesAreCacheable
├─► bail if hasPolyProto
└─► check Absence/Presence kind
└─► build status
Background
When GetByStatus::computeFor is called from the DFG constant folding phase or abstract interpreter, it walks ObjectPropertyCondition entries to verify that a property access can be folded — meaning the JIT can hardcode the property value or offset rather than performing a runtime lookup. Each condition references an object in the prototype chain and asserts something about that object's structure (e.g., Absence — the property is absent on this prototype, or Presence — the property exists here). These conditions are created at one point in time during bytecode analysis, then consumed later during DFG compilation.
ClonedArguments is a special JSC object type created when arguments is accessed in certain calling conventions. It has a synthetic callee property that is handled by overriding getOwnPropertySlot, meaning normal inline-cache-based caching assumptions do not hold for it. The overridesGetOwnPropertySlot flag on a structure indicates this kind of custom property lookup logic — objects with this flag cannot be safely cached by inline caches or folded by the DFG, because their property resolution may differ from the standard structure-based path.
DFG prototype folding is the optimization where the compiler walks a prototype chain, verifies that each intermediate object lacks the target property (Absence) and the final object has it (Presence), then hardcodes the resolved value or offset directly into the compiled code. This avoids the runtime cost of walking the chain on every access.
Analysis
TOCTOU race in DFG prototype condition validation — structure characteristics assumed stable between condition creation and consumption, bypassed by prototype chain mutation.
Before the fix, GetByStatus::computeFor iterated over the ObjectPropertyCondition set without re-checking the current structure of each condition's object. The conditions were created earlier during bytecode analysis, but between creation and consumption during DFG compilation, an attacker could swap objects in the prototype chain via Reflect.setPrototypeOf. The code then used these stale conditions to fold a prototype property access, without verifying that the swapped-in objects had compatible structure characteristics.
This is the third prototype-chain-related DFG folding invalidation bug — the test is explicitly named dfg-proto-fold-invalidate3.js. The pattern is consistent: GetByStatus::computeFor builds property conditions from one snapshot of the prototype chain but consumes them after the chain may have mutated. Each variant finds a new structure characteristic that the code fails to re-validate. The systemic issue is that ObjectPropertyCondition captures a point-in-time assertion, but the code trusts the assertion without rechecking the live state of the referenced object at consumption time. This variant was discovered through variant analysis of the previous two bugs, identifying additional structure characteristics that were not re-validated in the condition loop.
Aaa Aaaa Aaaa Aaaaaaaaaaaa a Aaaaaaaa Aaaaaaaa Aaa Aaaaaaaa Aaaaaa a Aaaaaaaaa Aaaaa Aa a a a a a a a Aa Aaaaa Aaaaaaaa Aa Aaaaaaa Aa a Aa Aaaa Aaaaaa Aaa Aaaaaaaa Aaaaaaa Aa Aaaaaaaa Aaa Aaaaaa Aaa Aaa Aa Aaaa Aaa Aaaaaaaa Aaaaaa Aaaaaaa Aaa Aaaaaa Aaaa Aaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaa Aaaa Aaa Aa Aaaaaaaaa a a Aaaaaaaaaaaaaaa Aaaaaa a Aaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aa Aaaaaa Aaaaaaaaaaaa Aa Aaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aa Aaaaaaa Aaa Aaaaaaaaaaaa Aaaa Aaaa Aaaaa Aaaaaa Aaaaaaaaaa Aaa Aaaaaaaa Aaaaaaaa Aaaaaaaaaaa a Aaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaaa a Aaaaaaaa Aaaaaa Aaaaa Aaaaaaaa Aaaaaa Aaaaa Aa Aaaaaaaaaaa Aa Aaaaaaa Aaaaaaaa Aaaaaaaaa a Aaaa Aaaaaaaaaa Aaa Aaaaaaaa Aaaaa Aaaaaaaaaaaaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aaaaaaaa a Aaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaa Aaaaaaaaaa
Aaa
Aaaaaaa Aaaaaaaaa
Aa Aaaaa Aaaaaa a a a a a a a a a Aaaaaaa a Aaa Aaaa Aa Aa
Aa Aaaa Aaaaa a Aaa Aaaaa Aaaaaa Aaaaaaa Aaaaa
Aa Aaaaa a a a a Aaaaaaaaaaaaaaaaaa a a a a
Aa Aaaaa Aaaaaaaaaaa a Aaa Aaaaaaaaaa Aaaa Aaaaa Aaaaaaaaaa
Aa Aaaaaaaaaaaa a Aaaaa Aaaa Aaaaaaaa Aaaaaa Aaaaa
Aaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaa Aa Aaa Aaaa
Aaa Aaaaaaaaaaaaa Aaaaaa Aaaaa Aaaaaaaaaaa
Aaa
Aaa Aaaa Aaaaaaaaa Aaaaaaa a Aaaaa Aaaaaaa Aaaaaa Aaa a Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaaaaaa Aaaaaaaaaaa Aaa Aaa Aaaaaa a Aaaaaaaaaaaaaaa a Aaaaa Aaaaaaaa Aaaaaaa a Aaaaaaaa a Aa Aaaaaa Aaa Aaaaaaaa Aaaaaaaa Aa Aaa Aaaaaaaa Aaaa Aaaaa Aaaaa Aaaaaaa Aaaaaaa Aa Aaaaa a Aa Aaa Aaaaaaaa Aaaaaa Aaaaa Aaaaaaa Aaaaaaaa Aaaaaa Aaaaaaaaa Aa Aaaaaaaaaaaaaaa Aaaaaaa Aaaaaaaa Aaa Aaaa Aaaaaa Aa Aaaaaaa Aa Aaaaaa Aaaaaaaa Aaaaaa Aaaaaa Aa Aaaaaaaa Aaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaaaa Aaaaaa a Aaaa Aa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaa Aaa Aaa Aaaaa Aa a Aaaa Aaaaaa Aaaa Aaa a Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaa Aaaaaaa Aa Aaaaaaa Aaa Aaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaaa Aaaaa Aaa Aaaa Aaaaaaaaaaaa Aaaa Aaa Aaaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaa Aaa Aaaa Aaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaa Aaaaaaaa Aaaaa a Aaaaaaaaa Aaaaaaaa Aaaaaa Aaaaa Aaaaa Aaaaaaaaaaa Aaaaaaaaa a Aaaaa Aaaaa Aaaaaaa Aaaa Aaaaaaaaa Aaaa Aaa Aaaaaaaaaa Aaaaaaaaaaa Aa Aaaaaaaa Aaa Aaaa Aaaa Aaaaaaaaa Aaaaa Aaaaaa Aaa Aaa Aa Aaaaa Aaa Aaaaaa Aaaa Aaaaaa a Aaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaa Aaaaaa a Aaaaa Aaaaaa Aaaa Aaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaa Aa Aaa Aaaaaaaaaa Aaaaaaaa Aaaaaaaa Aaaaaaaaaaaa Aaaa Aaaaaa Aaa Aaaaaaaa Aaaaaaaa a Aaaaaaaa Aaaaaaa Aaaaaa Aaaaa Aa Aaaaaaaaa
🔒Explores the DFG prototype folding race window and the type confusion primitive it produces, with feasibility assessment under realistic timing conditions
Subscribe to read more
Audit directions
a Aaaaaaaa Aaaaaa Aa Aaa Aaaaaa Aaaaaaaaaaa a Aaa Aaaaaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaa Aaaa Aaaaaaaa Aaaaaaaaa Aaaa Aaa Aaaaa Aaaaaa Aaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaa Aaa Aaaaaaaa Aaaaaaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaa Aaaa Aaaaaaa Aaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaa Aa Aaaaaaaaa Aaaaaaaa Aaaa Aaa Aaaaaaaaaaaaaa Aaaaaaaaa Aaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
a Aaaaaaaa Aaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaaaaa Aaa Aaaaaaaaaaa a Aaa Aaa Aa Aaa Aaaaaaaaaaaa Aaaa Aaaaaa Aaaaaaaaa Aaaaa Aaaaaaaaa Aaaaaaa Aaaaaaa Aaaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaa Aa Aaaaaa Aaa Aa Aaaaaaaaaa Aa Aaa Aaaaaaaaaaaa Aaaaaaaaaaa Aa Aaa Aaaaa Aaa Aaaaaaaaa Aaaaaaaaaaaaaaa Aa Aaaaa Aaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaa Aaaaaaaa a Aaaa Aaa Aaaaaaa Aaaa Aaaaaaaaa Aaaaaaaaa Aaaaaa Aa Aaaa Aa Aaaaa Aaa Aaaaaa Aaaaaaaaaaaaaaaa Aaaaa Aaaa Aaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
a Aaaaaaaa Aaaaaaaaaaaaaaa Aaaa Aaaaa Aaaaaa Aaaaaaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaa Aaaa Aaaaaaaaa Aaaaaa Aa Aaaaaa Aaaaaa Aaaaaaa Aaaaaaaaaaaa Aaaaa Aaaaaaa Aaaaa Aaaa Aaaaa Aaaa Aaaa Aaaaaaaaa Aaaaaa a Aaaa Aa Aaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaa Aaaaa Aaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaa Aaa Aaaaaaaaa Aaa Aaaaa Aaa Aaaaaaaaaa Aaaaaaaaaaa
Aaaaaaaaa Aaaa Aaaaaaaaaaaaaa Aaaaaaa a Aaaaaaaaaaaa Aaaaaaa Aaa Aaaaaaaa Aaaaaaa Aaa Aaaaaaaa Aaaaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaa Aaaaaaa Aaaaaaa Aaaaaaaaaaaa Aaaaaaaaa Aaaaaa Aaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaa Aaaa Aaaaaaa Aaaaaaaaaa Aaaaaaa a Aaa Aaaaaaaa Aaaa Aaaaaaaaaaaaa Aaaaaaaaa Aaaaaa Aaaa Aaaaaaaa Aaaaaaa Aa Aaa Aaaaaaa Aaa Aaaa Aaaaaaaa Aaaa Aaaaaa Aaa Aaaaaaaaaaaaaa Aaaaaaaaa Aaa Aaaaaaaaaaaa Aaaaaaaaa Aa Aaa Aaaaaaaaaa Aaaa Aaa Aaaaaa
🔒Multiple reusable audit patterns identified across JSC's bytecode status computation infrastructure, with concrete search targets for variant discovery
Subscribe to read more