CVE-2025-43536
Overview
Background
- CodeBlock jettison
- JSC’s action of discarding optimized bytecode/JIT code when it is invalidated or reoptimized, tearing down associated metadata.
- StructureStubInfo
- Per-inline-cache metadata for property access; reset() returns it to an uncached state, deref() releases a reference to it.
- ConcurrentJSLocker
- The lock guarding concurrent access to CodeBlock state between the mutator and compiler threads.
Root Cause Analysis
This fixes a use-after-free during CodeBlock jettison in JavaScriptCore’s inline-cache teardown. CodeBlock::jettison() throws away optimized/older code; under the ConcurrentJSLocker it iterated every StructureStubInfo (the per-inline-cache metadata for get/put/in operations) and called stubInfo.reset(locker, this). reset() re-initializes the stub back to its uncached state, which touches structures, watchpoints and the owning CodeBlock (passed as this) — objects that during jettison may already be undergoing teardown, so re-initializing the stub there dereferences state that is being destroyed. The one-line fix replaces stubInfo.reset(locker, this) with stubInfo.deref(), so jettison simply releases the stub’s reference (it is reference-counted) rather than resetting and re-touching now-fragile CodeBlock/structure state.
The restored invariant is that jettison only drops ownership of its inline-cache stubs and does not walk into their reset path during code-block teardown. Because the diff is a single call-site change, the exact object whose lifetime was violated is inferred from the reset(locker, this) signature (it re-enters CodeBlock/structure state); the patch clearly establishes that resetting stubs at jettison time was unsafe and dereferencing/releasing is the correct action.
Attack Path
- Trigger tiered compilation Run JS that builds inline caches (StructureStubInfos) in an optimized CodeBlock.
- Force a jettison Cause reoptimization/invalidation so CodeBlock::jettison() runs and iterates the stub infos.
- Re-enter fragile state reset(locker, this) re-initializes each stub, touching CodeBlock/structure state already being torn down — a use-after-free.
- Crash or corrupt The dangling access crashes or corrupts JSC heap state in the WebContent process.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
CodeBlock::jettisonSource/JavaScriptCore/bytecode/CodeBlock.cpp |
modified | In the forEachStructureStubInfo loop, replaces stubInfo.reset(locker, this) with stubInfo.deref(), releasing the stub reference instead of re-initializing it during jettison. |
Files Changed
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Audit Directions
- Other jettison/teardown loopsGrep CodeBlock.cpp and JIT teardown for reset(locker, this) or similar re-initialization calls during destruction/jettison where a deref/clear is the safe action.
- StructureStubInfo lifetimeReview all StructureStubInfo::reset callers to ensure the owning CodeBlock and referenced structures are fully live at reset time.