Medium CVSS 7.5 webkit OOB 🔧 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
ComponentThirdParty ANGLE
Bug ClassOOB
Tracker311631
Fix commita9f9b9ecfd4b (WebKit/WebKit) +63/-3
CWECWE-119 (Buffer bounds error)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CISA KEVNot listed
Creditedan anonymous researcher
Disclosed2026-05-11

Background

Block-compressed texture format
Formats like ETC/ETC2 store fixed-size blocks covering multiple texels, so pitch is block-based, not pixelBytes*width.
Row/depth pitch
Byte stride between rows/slices of texture data; must match the format layout or copies go out of bounds.
ANGLE Metal backend
Implements WebGL/GLES on Apple Metal, including texture sub-image uploads.
ANGLE_CHECK_GL_MATH
Overflow-checked arithmetic used when computing compressed image pitches.

Root Cause Analysis

ANGLE’s Metal backend uploads sub-image texture data in TextureMtl::convertAndSetPerSliceSubImage. It computed the destination row and depth pitch as dstRowPitch = dstFormat.pixelBytes * mtlArea.size.width and dstDepthPitch = dstRowPitch * mtlArea.size.height. That formula is correct only for uncompressed (per-pixel) formats. For BLOCK-compressed formats (e.g. ETC/ETC2), data is laid out in fixed-size blocks covering several texels, so pixelBytes*width drastically underestimates the true row pitch; using that too-small pitch to index/copy the compressed sub-image writes and reads outside the allocated staging buffer — an out-of-bounds access surfacing as a process crash.

The fix branches on dstFormat.isBlock: for block formats it computes the row and depth pitch with the format’s block-aware helpers computeCompressedImageRowPitch() / computeCompressedImageDepthPitch(), guarded by ANGLE_CHECK_GL_MATH (overflow-checked), and only falls back to pixelBytes*width for uncompressed formats.

The restored invariant is that the destination pitch matches the actual (block-based) layout of the format being uploaded, so the copy stays within bounds.

Key insight
ANGLE’s Metal sub-image upload used pixelBytes*width as the row pitch for block-compressed formats, badly under-sizing it and copying out of bounds; computing the pitch with block-aware helpers fixes it.

Attack Path

  1. Use a compressed texture in WebGL On a Metal/ANGLE backend, upload a block-compressed texture (e.g. ETC2) via a sub-image update.
  2. Hit the per-slice convert path convertAndSetPerSliceSubImage computes dstRowPitch as pixelBytes*width, far smaller than the compressed layout needs.
  3. Under-sized pitch The copy uses the wrong pitch to index the destination, walking outside the staging buffer.
  4. Out-of-bounds / crash The mis-pitched copy reads/writes out of bounds in the GPU/WebContent process.

Impact Assessment

An out-of-bounds access from a mis-computed destination pitch when uploading block-compressed textures, reachable from WebGL compressed-texture sub-image uploads in the GPU/WebContent process. The observable is a crash; controllability depends on the format/size, and the change is a single isolable ANGLE file (unlike a bulk roll). Confined to the GPU/WebContent process; rated medium.

Changed Functions

FunctionChangeNotes
TextureMtl::convertAndSetPerSliceSubImage
Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/TextureMtl.mm
modified Computes dstRowPitch/dstDepthPitch via computeCompressedImageRowPitch/DepthPitch (ANGLE_CHECK_GL_MATH) for block-compressed formats instead of pixelBytes*width, fixing the under-sized pitch.

Files Changed

  • Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/TextureMtl.mm
  • Source/ThirdParty/ANGLE/src/tests/gl_tests/ETCTextureTest.cpp

Audit Directions

  • Other pixelBytes*width pitches
    grep ANGLE metal/ for rowPitch/depthPitch computed as pixelBytes*width without an isBlock branch.
  • Compressed-format paths
    Audit texture upload/readback/copy code for compressed formats using per-pixel pitch math.
  • Overflow checks
    Ensure compressed pitch computations use ANGLE_CHECK_GL_MATH so large dimensions can’t overflow the pitch.

Original Bug Report

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