Medium CVSS 4.3 webkit UAF 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected process crash
ComponentJSC Bytecode
Bug ClassUAF
Tracker301726
Fix commit1025bd18c9c7 (WebKit/WebKit) +1/-1
CWECWE-416 (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
CreditedNan Wang (@eternalsakura13)
Disclosed2025-12-12

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.

Key insight
Jettison was resetting each inline-cache stub — re-entering CodeBlock/structure state that is already being destroyed — when it should simply release the stub’s reference; reset-at-teardown was the use-after-free.

Attack Path

  1. Trigger tiered compilation Run JS that builds inline caches (StructureStubInfos) in an optimized CodeBlock.
  2. Force a jettison Cause reoptimization/invalidation so CodeBlock::jettison() runs and iterates the stub infos.
  3. Re-enter fragile state reset(locker, this) re-initializes each stub, touching CodeBlock/structure state already being torn down — a use-after-free.
  4. Crash or corrupt The dangling access crashes or corrupts JSC heap state in the WebContent process.

Impact Assessment

A use-after-free confined to the WebContent process, reachable by driving inline-cache creation and forcing jettison. Teardown-time UAFs in JSC metadata are exploitable with grooming, though this particular site (releasing vs resetting a stub during jettison) is a narrower primitive than a direct object-reuse bug; the advisory rates it a process crash.

Changed Functions

FunctionChangeNotes
CodeBlock::jettison
Source/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 loops
    Grep 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 lifetime
    Review all StructureStubInfo::reset callers to ensure the owning CodeBlock and referenced structures are fully live at reset time.

Original Bug Report

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