Medium CVSS 4.3 webkit OOB 🔧 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
ComponentThirdParty ANGLE
Bug ClassOOB
Tracker310527
Fix commitcf2e67ecb913 (WebKit/WebKit) +35/-81
CWECWE-20 (Improper input validation)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedVitaly Simonovich
Disclosed2026-05-11

Background

Provoking vertex
The vertex whose attributes are used for flat-shaded primitives; ANGLE rewrites index buffers on Metal to emulate GL provoking-vertex semantics.
Index vs primitive count
For each primitive mode (points/lines/strips/triangles/fans) there is a fixed relation between index count and primitive count used to size buffers.
Index-buffer rewrite
ANGLE builds a new Metal index buffer; its size must match how it is later indexed, or accesses go out of bounds.
ANGLE Metal backend
The translation layer that implements WebGL/GLES on Apple’s Metal API.

Root Cause Analysis

ANGLE’s Metal backend rewrites index buffers for provoking-vertex handling (ProvokingVertexHelper). The pre-patch code converted between index counts and primitive counts with two hand-rolled per-mode helpers, primCountForIndexCount() and indexCountForPrimCount(), that switched on a packed fixIndexBufferKey mode and did unchecked integer arithmetic (indexCount/2, indexCount-1, primCount*3, casts through int/uint). Those computations size and index the rewritten Metal index buffer, so an inconsistent or wrapped count (from a crafted draw with an unusual mode/count, or the two directions disagreeing) yields a buffer sized differently from how it is later indexed – an out-of-bounds access during the index-buffer fixup, surfacing as a GPU/WebContent process crash.

The fix replaces both helpers with a single resolveIndexedDrawRewriteInfo(gl::PrimitiveMode mode, GLsizei count) that returns a coherent {primitiveCount, newIndexCount, newPrimitiveMode} struct computed once from the GL draw parameters, so the primitive count, the rewritten index count, and the mode are derived together and cannot disagree. [Inference] The exact overflow/mismatch input is not spelled out by the diff; what the patch establishes is that the fragile dual-direction count arithmetic is consolidated into one bounded computation, removing the count-mismatch that led to the OOB. This is reached through WebGL draw calls that hit the Metal provoking-vertex index-rewrite path.

Key insight
Two independent hand-rolled index<->primitive count conversions could disagree or overflow, so the Metal index-rewrite buffer was sized inconsistently with how it was indexed; deriving all counts together in one function removes the mismatch.

Attack Path

  1. Use WebGL on Metal Run WebGL content on an Apple/Metal ANGLE backend that uses ProvokingVertexHelper to rewrite index buffers.
  2. Issue a crafted indexed draw Call an indexed draw with a primitive mode and index count chosen so the per-mode index<->primitive count arithmetic miscomputes or the two directions disagree.
  3. Mis-size the rewrite buffer [inference] The rewritten Metal index buffer is allocated/indexed from an inconsistent count, so writes/reads fall outside it.
  4. Out-of-bounds / crash The index-buffer fixup accesses out of bounds, corrupting memory or crashing the GPU/WebContent process.

Impact Assessment

An out-of-bounds access in ANGLE’s Metal index-buffer rewrite, reachable from crafted WebGL indexed draws, in the GPU/WebContent process. The demonstrated effect is a process crash; whether it yields a controlled corruption primitive depends on the specific count mismatch, which the diff does not fully expose (inference). Confined to the GPU/WebContent process. Rated medium.

Changed Functions

FunctionChangeNotes
resolveIndexedDrawRewriteInfo (replaces primCountForIndexCount / indexCountForPrimCount)
Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm
modified Consolidates the index<->primitive count conversions into one function returning a coherent {primitiveCount, newIndexCount, newPrimitiveMode}, so the counts used to size and index the rewritten Metal index buffer are derived together and cannot disagree/overflow.

Files Changed

  • Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm

Audit Directions

  • Other count arithmetic in the Metal backend
    grep ANGLE metal/ for per-primitive-mode count math (count/2, count-1, *3) that sizes buffers without a single coherent computation or overflow check.
  • Index-buffer sizing vs indexing
    Audit index-rewrite/line-loop/triangle-fan expansion paths to ensure the allocated size and the write/read loop use the same derived count.
  • Draw-parameter validation
    Review where GL draw count/mode reach the Metal rewrite to confirm bounds/mode validation before the conversion.

Original Bug Report

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