Medium CVSS 7.8 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
7.8
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionA type confusion issue could lead to memory corruption
ComponentWebCore Platform/Audio
Bug ClassType Confusion
Tracker286694
Fix commitc1b04541303e (WebKit/WebKit) +171/-111
CWECWE-843 (Type confusion)
CVSS vectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle V8 Security Team
Disclosed2025-05-12

Background

Denormal (subnormal) floats
Very small floating-point values near zero; processing them is slow, so audio code flushes them to zero via CPU mode bits.
FP status/control word (MXCSR / FPCR)
The per-thread register controlling FP behavior, including flush-to-zero (FTZ) and denormals-are-zero (DAZ); changing it alters arithmetic semantics for all subsequent FP ops on that thread.
AudioWorklet
A WebAudio feature that runs author-supplied JavaScript on the real-time audio rendering thread, where DenormalDisabler governs the FP environment.
JIT FP soundness
The DFG/FTL constant-fold and range-analyze floating-point assuming IEEE-754; if the runtime FP mode differs (FTZ/DAZ), runtime results can diverge from compile-time assumptions.
RAII scoping
Acquiring/releasing the FP mode in a constructor/destructor so it is changed and restored exactly, preventing leakage beyond the intended region.

Root Cause Analysis

OBSERVED (from the diff): DenormalDisabler is an RAII guard used around WebAudio rendering to put the CPU floating-point environment into flush-to-zero / denormals-are-zero mode (denormals badly hurt audio DSP performance). The pre-patch implementation defined the guard only for OS(WINDOWS) && COMPILER(MSVC) or COMPILER(GCC_COMPATIBLE) && defined(__SSE__) (x86), wrapping the whole class in #ifdef HAVE_DENORMAL; on ARM (Apple Silicon / iOS / iPadOS) HAVE_DENORMAL was undefined, so there was effectively no working, correctly-scoped denormal control on Apple’s primary architecture. Its constructor unconditionally OR’d flush bits into the status word (setCSR(m_savedCSR | 0x8040/0x8000)) and the destructor wrote back m_savedCSR, with x86 detection done via inline stmxcsr/ldmxcsr and an fxsave-based DAZ probe.

The fix rewrites it: it reads the status word once (readStatusWord: stmxcsr on x86, mrs FPCR on ARM64, vmrs FPSCR on ARM), records m_disablingActivated = areDenormalsEnabled(m_savedCSR), changes the mode ONLY when denormals were actually enabled, and in the destructor restores the exact saved word only if it changed it; HAVE_DENORMAL moves into PlatformHave.h for X86_SSE2/ARM/ARM64 and a manual flushDenormalFloatToZero fallback covers platforms without hardware support. The net effect is a precisely-scoped, save-exactly/restore-exactly FP-environment guard that is correct on ARM as well as x86. INFERENCE (mechanism, not shown by the diff): the security significance is the interaction between this non-IEEE FP mode and JIT-compiled JavaScript. AudioWorklet executes author JS on the audio rendering thread where the denormal guard is active, and the DFG/FTL JIT constant-folds and range-analyzes floating-point operations assuming standard IEEE-754 semantics. If the flush-to-zero/denormals-are-zero mode is left active, mis-scoped, or (on ARM) uncontrolled while JIT-compiled JS runs, runtime FP results (denormals becoming zero, changed comparisons) diverge from the values the optimizer proved at compile time, breaking a JIT soundness invariant; such a divergence can be turned into a type confusion where a value the compiler treated as a specific type/shape differs at runtime, leading to memory corruption.

The patch removes that divergence by making the FP-mode change tightly scoped and architecture-correct so it cannot bleed into JIT-compiled code with mismatched assumptions.

Key insight
The bug is an FP-environment scoping problem: WebAudio’s denormal guard flushed denormals to zero (and was absent/uncontrolled on ARM), and that non-IEEE FP mode could bleed into JIT-compiled JavaScript on the audio thread, breaking the optimizer’s floating-point assumptions into a type confusion. The fix makes the mode change precisely saved/restored and architecture-correct.

Attack Path

  1. Set up a WebAudio graph with AudioWorklet Create an AudioContext and register an AudioWorkletProcessor so attacker JavaScript runs on the audio rendering thread, where DenormalDisabler controls the FP environment.
  2. Induce an FP-mode mismatch [inference] Rely on the flush-to-zero/denormals-are-zero mode being active (or, on ARM, uncontrolled) while JIT-compiled JS on that thread executes floating-point the DFG/FTL folded assuming IEEE semantics.
  3. Diverge runtime from compile-time FP [inference] Craft FP computations (denormal-producing arithmetic, comparisons against tiny values) whose runtime results under flush-to-zero differ from the constant-folded/range-analyzed values the JIT baked in.
  4. Break a JIT invariant into type confusion [inference] Use the divergence so a value the optimizer proved to be a given type/shape (or an index proved in-bounds) is different at runtime — a type confusion.
  5. Corrupt memory [inference] Escalate the type confusion to out-of-bounds or confused-object read/write in the WebContent process.

Impact Assessment

The patch itself is a correctness/scoping fix to the audio FP-environment guard (precise save/restore, only-when-needed, and a previously-absent ARM implementation). Its security weight — reflected in the advisory’s ’type confusion could lead to memory corruption’ — comes from the inferred interaction between a mis-scoped flush-to-zero FP mode and JIT-compiled JavaScript (notably AudioWorklet on the same thread), where an FP-semantics mismatch can break JIT soundness into a type confusion and thence memory corruption. That exploitation chain is reasoned inference, not shown by the diff; what the diff establishes is the removal of the FP-mode divergence. Confined to the WebContent process. Rated medium (CVSS per NVD).

Changed Functions

FunctionChangeNotes
DenormalDisabler::DenormalDisabler / ~DenormalDisabler
Source/WebCore/platform/audio/DenormalDisabler.cpp
added New out-of-line RAII implementation: reads the FP status word (MXCSR/FPCR/FPSCR), sets flush-to-zero only when denormals were enabled (m_disablingActivated), and restores the exact saved word in the destructor — including a correct ARM/ARM64 implementation.
readStatusWord / setStatusWord / areDenormalsEnabled
Source/WebCore/platform/audio/DenormalDisabler.cpp
added Per-architecture FP status-word accessors (stmxcsr/ldmxcsr on x86, mrs/msr FPCR on ARM64, vmrs/vmsr FPSCR on ARM) and a helper to test whether denormals are currently enabled.
DenormalDisabler (class) / flushDenormalFloatToZero
Source/WebCore/platform/audio/DenormalDisabler.h
modified Removes the x86/Windows-only #ifdef gating and inline asm, declares the ctor/dtor out-of-line, and keeps a manual flush fallback for !HAVE(DENORMAL).
HAVE_DENORMAL definition
Source/WTF/wtf/PlatformHave.h
modified Defines HAVE_DENORMAL for X86_SSE2/ARM/ARM64 so denormal control exists and is consistent on Apple's ARM platforms, not just x86.

Files Changed

  • LayoutTests/platform/ios/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-denormals.https.window-expected.txt
  • LayoutTests/platform/mac/TestExpectations
  • LayoutTests/webaudio/audoworklet-denormal-float-values-expected.txt
  • LayoutTests/webaudio/audoworklet-denormal-float-values.html
  • Source/WTF/wtf/PlatformHave.h
  • Source/WebCore/Sources.txt
  • Source/WebCore/WebCore.xcodeproj/project.pbxproj
  • Source/WebCore/platform/audio/DenormalDisabler.cpp
  • Source/WebCore/platform/audio/DenormalDisabler.h

Audit Directions

  • Other FP-mode changers
    grep for MXCSR/FPCR/FPSCR access (stmxcsr/ldmxcsr, mrs/msr FPCR, _controlfp) and rounding/flush-mode changes anywhere reachable from a thread that also runs JIT-compiled JS (audio, WebGL, workers).
  • AudioWorklet thread FP invariants
    Audit the AudioWorklet render path for places where author JS executes while a non-default FP environment is active, and confirm the environment is IEEE (or restored) before JIT-compiled JS runs.
  • RAII scope leaks
    Review DenormalDisabler use sites (and similar scoped-mode guards) for early returns, exceptions, or nested/threaded scopes where the mode could outlive the guard.

Original Bug Report

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