CVE-2026-5277
Overview
Files Changed
src/common/mathutil.hsrc/common/mathutil_unittest.cppsrc/libANGLE/renderer/d3d/RendererD3D.hsrc/libANGLE/renderer/d3d/VertexBuffer.cppsrc/libANGLE/renderer/d3d/VertexBuffer.h
Patch
From f4c4aaf00cd981baf98fd81d37823d1032582d12 Mon Sep 17 00:00:00 2001
From: Shrek Shao <shrekshao@google.com>
Date: Tue, 17 Mar 2026 14:04:32 -0700
Subject: [PATCH] Fix D3D11 integer overflows in streaming vertex buffer path
The D3D11 backend's streaming vertex buffer path had several integer
arithmetic errors that could lead to under-reservation or out-of-bounds
memory access when using large base instance values.
Key changes:
- mathutil.h: Added UnsignedCeilDivide64 to handle 64-bit values safely.
- Renderer11/Renderer9: Updated getVertexSpaceRequired to use size_t and
CheckedNumeric for instance calculations, preventing 32-bit truncation.
- VertexBuffer: Updated storeDynamicAttribute to use CheckedNumeric when
calculating adjustedCount for instanced attributes with a base instance.
- VertexDataManager: Changed firstVertexIndex from GLint to size_t to
prevent negative index wrapping and added overflow checks for vertex
buffer size validation.
- Added a regression test (D3D11OverflowTest.cpp) to verify that large
baseInstance values do not cause crashes in the D3D11 backend.
This is a Gemini generated CL with manual modifications.
Bug: chromium:489791424
Change-Id: I86d13594ee6da6238d8c6583c5268b4bd2ee2658
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7675790
Auto-Submit: Shrek Shao <shrekshao@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
---
diff --git a/src/common/mathutil.h b/src/common/mathutil.h
index 0a67c2c..4f5b5c5 100644
--- a/src/common/mathutil.h
+++ b/src/common/mathutil.h
@@ -1538,6 +1538,12 @@
return (divided + ((value % divisor == 0) ? 0 : 1));
}
+inline constexpr uint64_t UnsignedCeilDivide64(uint64_t value, uint64_t divisor)
+{
+ uint64_t divided = value / divisor;
+ return (divided + ((value % divisor == 0) ? 0 : 1));
+}
+
#if defined(__has_builtin)
# define ANGLE_HAS_BUILTIN(x) __has_builtin(x)
#else
diff --git a/src/common/mathutil_unittest.cpp b/src/common/mathutil_unittest.cpp
index a66d881..b2e0a5c 100644
--- a/src/common/mathutil_unittest.cpp
+++ b/src/common/mathutil_unittest.cpp
@@ -1112,4 +1112,28 @@
EXPECT_NEAR((normalizedToFloat<26>(-16777216)), -0.5f, 0.00000003);
}
+// Test UnsignedCeilDivide
+TEST(MathUtilTest, UnsignedCeilDivide)
+{
+ EXPECT_EQ(0u, rx::UnsignedCeilDivide(0u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(1u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(4u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(5u, 5u));
+ EXPECT_EQ(2u, rx::UnsignedCeilDivide(6u, 5u));
+}
+
+// Test UnsignedCeilDivide64
+TEST(MathUtilTest, UnsignedCeilDivide64)
+{
+ EXPECT_EQ(0ull, rx::UnsignedCeilDivide64(0ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(1ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(4ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(5ull, 5ull));
+ EXPECT_EQ(2ull, rx::UnsignedCeilDivide64(6ull, 5ull));
+
+ uint64_t largeValue = 0xFFFFFFFF00000000ull;
+ EXPECT_EQ(0xFFFFFFFFull, rx::UnsignedCeilDivide64(largeValue, 0x100000000ull));
+ EXPECT_EQ(0x100000000ull, rx::UnsignedCeilDivide64(largeValue + 1, 0x100000000ull));
+}
+
} // anonymous namespace
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index 11e9e59..23183f0 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -160,7 +160,7 @@
const gl::VertexBinding &binding,
size_t count,
GLsizei instances,
- GLuint baseInstance,
+ uint64_t baseInstance,
unsigned int *bytesRequiredOut) const = 0;
};
diff --git a/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/libANGLE/renderer/d3d/VertexBuffer.cpp
index acb27ad..051fc7f 100644
--- a/src/libANGLE/renderer/d3d/VertexBuffer.cpp
+++ b/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -96,7 +96,7 @@
const gl::VertexBinding &binding,
size_t count,
GLsizei instances,
- GLuint baseInstance,
+ uint64_t baseInstance,
unsigned int *spaceInBytesOut) const
{
unsigned int spaceRequired = 0;
@@ -169,10 +169,10 @@
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
gl::VertexAttribType currentValueType,
- GLint start,
+ size_t start,
size_t count,
GLsizei instances,
- GLuint baseInstance,
+ uint64_t baseInstance,
unsigned int *outStreamOffset,
const uint8_t *sourceData)
{
@@ -187,17 +187,22 @@
mReservedSpace = 0;
- size_t adjustedCount = count;
- GLuint divisor = binding.getDivisor();
+ angle::CheckedNumeric<size_t> checkedCount = count;
+ GLuint divisor = binding.getDivisor();
if (instances != 0 && divisor != 0)
{
// The attribute is an instanced attribute and it's an draw instance call
// Extra number of elements are copied at the beginning to make sure
// the driver is referencing the correct data with non-zero baseInstance
- adjustedCount += UnsignedCeilDivide(baseInstance, divisor);
+ checkedCount += UnsignedCeilDivide64(static_cast<uint64_t>(baseInstance),
+ static_cast<uint64_t>(divisor));
}
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context), checkedCount.IsValid(),
+ "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
+
+ size_t adjustedCount = checkedCount.ValueOrDie();
ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding, currentValueType,
start, adjustedCount, instances, mWritePosition,
sourceData));
@@ -217,7 +222,7 @@
const gl::VertexBinding &binding,
size_t count,
GLsizei instances,
- GLuint baseInstance)
+ uint64_t baseInstance)
{
unsigned int requiredSpace = 0;
ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
@@ -286,7 +291,7 @@
angle::Result StaticVertexBufferInterface::storeStaticAttribute(const gl::Context *context,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
- GLint start,
+ size_t start,
GLsizei count,
GLsizei instances,
const uint8_t *sourceData)
diff --git a/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/libANGLE/renderer/d3d/VertexBuffer.h
index 45a16c6..4d0038f 100644
--- a/src/libANGLE/renderer/d3d/VertexBuffer.h
+++ b/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -50,7 +50,7 @@
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
gl::VertexAttribType currentValueType,
- GLint start,
+ size_t start,
size_t count,
GLsizei instances,
unsigned int offset,
@@ -102,7 +102,7 @@
const gl::VertexBinding &binding,
size_t count,
GLsizei instances,
- GLuint baseInstance,
+ uint64_t baseInstance,
unsigned int *spaceInBytesOut) const;
BufferFactoryD3D *const mFactory;
VertexBuffer *mVertexBuffer;
@@ -122,10 +122,10 @@
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
gl::VertexAttribType currentValueType,
- GLint start,
+ size_t start,
size_t count,
GLsizei instances,
- GLuint baseInstance,
+ uint64_t baseInstance,
unsigned int *outStreamOffset,
const uint8_t *sourceData);
Regression Test / PoC
diff --git a/src/common/mathutil_unittest.cpp b/src/common/mathutil_unittest.cpp
index a66d881..b2e0a5c 100644
--- a/src/common/mathutil_unittest.cpp
+++ b/src/common/mathutil_unittest.cpp
@@ -1112,4 +1112,28 @@
EXPECT_NEAR((normalizedToFloat<26>(-16777216)), -0.5f, 0.00000003);
}
+// Test UnsignedCeilDivide
+TEST(MathUtilTest, UnsignedCeilDivide)
+{
+ EXPECT_EQ(0u, rx::UnsignedCeilDivide(0u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(1u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(4u, 5u));
+ EXPECT_EQ(1u, rx::UnsignedCeilDivide(5u, 5u));
+ EXPECT_EQ(2u, rx::UnsignedCeilDivide(6u, 5u));
+}
+
+// Test UnsignedCeilDivide64
+TEST(MathUtilTest, UnsignedCeilDivide64)
+{
+ EXPECT_EQ(0ull, rx::UnsignedCeilDivide64(0ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(1ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(4ull, 5ull));
+ EXPECT_EQ(1ull, rx::UnsignedCeilDivide64(5ull, 5ull));
+ EXPECT_EQ(2ull, rx::UnsignedCeilDivide64(6ull, 5ull));
+
+ uint64_t largeValue = 0xFFFFFFFF00000000ull;
+ EXPECT_EQ(0xFFFFFFFFull, rx::UnsignedCeilDivide64(largeValue, 0x100000000ull));
+ EXPECT_EQ(0x100000000ull, rx::UnsignedCeilDivide64(largeValue + 1, 0x100000000ull));
+}
+
} // anonymous namespace
diff --git a/src/tests/angle_end2end_tests.gni b/src/tests/angle_end2end_tests.gni
index 314ac14..bce0a90 100644
--- a/src/tests/angle_end2end_tests.gni
+++ b/src/tests/angle_end2end_tests.gni
@@ -39,6 +39,7 @@
"gl_tests/AtomicCounterBufferTest.cpp",
"gl_tests/AttributeLayoutTest.cpp",
"gl_tests/BPTCCompressedTextureTest.cpp",
+ "gl_tests/BaseInstanceOverflowTest.cpp",
"gl_tests/BindGeneratesResourceTest.cpp",
"gl_tests/BindUniformLocationTest.cpp",
"gl_tests/BlendFuncExtendedTest.cpp",
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 11cb020..02db357 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -407,6 +407,7 @@
448658630 MAC OPENGL : GLSLTestLoops.ForContinueInConstSwitch/* = SKIP
448658630 MAC OPENGL : GLSLTestLoops.ForContinueInSwitchComplex/* = SKIP
475587478 MAC OPENGL : VertexAttributeTestES3.MaxAttribsWithBuiltInAttribs/* = SKIP
+494270619 MAC OPENGL : BaseInstanceOverflowTest.BaseInstanceOverflow/* = SKIP
// BlitFramebufferTest.ScissoredMultisampleStencil failures
42262159 MAC INTEL OPENGL : BlitFramebufferTest.ScissoredMultisampleStencil/* = SKIP
diff --git a/src/tests/gl_tests/BaseInstanceOverflowTest.cpp b/src/tests/gl_tests/BaseInstanceOverflowTest.cpp
new file mode 100644
index 0000000..51a4e64
--- /dev/null
+++ b/src/tests/gl_tests/BaseInstanceOverflowTest.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright 2026 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BaseInstanceOverflowTest: Reproduces integer overflow in vertex buffer streaming path.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class BaseInstanceOverflowTest : public ANGLETest<>
+{
+ protected:
+ BaseInstanceOverflowTest()
+ {
+ setWindowWidth(1);
+ setWindowHeight(1);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ }
+};
+
+// Regression Test (crbug.com/489791424)
+// Reproduces integer overflow in vertex buffer streaming path.
+// The bug occurs when baseInstance is large, causing a wrap-around in reservation
+// while the copy path uses 64-bit math.
+TEST_P(BaseInstanceOverflowTest, BaseInstanceOverflow)
+{
+ ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance"));
+
+ // We need a dynamic vertex attribute to trigger the streaming path.
+ // In D3D11, using an unaligned offset forces the streaming path.
+ GLBuffer buffer;
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ std::vector<GLfloat> data(1000, 1.0f);
+ glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_DYNAMIC_DRAW);
+
+ GLProgram program;
+ program.makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+ glUseProgram(program);
+
+ GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
+ glEnableVertexAttribArray(posLoc);
+
+ // Unaligned offset (1 byte) forces streaming path in D3D11.
+ glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 16, reinterpret_cast<void *>(1));
+ glVertexAttribDivisor(posLoc, 1);
+
+ // Trigger overflow by using a large baseInstance.
+ // elementCount calculation in Renderer11::getVertexSpaceRequired:
+ // (instances + baseInstance) / divisor
+ // If instances = 300, baseInstance = 0xFFFFFF00, divisor = 1:
+ // 300 + 0xFFFFFF00 = 0x10000002C.
+ // 32-bit truncation results in 0x2C = 44 elements reserved.
+ // However, StreamingVertexBufferInterface::storeDynamicAttribute uses 64-bit size_t:
+ // adjustedCount = 300 + 0xFFFFFF00 = 4,294,967,340 elements copied.
+ GLuint baseInstance = 0xFFFFFF00;
+ GLsizei instanceCount = 300;
+
+ // This call is expected to crash the GPU process without the fix.
+ // With the fix, the large baseInstance is caught by validation in VertexDataManager (D3D11)
+ // or ContextGL (OpenGL) because it exceeds the source buffer's bounds, returning
+ // GL_INVALID_OPERATION (D3D11) or avoiding the draw (OpenGL fallback).
+ glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, 3, instanceCount, baseInstance);
+
+ if (isD3D11Renderer())
+ {
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ EXPECT_GL_NO_ERROR();
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BaseInstanceOverflowTest);
+ANGLE_INSTANTIATE_TEST(BaseInstanceOverflowTest,
+ ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),
+ ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),
+ ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),
+ ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),
+ ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions));
diff --git a/src/tests/perf_tests/IndexDataManagerTest.cpp b/src/tests/perf_tests/IndexDataManagerTest.cpp
index 5d9856a..8084612 100644
--- a/src/tests/perf_tests/IndexDataManagerTest.cpp
+++ b/src/tests/perf_tests/IndexDataManagerTest.cpp
@@ -66,7 +66,7 @@
const gl::VertexBinding &,
size_t,
GLsizei,
- GLuint,
+ uint64_t,
unsigned int *));
// Dependency injection
Original Bug Report
Integer overflow in ANGLE D3D11 streaming vertex buffer leads to massive heap OOB write in the GPU process on Windows
Integer overflow in ANGLE D3D11 streaming vertex buffer leads to massive heap OOB write in the GPU process
Summary
ANGLE’s D3D11 backend computes the space to reserve in a streaming vertex buffer and the number of elements to copy using two inconsistent formulas when processing instanced draw calls with a non-zero baseInstance. By choosing a baseInstance close to 2^32, an attacker can cause unsigned 32-bit wrap in the reservation path while the copy path operates on a 64-bit accumulator, resulting in a heap buffer overflow of approximately 64 GB past a 768-byte allocation. A secondary defense in VertexDataManager::reserveSpaceForAttrib that validates the source buffer size is also defeated through an unsigned-to-signed truncation of the same baseInstance value. The crash occurs in the GPU process on Windows with the D3D11 backend (the default ANGLE backend on Windows), reachable from a compromised renderer via the WEBGL_draw_instanced_base_vertex_base_instance WebGL2 extension. The extension is gated behind a draft extension check in the renderer process, but since the vulnerability is in the GPU process, a compromised renderer can trivially bypass this gate.
Bisect
Introducing Commit: e61245008e7b1a152b31a1ee34f631203130d384
- Date: 2020-06-15
- Author: shrekshao (shrekshao@google.com)
- Review: https://chromium-review.googlesource.com/c/angle/angle/+/2227022
Root Cause
Three integer arithmetic errors combine to produce this vulnerability. They all stem from the same commit that added baseInstance support to ANGLE’s D3D11 streaming vertex translation path.
The first error is in Renderer11::getVertexSpaceRequired, which computes how many bytes to reserve in the streaming vertex buffer. For instanced attributes, the element count is calculated as:
// src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
elementCount =
UnsignedCeilDivide(static_cast<unsigned int>(instances + baseInstance), divisor);
Both instances (a GLsizei, i.e. signed 32-bit) and baseInstance (a GLuint, i.e. unsigned 32-bit) are added together and the result is truncated to unsigned int before the division. When baseInstance is 0xFFFFFF00 and instances is 300, the sum is 0x10000002C, which wraps to 44 after truncation. The function therefore reports that only 44 elements (704 bytes for vec4 floats) need to be reserved.
The second error is in StreamingVertexBufferInterface::storeDynamicAttribute, which computes how many elements to actually copy into that buffer:
// src/libANGLE/renderer/d3d/VertexBuffer.cpp
size_t adjustedCount = count;
GLuint divisor = binding.getDivisor();
if (instances != 0 && divisor != 0)
{
adjustedCount += UnsignedCeilDivide(baseInstance, divisor);
}
Here adjustedCount is a size_t (64-bit on x64), and UnsignedCeilDivide(0xFFFFFF00, 1) returns 0xFFFFFF00, so adjustedCount becomes 300 + 4,294,967,040 = 4,294,967,340. The subsequent call to VertexBuffer11::storeVertexAttributes passes this count to CopyNativeVertexData, which runs a memcpy-based loop that immediately overflows the 704-byte reservation.
The third error is in VertexDataManager::reserveSpaceForAttrib, which attempts to validate the source buffer before copying. It computes the first vertex index for instanced attributes:
// src/libANGLE/renderer/d3d/VertexDataManager.cpp
GLint firstVertexIndex = binding.getDivisor() > 0
? UnsignedCeilDivide(baseInstance, binding.getDivisor())
: start;
int64_t maxVertexCount =
static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
UnsignedCeilDivide returns GLuint (unsigned 32-bit), but the result is stored in GLint (signed 32-bit). When baseInstance is 0xFFFFFF00 and divisor is 1, the return value 0xFFFFFF00 is reinterpreted as -256 in the signed domain. This makes maxVertexCount equal to -256 + 300 = 44, and the subsequent maxByte <= bufferSize check passes trivially when the source buffer has at least 44 elements.
A potential validation exists in ValidateDrawInstancedAttribs in validationES.h, which checks whether baseInstance exceeds the instanced vertex element limit. However, this validation is gated on context->isBufferAccessValidationEnabled(), which is set to false when the backend supports GL_KHR_robust_buffer_access_behavior. The D3D11 backend advertises this extension, so the validation is skipped entirely. The hardware-level robust access only guards D3D11 GPU reads, not ANGLE’s CPU-side streaming buffer copies that precede the actual draw call.
Reproduce
This vulnerability affects Windows systems using the ANGLE D3D11 backend (the default on Windows). It crashes the GPU process via an integer overflow in ANGLE’s streaming vertex buffer translation, triggered through the WEBGL_draw_instanced_base_vertex_base_instance WebGL2 extension. The extension is gated behind a draft extension check in the renderer process; since the bug is in the GPU process, the attached patch.diff removes this renderer-side gate under the compromised renderer threat model.
Tested on commit 4e910e2277470c4576177b37937569fa4151abdc.
Build
Check out the tested commit and apply the renderer patch:
cd D:\chromium\src
git checkout 4e910e2277470c4576177b37937569fa4151abdc
git apply patch.diff
Configure an ASAN build by placing the following in D:\chromium\src\out\asan-release\args.gn:
is_asan = true
is_debug = false
is_component_build = false
symbol_level = 1
dcheck_always_on = false
use_remoteexec = true
Then build Chrome:
autoninja -C D:\chromium\src\out\asan-release chrome
Run
Set the ASAN options environment variable and launch Chrome, pointing it at the attached poc.html:
set ASAN_OPTIONS=detect_odr_violation=0
D:\chromium\src\out\asan-release\chrome.exe --enable-logging=stderr --no-first-run --user-data-dir=%TEMP%\poc-angl008 poc.html
The GPU process will crash within seconds. ASAN reports a heap-buffer-overflow in rx::CopyNativeVertexData<float,4,4,0> at copyvertex.inc.h, with a read of approximately 64 GB past the end of a 768-byte heap buffer. The full ASAN trace is provided in asan.log.
ASAN Output
=================================================================
==1944==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x116a3688ca00 at pc 0x7ffaf208b36c bp 0x0032075fd4b0 sp 0x0032075fd4f8
READ of size 68719477440 at 0x116a3688ca00 thread T0
#0 0x7ffaf208b36b in _asan_memcpy+0x25b (D:\chromium\src\out\asan-release\clang_rt.asan_dynamic-x86_64.dll+0x18004b36b)
#1 0x7ffaee711956 in rx::CopyNativeVertexData<float,4,4,0> D:\chromium\src\third_party\angle\src\libANGLE\renderer\copyvertex.inc.h:69
#2 0x7ffaeed4efcf in rx::VertexBuffer11::storeVertexAttributes D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\VertexBuffer11.cpp:133
#3 0x7ffaeee0bd9f in rx::StreamingVertexBufferInterface::storeDynamicAttribute D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\VertexBuffer.cpp:202
#4 0x7ffaeee11c81 in rx::VertexDataManager::storeDynamicAttrib D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\VertexDataManager.cpp:587
#5 0x7ffaeee1117f in rx::VertexDataManager::storeDynamicAttribs D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\VertexDataManager.cpp:466
#6 0x7ffaeed4e1c9 in rx::VertexArray11::updateDynamicAttribs D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\VertexArray11.cpp:330
#7 0x7ffaeed4d072 in rx::VertexArray11::syncStateForDraw D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\VertexArray11.cpp:163
#8 0x7ffaeecf97aa in rx::StateManager11::updateState D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\StateManager11.cpp:2001
#9 0x7ffaeec7dd87 in rx::Context11::drawArraysInstancedBaseInstance D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\Context11.cpp:311
#10 0x7ffaee94b013 in gl::Context::drawArraysInstancedBaseInstance D:\chromium\src\third_party\angle\src\libANGLE\Context.cpp:6946
#11 0x7ffaee4a97f8 in GL_DrawArraysInstancedBaseInstanceANGLE D:\chromium\src\third_party\angle\src\libGLESv2\entry_points_gles_ext_autogen.cpp:616
#12 0x7ffac9c2a10c in gl::GLApiBase::glDrawArraysInstancedBaseInstanceANGLEFn D:\chromium\src\ui\gl\gl_bindings_autogen_gl.cc:2679
#13 0x7ffaceba2304 in gpu::gles2::GLES2DecoderPassthroughImpl::DoDrawArraysInstancedBaseInstanceANGLE D:\chromium\src\gpu\command_buffer\service\gles2_cmd_decoder_passthrough_doers.cc:4525
#14 0x7ffacebce8aa in gpu::gles2::GLES2DecoderPassthroughImpl::HandleDrawArraysInstancedBaseInstanceANGLE D:\chromium\src\gpu\command_buffer\service\gles2_cmd_decoder_passthrough_handlers.cc:1645
#15 0x7ffaca02ae8c in gpu::gles2::GLES2DecoderPassthroughImpl::DoCommandsImpl<0> D:\chromium\src\gpu\command_buffer\service\gles2_cmd_decoder_passthrough.cc:742
#16 0x7ffaae4277fb in gpu::CommandBufferService::Flush D:\chromium\src\gpu\command_buffer\service\command_buffer_service.cc:267
#17 0x7ffabfc389e1 in gpu::CommandBufferStub::OnAsyncFlush D:\chromium\src\gpu\ipc\service\command_buffer_stub.cc:504
#18 0x7ffabfc378f3 in gpu::CommandBufferStub::ExecuteDeferredRequest D:\chromium\src\gpu\ipc\service\command_buffer_stub.cc:173
#19 0x7ffac530d8a1 in gpu::GpuChannel::ExecuteDeferredRequest D:\chromium\src\gpu\ipc\service\gpu_channel.cc:833
#20 0x7ffac531d40f in base::internal::Invoker<...>::RunOnce D:\chromium\src\base\functional\bind_internal.h:982
#21 0x7ffaae46996b in base::internal::Invoker<...>::RunImpl D:\chromium\src\base\functional\bind_internal.h:1069
#22 0x7ffaae43d792 in gpu::Scheduler::ExecuteSequence D:\chromium\src\gpu\command_buffer\service\scheduler.cc:707
#23 0x7ffaae43b8c0 in gpu::Scheduler::RunNextTask D:\chromium\src\gpu\command_buffer\service\scheduler.cc:625
#24 0x7ffaae440444 in base::internal::Invoker<...>::RunOnce D:\chromium\src\base\functional\bind_internal.h:982
#25 0x7ffabe4ccc98 in base::TaskAnnotator::RunTaskImpl D:\chromium\src\base\task\common\task_annotator.cc:229
#26 0x7ffac3c1b9f1 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl D:\chromium\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:475
#27 0x7ffac3c1a853 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork D:\chromium\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:346
#28 0x7ffac3c630f7 in base::MessagePumpDefault::Run D:\chromium\src\base\message_loop\message_pump_default.cc:42
#29 0x7ffac3c1d73f in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run D:\chromium\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:650
#30 0x7ffabe53fd0c in base::RunLoop::Run D:\chromium\src\base\run_loop.cc:135
#31 0x7ffac1a78e13 in content::GpuMain D:\chromium\src\content\gpu\gpu_main.cc:479
#32 0x7ffabae8899f in content::RunOtherNamedProcessTypeMain D:\chromium\src\content\app\content_main_runner_impl.cc:762
#33 0x7ffabae8b10b in content::ContentMainRunnerImpl::Run D:\chromium\src\content\app\content_main_runner_impl.cc:1152
#34 0x7ffabae7eeff in content::RunContentProcess D:\chromium\src\content\app\content_main.cc:358
#35 0x7ffabae7f6a2 in content::ContentMain D:\chromium\src\content\app\content_main.cc:371
#36 0x7ffaaace2b06 in ChromeMain D:\chromium\src\chrome\app\chrome_main.cc:191
#37 0x7ff7e0db4807 in MainDllLoader::Launch D:\chromium\src\chrome\app\main_dll_loader_win.cc:204
#38 0x7ff7e0db2074 in main D:\chromium\src\chrome\app\chrome_exe_main_win.cc:351
0x116a3688ca00 is located 0 bytes after 768-byte region [0x116a3688c700,0x116a3688ca00)
allocated by thread T0 here:
#0 0x7ffaf208c93f in _asan_wrap_memcpy+0x73f
#1 0x7ffaee4423c3 in _malloc_base
#2 0x7ffaf0050c2c in angle::MemoryBuffer::resize D:\chromium\src\third_party\angle\src\common\MemoryBuffer.cpp:40
#3 0x7ffaeec73564 in rx::Buffer11::SystemMemoryStorage::resize D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\Buffer11.cpp:1691
#4 0x7ffaeec6a0a7 in rx::Buffer11::setSubData D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\Buffer11.cpp:443
#5 0x7ffaeec68bd4 in rx::Buffer11::setData D:\chromium\src\third_party\angle\src\libANGLE\renderer\d3d\d3d11\Buffer11.cpp:359
#6 0x7ffaeeb81d0a in rx::BufferImpl::setDataWithUsageFlags D:\chromium\src\third_party\angle\src\libANGLE\renderer\BufferImpl.cpp:33
#7 0x7ffaee8dc21a in gl::Buffer::setDataWithUsageFlags D:\chromium\src\third_party\angle\src\libANGLE\Buffer.cpp:186
#8 0x7ffaee8dbb7c in gl::Buffer::bufferDataImpl D:\chromium\src\third_party\angle\src\libANGLE\Buffer.cpp:237
#9 0x7ffaee8dc0aa in gl::Buffer::bufferData D:\chromium\src\third_party\angle\src\libANGLE\Buffer.cpp:173
#10 0x7ffaee9450cf in gl::Context::bufferData D:\chromium\src\third_party\angle\src\libANGLE\Context.cpp:6434
#11 0x7ffaee476a89 in GL_BufferData D:\chromium\src\third_party\angle\src\libGLESv2\entry_points_gles_2_0_autogen.cpp:589
SUMMARY: AddressSanitizer: heap-buffer-overflow D:\chromium\src\third_party\angle\src\libANGLE\renderer\copyvertex.inc.h:69 in rx::CopyNativeVertexData<float,4,4,0>
Credit
Please use c6eed09fc8b174b0f3eebedcceb1e792 as the credit for this vulnerability. Thank you.
References
- https://chromium-review.googlesource.com/c/angle/angle/+/2227022
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/common/mathutil.h;l=1535-1539
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp;l=191-199
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp;l=525-527
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp;l=4103-4104
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/validationES.h;l=885-906