Medium CVSS 4.3 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected Safari crash
ComponentJSC B3
Bug ClassType Confusion
Tracker317603
Fix commit7d867192b7ab (WebKit/WebKit) +186/-6
CWECWE-119 (Buffer bounds error)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedOpenAI Codex Security - Amy Burnett
Disclosed2026-08-17

Background

Post-dominator / BackwardsGraph
B is a post-dominator of A if every path from A to program exit passes through B; B3 computes it by reversing the CFG with a synthetic root over all terminals and back-edge sources.
Latch / back-edge source
A block that jumps back to a loop header; an exit-less latch lets control loop forever without reaching other latches.
LICM
Loop-invariant code motion hoists computations out of loops; hoisting a control-dependent memory access is only safe if it truly post-dominates the loop entry.

Root Cause Analysis

This fixes a B3 post-dominator miscomputation that could let loop-invariant code motion (LICM) hoist a control-dependent memory access out of a loop. B3 computes post-dominators via BackwardsGraph, which reverses the CFG and gives a synthetic reverse root a successor for every terminal block AND every back-edge source (latch). The correctness of LICM (and other control-equivalence consumers) depends on the resulting post-dominator relation. Consider a loop whose header has two latches: ‘success’ (which can also exit the loop) and ‘failure’ (an exit-less latch that just jumps back to the header). Control can stay in the loop forever by repeatedly taking the exit-less ‘failure’ latch without ever reaching ‘success’. Therefore ‘success’ must NOT post-dominate the header or the loop entry.

Pre-patch, if an exit-less back-edge source like ‘failure’ was omitted from the synthetic reverse root’s successors, then in the reversed CFG the header was reachable only through ‘success’, so ‘success’ FALSELY post-dominated the header (and the loop entry). B3 LICM would then treat a read guarded by the ‘success’ path as always-executed and hoist that control-dependent read out of the loop, so it runs unconditionally (even when control never legitimately reaches it) — an invalid/out-of-bounds read (bad hoisting).

The fix ensures every back-edge source, including exit-less latches, is a successor of the synthetic reverse root in BackwardsGraph so post-dominance is computed correctly and LICM does not hoist the control-dependent access. The added B3 unit test (testBackwardsDominatorsWithMultipleBackEdges) builds exactly this two-latch loop and asserts ‘success’ does not post-dominate the header/root. (The source change is in B3’s BackwardsGraph/BackwardsDominators; this diff shows the authoritative test that documents the property, per its comment.)

Key insight
B3’s reverse CFG omitted exit-less back-edge sources from the synthetic root, so an exiting latch falsely post-dominated the loop header, letting LICM hoist a control-dependent read out of the loop; adding every latch as a reverse-root successor restores correct post-dominance.

Attack Path

  1. Reach the B3/FTL JIT Run JS that the FTL compiles through B3 with a loop shaped to have two latches, one of them exit-less.
  2. Induce false post-dominance The exit-less latch is omitted from the reverse-root successors, so an exiting latch falsely post-dominates the header.
  3. Hoist a control-dependent read LICM treats a guarded (control-dependent) memory access as always-executed and hoists it out of the loop.
  4. Out-of-bounds read The hoisted access runs unconditionally, performing an invalid/out-of-bounds read and crashing the WebContent process.

Impact Assessment

A JIT miscompilation in the WebContent process: incorrect post-dominance let LICM hoist a control-dependent (guarded) memory access so it executes unconditionally — an out-of-bounds/invalid read. The advisory rates it a crash; bad-hoisting bugs can be shaped into controlled OOB reads.

Changed Functions

FunctionChangeNotes
B3 BackwardsGraph / BackwardsDominators (reverse-root successors)
Source/JavaScriptCore/b3/B3BackwardsGraph.h
modified Includes every back-edge source (including exit-less latches) as a successor of the synthetic reverse root so post-dominance is correct and LICM cannot falsely treat an exiting latch as post-dominating the header. (Fix location per the added test's documentation.)
testBackwardsDominatorsWithMultipleBackEdges
Source/JavaScriptCore/b3/testb3_7.cpp
added Unit test building a two-latch loop (one latch exit-less) and asserting the exiting latch does not post-dominate the header/root.

Files Changed

  • JSTests/wasm/gc/backwards-graph-multi-backedge-licm.js
  • Source/JavaScriptCore/b3/B3Procedure.h
  • Source/JavaScriptCore/b3/testb3.h
  • Source/JavaScriptCore/b3/testb3_1.cpp
  • Source/JavaScriptCore/b3/testb3_7.cpp
  • Source/WTF/wtf/BackwardsGraph.h

Audit Directions

  • Reverse-root successor set
    Audit B3BackwardsGraph for which blocks seed the synthetic reverse root; every terminal and every back-edge source (including exit-less latches) must be included.
  • Control-equivalence consumers
    Review LICM and other post-dominator/control-equivalence users for reliance on the post-dominator relation across irreducible/multi-latch loops.

Original Bug Report

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