Medium CVSS 8.8 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to memory corruption
ComponentJSC DFG
Bug ClassType Confusion
Tracker282661
Fix commit2d5e29d47324 (WebKit/WebKit) +17/-1
CWECWE-843 (Type confusion)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGary Kwong
Disclosed2024-12-11

Background

Backwards propagation / usage flags
A DFG phase that records how values are used (NodeBytecodeUsesAsNumber/AsOther/…) to guide later representation and conversion choices.
SpecOther
The speculated type for ‘other’ primitives (null/undefined); UsesAsOther is only meaningful when the operand can be SpecOther.
ToString / CallStringConstructor
DFG nodes for String() coercion whose operand-usage flags feed downstream optimization.

Root Cause Analysis

This fixes an incorrect backward-propagation of usage flags for ToString/CallStringConstructor in the DFG that could mislead value-representation decisions into a type confusion. DFGBackwardsPropagationPhase walks the graph backward to record how each value is used (NodeBytecodeUses* flags), which downstream phases consult to pick number/other representations and conversions. For ToString and CallStringConstructor, the pre-patch code unconditionally merged NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity onto the operand (child1). Marking the operand as UsesAsOther even when its use kind cannot actually be an ‘other’ (null/undefined, SpecOther) type feeds an inconsistent usage signal into later optimization: the representation/conversion chosen for the operand based on these flags becomes inconsistent with how the value is really produced/consumed, and that mismatch is exploitable as a type confusion (a value handled as the wrong representation), which the advisory rates as memory corruption.

The fix gates the UsesAsOther flag on the operand actually being able to be SpecOther: if (typeFilterFor(node->child1().useKind()) & SpecOther) node->child1()->mergeFlags(NodeBytecodeUsesAsOther); and always merges UsesAsNumber | NeedsNaNOrInfinity.

The restored invariant is that the UsesAsOther usage flag is propagated only when the operand’s use kind admits an ‘other’ type, so downstream representation choices are consistent. INFERENCE: the precise downstream miscompilation that turns the wrong flag into a corrupting type confusion is not contained in this one-hunk diff; the patch establishes the incorrect unconditional UsesAsOther propagation as the root cause.

Key insight
ToString/CallStringConstructor unconditionally marked their operand as UsesAsOther even when it could not be an ‘other’ type, feeding inconsistent usage flags into representation choices; gating the flag on SpecOther fixes the miscompilation.

Attack Path

  1. Reach the DFG Run JS with a ToString/String() over a value whose DFG use kind cannot be an ‘other’ type.
  2. Mis-propagate UsesAsOther Backward propagation unconditionally marks the operand UsesAsOther, an inconsistent usage signal.
  3. Choose a wrong representation A later phase picks a value representation/conversion based on the incorrect flags.
  4. Type confusion The value is handled as the wrong representation, a memory-corruption primitive in the WebContent process (inferred escalation).

Impact Assessment

A DFG usage-flag miscompilation in the WebContent process that the advisory rates as memory corruption via type confusion. The shown change corrects the flag propagation; the concrete corrupting path downstream is not in this diff, so the demonstrated defect is an incorrect optimization input rather than a fully-shown write primitive, though the class (JSC type confusion) is high-value.

Changed Functions

FunctionChangeNotes
BackwardsPropagationPhase (ToString / CallStringConstructor)
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
modified Merges NodeBytecodeUsesAsOther only when typeFilterFor(child1 useKind) & SpecOther, instead of unconditionally, so the usage flag matches the operand's possible types.

Files Changed

  • JSTests/stress/string-add-conversion-unused.js
  • Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp

Audit Directions

  • Unconditional usage-flag merges
    Audit DFGBackwardsPropagationPhase for other nodes that merge NodeBytecodeUsesAsOther/AsNumber unconditionally regardless of the operand’s use kind / possible types.
  • Flag-driven representation
    Trace consumers of NodeBytecodeUsesAsOther to confirm they tolerate (or the producers correctly gate) the flag on SpecOther.

Original Bug Report

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