Medium chrome Integer Overflow 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInteger overflow in GPU
DescriptionInteger overflow in GPU
ComponentGPU
Bug ClassInteger Overflow
Tracker500132379
Fix commit857172c2d18b (chromium/src) +6/-4
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Changed Functions

FunctionChangeNotes
if
gpu/command_buffer/service/indexed_buffer_binding_host.cc
modified

Files Changed

  • gpu/command_buffer/service/indexed_buffer_binding_host.cc
From 857172c2d18b095acfd8e1a5ced0a5e89763a931 Mon Sep 17 00:00:00 2001
From: Corentin Wallez <[email protected]>
Date: Thu, 21 May 2026 09:00:36 -0700
Subject: [PATCH] [gpu] indexed_buffer_binding_host.cc: Avoid overflow of size + offset

In two cases the computation of a buffer binding's size + offset could
overflow making computation take the wrong code path. Instead make sure
that computation never have overflow by doing checks in this order:

 1. offset >= buffer_size -> OOB case
 2. size > buffer_size - offset -> OOB case
 3. in bounds case

Fixed: 500132379
Change-Id: I874d69f527d9811260ee4ab73b71bcb0681d885f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7865284
Reviewed-by: Geoff Lang <[email protected]>
Commit-Queue: Geoff Lang <[email protected]>
Auto-Submit: Corentin Wallez <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1634328}
---

diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host.cc b/gpu/command_buffer/service/indexed_buffer_binding_host.cc
index d19c6053..f605cb28 100644
--- a/gpu/command_buffer/service/indexed_buffer_binding_host.cc
+++ b/gpu/command_buffer/service/indexed_buffer_binding_host.cc
@@ -153,9 +153,7 @@
     glBindBufferBase(target, index, service_id);
     return;
   }
-  GLsizeiptr range_end = 0;
-  if (!base::CheckAdd(offset, size).AssignIfValid(&range_end) ||
-      range_end > full_buffer_size) {
+  if (size > full_buffer_size - offset) {
     adjusted_size = full_buffer_size - offset;
     // size needs to be a multiple of 4.
     adjusted_size = adjusted_size & ~3;
@@ -281,8 +279,12 @@
     case IndexedBufferBindingType::kBindBufferBase:
       return full_buffer_size;
     case IndexedBufferBindingType::kBindBufferRange:
-      if (binding.offset + binding.size > full_buffer_size)
+      if (binding.offset > full_buffer_size) {
+        return 0;
+      }
+      if (binding.size > full_buffer_size - binding.offset) {
         return full_buffer_size - binding.offset;
+      }
       return binding.size;
     case IndexedBufferBindingType::kBindBufferNone:
       return 0;
Loading diff…

Original Bug Report

reported by [email protected]

32-bit signed overflow in IndexedBufferBindingHost allows OOB GPU access

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.

Overview: A signed integer overflow in IndexedBufferBindingHost::GetEffectiveBufferSize and DoAdjustedBindBufferRange bypasses buffer bounds checks on 32-bit platforms. This allows a malicious WebGL app to bind an inflated buffer size, potentially tricking the underlying GPU driver into allowing out-of-bounds reads/writes during Transform Feedback or Uniform Block operations.

Affected files:

  • gpu/command_buffer/service/indexed_buffer_binding_host.cc
  • gpu/command_buffer/service/buffer_manager.cc
  • gpu/command_buffer/service/gles2_cmd_decoder.cc

Estimated timestamp from git blame: 2019-02-12

Description

A potential 32-bit signed integer overflow vulnerability exists in the validating command decoder’s buffer binding logic on 32-bit platforms (such as 32-bit Android). The OpenGL types GLintptr and GLsizeiptr are defined as 32-bit signed integers (khronos_ssize_t / long int). Because Chromium compiles with -fno-strict-overflow, signed integer addition wraps predictably.

Two critical bounds checks in gpu/command_buffer/service/indexed_buffer_binding_host.cc use direct addition without overflow protection:

  1. In IndexedBufferBindingHost::DoAdjustedBindBufferRange (which computes clamped parameters to safely send to the underlying OpenGL driver):
if (offset + size > full_buffer_size) {
  adjusted_size = full_buffer_size - offset;
  // ...
  1. In IndexedBufferBindingHost::GetEffectiveBufferSize (which determines the size available for BufferManager to validate draw calls):
if (binding.offset + binding.size > full_buffer_size)
  return full_buffer_size - binding.offset;
return binding.size;

If an attacker provides an offset and size that overflow a signed 32-bit integer when added (e.g., offset = 4 and size = 0x7FFFFFFC), the sum becomes negative (e.g., -2147483648). This negative sum is less than full_buffer_size, causing the bounds check to be entirely bypassed.

Consequently, the command decoder passes the massive size directly to the graphics driver (glBindBufferRange) and subsequently returns that massive size to BufferManager::RequestBuffersAccess. This bypasses the protections designed to prevent out-of-bounds GPU access.

Potential Attack Steps

Note: These are potential steps; our automated tooling has not yet executed a live proof-of-concept.

  1. A malicious WebGL2 script running in the renderer creates a small WebGLBuffer (e.g., 100 bytes).
  2. The script calls gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, buffer, 4, 0x7FFFFFFC).
  3. Blink’s WebGL2RenderingContextBase::bindBufferRange verifies that the size and offset fit within a non-negative 32-bit range, but does not check them against the actual buffer size, dispatching the IPC command.
  4. The GPU process executes IndexedBufferBindingHost::DoBindBufferRange. Because 4 + 0x7FFFFFFC overflows to -2147483648, the check offset + size > full_buffer_size fails. The underlying OpenGL driver is commanded to bind a ~2 GiB range.
  5. The script issues a draw call utilizing the bound UBO or Transform Feedback, requiring a size larger than the actual 100-byte buffer (e.g., 1000 bytes).
  6. During draw validation, BufferManager::RequestBuffersAccess calls GetEffectiveBufferSize. The overflow occurs again, causing the function to incorrectly report that the buffer has 0x7FFFFFFC bytes available.
  7. The draw call successfully validates and is sent to the GPU driver. Because the driver was misconfigured in step 4, the GPU hardware performs an out-of-bounds read (for UBOs) or out-of-bounds write (for Transform Feedback) into adjacent GPU memory.
  8. An attacker can use Transform Feedback OOB writes to corrupt GPU memory, leading to a potential sandbox escape from the renderer to the GPU process.

Recommendation

Replace the unsafe addition in IndexedBufferBindingHost with safe integer arithmetic using base::CheckAdd. Other components, such as Buffer::CheckRange in gpu/command_buffer/service/buffer_manager.cc, already successfully use this pattern:

// Example fix
GLsizeiptr max;
if (!base::CheckAdd(offset, size).AssignIfValid(&max) || max > full_buffer_size) {
    // clamp or handle error
}

Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker