[5] [JSC] Move DataView null vector check in IC outside of register save/restore
Severity: High | Component: JSC InlineCacheCompiler | 34669c8
Rated High because the diff fixes an IC handler that pops registers without a matching push, jumping to the polymorphic continuation with a corrupted register file and stack — downstream JIT code then executes against attacker-influenceable register state.
In emitIntrinsicGetter, a pre-push null-vector check shared a JumpList with a post-push out-of-bounds check; the shared link site pop'd registers for both, so the pre-push failure path executed restoreReusedRegistersByPopping without a matching push.
Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp
if (isResizableOrGrowableSharedTypedArrayIncludingDataView(accessCase.structure()->classInfoForCells())) {
+ m_failAndIgnore.append(failAndIgnore);
auto allocator = makeDefaultScratchAllocator(m_scratchGPR);
...
+ CCallHelpers::JumpList postPushFailAndIgnore;
if (isDataView) {
auto [outOfBounds, doneCases] = jit.loadDataViewByteLength(...);
- failAndIgnore.append(outOfBounds);
+ postPushFailAndIgnore.append(outOfBounds);
doneCases.link(&jit);
}
- if (allocator.didReuseRegisters() && !failAndIgnore.empty()) {
- failAndIgnore.link(&jit);
+ if (allocator.didReuseRegisters() && !postPushFailAndIgnore.empty()) {
+ postPushFailAndIgnore.link(&jit);
allocator.restoreReusedRegistersByPopping(jit, preservedState);
m_failAndIgnore.append(jit.jump());
} else
- m_failAndIgnore.append(failAndIgnore);
+ m_failAndIgnore.append(postPushFailAndIgnore);
Patch Details
The pre-push failAndIgnore jumps are appended directly to m_failAndIgnore (no pop). A new postPushFailAndIgnore list collects post-push failures that correctly route through restoreReusedRegistersByPopping.
Misbalanced register-save/restore on a JIT IC failure path: a pre-push failure jump was routed through a post-push pop, desynchronizing the stack.
Background
JSC caches property operations (like get_by_id for byteLength) as small machine-code stubs; on check failure they fall through to m_failAndIgnore. IntrinsicGetterAccessCase specializes built-in getters such as DataView.prototype.byteLength. ScratchRegisterAllocator::preserveReusedRegistersByPushing / restoreReusedRegistersByPopping push reused registers onto the native stack when the stub needs more scratches than free; every exit path between them must either both push and pop, or neither. loadDataViewByteLength emits inline code to read the underlying buffer length and emits an outOfBounds jump for detached/exceeded views.
Analysis
The pre-push null-vector check produced a jump that ended up linked through code that popped reused registers without a matching push, leaving SP offset by the push width and reused callee/scratch registers holding the wrong values.
Aaa Aaaa Aaaa Aaaaa Aa Aaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaa Aaaaaaaaaaaa a Aaaaaaaaa Aaaaaa Aaaa Aa Aaaaaa Aaa Aaaaaa Aaaaaaaaa Aaaaaaa Aaa Aaaaa Aaaaaaa Aaa Aaaa Aaaaaaaaaaaa Aaa Aaaaaaaaa Aaaaaaaaa Aaa Aaaa Aaa Aa Aaaaaa Aaaaaaaaa Aa Aaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaaaaa Aaaaa Aaa Aaaaaaaaaa Aaaa Aaaaaa a Aaaaaaaa Aaaaaaaaaaa Aaaa Aa Aaaaa Aa Aaaa Aaaaaaaaaaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaaaaa a Aaaaaaa Aaa Aaaaaaaa Aaaaaaa Aaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaa Aa Aaaaaaaaa Aaaa Aaaaa Aa Aaaaaaa Aaaaaaa Aa Aaa Aaaaaaaaaaa Aaaaaaaaaaaa Aaaa Aaa Aaaaaaaa Aaaaaaa Aaaaa Aaaaaaa Aaaa Aaaa Aaaaaaaaa Aa Aaaaaaaaa Aaa Aaaaaaaa Aaa Aaaaaaaaa Aaa Aaa Aaaaaaaaaa Aaaaaaaaa Aa Aaaaaaaaaa Aaaaaaaaaaaaa Aaaa Aaaaaaaaa Aaaa Aaa Aaa
🔒The escalation potential of a JIT stack desynchronization bug, and the conditions under which a misbalanced pop becomes more than a crash.
Subscribe to read more
Audit directions
a Aaa Aaaaaa Aaaaaaaaaa Aaaaaaaaaa Aaaaaaa Aaaaa Aaaa Aaaa Aaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaa Aaaaa Aaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaa Aaaaaaaaaaaa Aaaaa Aaa Aaaa Aaaa Aaaa Aaa Aaaaaaaa Aa Aaaa Aaaa Aaaaaa
a Aaaaaa Aaaaaaaaa Aaaa Aaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaa Aaaaaa Aaaaa Aaaa Aaaaaa Aa Aaaa Aaaaa Aaa Aaaaaaa Aaaaaaa Aaa Aaaaaaaa Aaaa Aaa Aaaa
a Aaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaa Aaaaa Aaaaa Aaaaaaaa Aaaaaaaaaaaa Aaaaaaaaaaa Aaa Aaaaaaa
a Aaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaa Aaaaaaaaa Aaa Aaaaaaaaaaa Aa Aaaaaaaaaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaa Aa a Aaaaaaaaa Aaa Aaaaa Aaaaaa Aa Aaa Aaaaa Aaaa Aa a Aaaaaaaaaaaaa Aaaaaaaaa
🔒Multiple reusable audit patterns identified for JIT register-save discipline, with specific JSC compilation paths as starting points.
Subscribe to read more