Medium CVSS 7.5 webkit Integer Overflow 🔧 Commit mapped

Overview

Medium
Severity
7.5
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected process crash
ComponentJSC YARR
Bug ClassInteger Overflow
Tracker309601
Fix commit7663d811d06c (WebKit/WebKit) +347/-29
CWECWE-119, CWE-120 (Buffer bounds error, Buffer overflow)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedLuka Rački
Disclosed2026-05-11

Background

YARR
JavaScriptCore’s regular-expression engine that compiles patterns to bytecode/JIT with a backtracking model.
Backtracking call frame
Per-match stack space YARR reserves to store backtracking state; its size is computed from the pattern structure.
CheckedUint32 / Checked<unsigned>
WTF integer wrappers that record overflow so it can be detected instead of silently wrapping.
FrameTooLarge (new)
The error code the fix returns to reject a pattern whose backtracking frame size overflows 32 bits.

Root Cause Analysis

During YARR (JavaScriptCore’s regexp engine) pattern compilation, setupAlternativeOffsets/setupDisjunctionOffsets compute the size of the backtracking call frame a regexp needs, accumulating per-construct stack space (e.g. YarrStackSpaceForBackTrackInfoParentheticalAssertion and similar) as a plain unsigned. For a sufficiently large or deeply nested pattern, this running total can exceed 2^32 and wrap around, so the computed newCallFrameSize is far smaller than the space the compiled matcher will actually use. The compiler then sizes the backtracking frame from the wrapped-small value while the matcher indexes it as if it were the true (large) size, an out-of-bounds access of the backtracking stack frame — memory corruption / crash.

The fix changes the call-frame-size accumulators to CheckedUint32 (currentCallFrameSize, initialCallFrameSize, perAlternativeInitial, currentAlternativeCallFrameSize, ignoredCallFrameSize) and, at every accumulation point, returns the new ErrorCode::FrameTooLarge when hasOverflowed() is true, so an over-large pattern is rejected at compile time instead of producing an undersized frame; a TooManyCaptures error code is likewise added. Complementary hardening in AssemblerBuffer.h switches capacity growth to Checked<unsigned> and compares indices as 64-bit to avoid analogous overflow in the code buffer.

The restored invariant is that the regexp backtracking frame size is computed with overflow checking and any pattern whose frame would overflow 32 bits is rejected rather than compiled with a truncated size.

Key insight
YARR accumulated the regexp backtracking call-frame size in a plain unsigned that could overflow, producing an undersized frame the matcher then over-indexed; computing it with CheckedUint32 and rejecting overflow (FrameTooLarge) restores safety.

Attack Path

  1. Craft an over-large regexp Construct a pattern (deeply nested groups/assertions/alternations, or very many captures) whose accumulated backtracking call-frame size exceeds 2^32.
  2. Compile it Have web content compile the RegExp (new RegExp / literal), driving setupAlternativeOffsets/setupDisjunctionOffsets to accumulate the frame size in a plain unsigned.
  3. Overflow the frame size The unsigned accumulation wraps to a small value, so newCallFrameSize is far smaller than the matcher actually needs.
  4. Out-of-bounds backtracking Executing a match allocates the undersized frame but indexes it at the true offsets, reading/writing out of bounds of the backtracking stack — corruption or crash in WebContent.

Impact Assessment

An integer-overflow in regexp backtracking-frame sizing that yields an undersized frame indexed at full offsets — an out-of-bounds read/write on the backtracking stack in the WebContent process. It is reachable directly from a crafted RegExp in web content; the demonstrated effect is a crash, but a controlled frame-size mismatch is a plausible corruption primitive. Rejecting over-large patterns removes it. Rated medium.

Changed Functions

FunctionChangeNotes
YarrPatternConstructor::setupAlternativeOffsets
Source/JavaScriptCore/yarr/YarrPattern.cpp
modified currentCallFrameSize/newCallFrameSize become CheckedUint32; every accumulation checks hasOverflowed() and returns ErrorCode::FrameTooLarge.
YarrPatternConstructor::setupDisjunctionOffsets
Source/JavaScriptCore/yarr/YarrPattern.cpp
modified initialCallFrameSize/callFrameSize/perAlternativeInitial/currentAlternativeCallFrameSize become CheckedUint32 with overflow checks before use of .value().
errorMessage / errorToThrow (+ ErrorCode)
Source/JavaScriptCore/yarr/YarrErrorCode.cpp
modified Adds FrameTooLarge and TooManyCaptures error codes and their thrown messages so over-large patterns fail cleanly.
AssemblerBuffer grow/putIntegral
Source/JavaScriptCore/assembler/AssemblerBuffer.h
modified Uses Checked<unsigned> for capacity growth and 64-bit index comparisons to prevent analogous integer overflow in the code buffer.

Files Changed

  • JSTests/stress/regexp-alternative-heavy.js
  • JSTests/stress/regexp-bol-optimize-out-of-stack.js
  • JSTests/stress/regexp-combined-large.js
  • JSTests/stress/regexp-deep-nested.js
  • JSTests/stress/regexp-heavy-mixed.js
  • JSTests/stress/regexp-lookahead-heavy.js
  • JSTests/stress/stack-overflow-regexp.js
  • LayoutTests/js/script-tests/stack-overflow-regexp.js
  • LayoutTests/js/stack-overflow-regexp-expected.txt
  • Source/JavaScriptCore/assembler/AssemblerBuffer.h
  • Source/JavaScriptCore/yarr/YarrErrorCode.cpp
  • Source/JavaScriptCore/yarr/YarrErrorCode.h
  • Source/JavaScriptCore/yarr/YarrParser.h
  • Source/JavaScriptCore/yarr/YarrPattern.cpp
  • Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp

Audit Directions

  • Other unchecked size accumulation in YARR
    grep yarr/ for unsigned running totals of offsets/sizes (input positions, frame slots, capture counts) added in loops without Checked/hasOverflowed().
  • Consumers of call-frame size
    Audit the JIT/interpreter backends that allocate and index the backtracking frame to ensure they use the same checked size and honor FrameTooLarge.
  • Assembler buffer growth
    Review other AssemblerBuffer/CodeBuffer growth and index arithmetic for 32-bit overflow like the ones hardened here.

Original Bug Report

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