[8] GetByStatus walks prototype chain for direct/private property opcodes
Severity: Medium | Component: JSC bytecode IC status + DFG | b07dca9
Rated Medium because the diff repairs a JIT IC status helper that allowed DFG to specialise GetByIdDirect/GetPrivateNameById under prototype-walk assumptions; whether this becomes a controlled property fetch from a non-own slot depends on downstream lowering that the diff does not establish in isolation.
When computing the GetByStatus, the property lookup should be checked for direct property access before doing a prototype walk, since direct accesses are not supposed to consult the prototype.
Source/JavaScriptCore/bytecode/GetByStatus.cpp
-GetByStatus GetByStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, CacheableIdentifier identifier)
+GetByStatus GetByStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, CacheableIdentifier identifier, GetByStatus::LookupMode mode)
{
- // Note that this code is also used for GetByIdDirect since this function only looks
- // into direct properties. When supporting prototype chains, we should split this for
- // GetById and GetByIdDirect.
...
- if (auto result = attempToFold())
- return result.value();
+ // We should do a prototype walk searching for the property only if this
+ // is a normal access. Don't consult proto for for direct accesses.
+ if (mode == GetByStatus::LookupMode::Normal) {
+ if (auto result = attempToFold())
+ return result.value();
+ }
Source/JavaScriptCore/dfg/DFGNode.h
+ GetByStatus::LookupMode propertyLookupMode()
+ {
+ switch (op()) {
+ case GetByIdDirect:
+ case GetByIdDirectFlush:
+ case GetPrivateNameById:
+ return GetByStatus::LookupMode::Direct;
+ case GetById:
+ case GetByIdFlush:
+ case GetByIdMegamorphic:
+ return GetByStatus::LookupMode::Normal;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
Patch Details
A new LookupMode enum (Normal/Direct) is added to GetByStatus and threaded through computeFor. The prototype-walk inside computeFor (the attempToFold() block) is now gated on mode == LookupMode::Normal. Node::propertyLookupMode() maps DFG opcodes to the correct mode. DFGAbstractInterpreterInlines.h::executeEffects and DFGConstantFoldingPhase::foldConstants now derive the mode from the node. op_get_from_scope in DFGByteCodeParser is explicitly pinned to Normal because global property lookup is supposed to walk the global object's prototype chain. The stale comment claiming the function only looks at direct properties is removed.
Speculation-soundness violation in the JIT IC status computation: a shared helper applies prototype-chain semantics to opcodes whose runtime semantics forbid prototype traversal.
Background
GetByStatus is JSC's summary of what a GetById-family bytecode has done at runtime: observed structures, offsets, and prototype walks, so the DFG can decide whether to inline a load, constant-fold a result, or fall back to a generic IC. GetById performs a full ECMAScript [[Get]] which walks the prototype chain. GetByIdDirect performs an own-property-only access; it must return undefined if the property is not own. GetPrivateNameById reads a private class field, keyed by a brand on the receiver, strictly own-property by spec. attempToFold inside computeFor is the proto-walk helper that searches the chain for the property and folds it into a Simple variant when found. The DFG's AbstractInterpreter and ConstantFoldingPhase consume the returned GetByStatus to specialise the IR.
Analysis
GetByStatus::computeFor always invoked attempToFold(), which walked the prototype chain. It was called from DFG passes for every GetBy* node, including GetByIdDirect, GetByIdDirectFlush, and GetPrivateNameById — opcodes whose runtime semantics require own-property-only access. The stale comment claimed the function only looked at direct properties, which was true when written but became false once attempToFold was added.
Aaa Aaaaaaa Aaa Aaaaa Aaaa Aa Aaaaaaaaaa a Aaaaaaaaaaaaaaa Aaaa Aa Aa Aa Aaa Aaaaaaaa Aa Aaa Aaaaaaaaaa Aaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaa Aaaaaaaaaaaaaaaa Aaaaaa Aa Aaa Aaaaaaaaa Aaaaaaaa Aaaa Aaaaaa Aaaa Aaaaaaaaaa Aaa Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aa Aaa Aaa Aaaaaaaaaaaa Aaaaa Aaaa Aaaa Aaaa Aaaa Aaaaaaaaa Aaaaaaaaaaaaaaaa Aa Aaaaaaaaaaa a Aaaaaa Aaa Aaaaaaaaa Aaaa Aaaaa Aaaaaa a Aaaaaaaaa Aaaa Aaaa Aaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaa Aa Aaaaa Aaaaa Aaa Aaaaaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaa Aaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaa Aaaaaaaaaa Aaaaaaaa Aaaaa Aaaaaaa a Aaaaaaaaaa Aaaaaaaaa Aaaaaa Aaa Aaaaaaaaaaa Aaaaaa Aaaa a Aaaaaaaa Aaaaaaaaa Aaaaaa Aa Aaaaaaa Aaaaaaaaaaaaa Aa Aa a Aaaaaaaaaa Aaaaaaaa Aaaaa Aaaa a Aaaaaaa Aaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaaa Aaa Aaaaaaaaa Aa Aaa Aaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaa Aaaaaaaaa Aaaaa Aaaaaaaa Aa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaa Aa Aaaaaaaaa Aaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaa Aaa Aaaaaaa Aaaa Aaaaaaa Aaa Aaa Aa Aaaaa a Aaaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaa a Aaaaaaaa Aaaaaaaaaa Aaaaa Aaa Aaaaaaaaa Aaaaaaaaaa Aaaaa Aaaaaaaa Aaa a Aaaaaaaaa Aaaaaa Aa Aaaaaa Aaa Aaaaaaaaaaa Aaaaa Aaa Aaa Aaaaaaa Aaaaaaaaa Aaaaaaaaa Aaa Aaaaaaaaaa Aaaaaaaaa Aa Aaa Aaaa Aa Aaa Aaaaaaaa Aaa Aaaaaaaaaaaaaa Aaa Aaaaa Aaaaa Aaaaaaa Aaaaaaaa Aaaaaa Aaa Aaaaaaa Aa Aaa Aaaa Aaaaa Aaaa Aaaaaaaa Aa Aaa Aaaaaaaa Aaaaaaaaa Aaa Aaaaaaaaaaaa Aa Aa Aaaaaaaa Aaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaa Aa Aaa Aaaaaaa Aaaaaaaaaaa Aaaaa Aaa Aaaaaaaa Aaaaaa Aaaa Aaaaaaa Aaa Aaaaaa Aaaaaaaaa Aa Aaa Aaaa Aaaaaaaaa
🔒The speculation-soundness implications of conflating own-property and prototype-walking semantics in a shared JIT helper, and the conditions under which this can escalate beyond a pure correctness bug
Subscribe to read more
Audit directions
a Aaaaaaaa Aaaaaaaaa Aaaaaaa Aaaa Aaaaaaa Aaaaaa Aaa Aaaaaa Aaaaaaaa Aaaaaaaaa Aaa Aaaaaa Aa a Aaaaaaa Aaaaaa Aaaa Aaaaaaaaa Aaaaaaaaaaaa Aaaaa Aaaaa Aaa Aaaaaa Aaaaaaaaa a Aaaaaaaaaaaaaa Aaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa a Aaa Aaa Aaaa Aaaaaa a Aaaaaa Aaaaaaaaaaaa Aaaaaaaa Aaaaaaaa Aa Aaaa Aaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaa Aaa Aaaaa Aaaaaaa a Aaaa Aaaaaaaaaa Aaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaa
a Aaaaaaaaaaaaaa Aaaaaaa Aaaaaaa Aaaaaaaa Aaaaa Aaaa Aaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaa Aa Aaaa Aaaa Aaa Aa Aaaaaaaa Aaa Aaa Aaaaaa Aaaa Aaaaaaaa Aaa Aaaaaaaaa Aaaaaa Aaaa Aaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaa Aaaaaa Aaaa Aaaaaa Aaaaaaaaaaaa Aaaaaaa Aa Aaaaaaa
a Aaaaaaa Aaaaaaaa Aaaaaaaaaaa a Aaaaaaaa Aaaaaaaa Aaaaaa Aaaa Aaa Aaaaaa Aaa Aaaaaaaaaaa Aaaa Aaaaaaaaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaa Aaaa Aaaaa Aaaaaaaa Aaaa Aaaa Aa a Aaaaa Aaaaaa a Aaaaa Aaaaaaaa a Aaaaa Aaaa Aaa Aaaaaa Aaa Aaaaaaa Aaaa Aaaaaaaa Aaaa Aaaa Aa
a Aaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaa Aaa Aaaaaaaa Aaaaaaa Aaaa Aaa Aaaaa Aaa Aaa Aaaaaaa Aaaaaaa a Aaa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaa Aaaaa Aa Aaaaaaa Aa a Aaa Aaaaaa Aa Aaaaa Aaaaaaa Aaaaaaaa Aaa Aaaaaaa Aaaaa Aaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaa Aa Aaa Aaaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaa Aaa Aaaaa Aaaaa Aaaa Aaaaa Aaaaaaa Aaaaa Aaaaaaa
🔒Several reusable audit patterns identified across JSC's IC status computation layer, with concrete starting points for finding variants in sibling status helpers
Subscribe to read more