Overview

Critical
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactOut of bounds read and write in ANGLE
DescriptionOut of bounds read and write in ANGLE
ComponentANGLE
Bug ClassOOB
Tracker498904293
Fix commit1c82f3a0bd18 (angle/angle) +111/-0
CISA KEVNot listed
CreditedAnonymous
Disclosed2026-06-02

Files Changed

  • src/libANGLE/renderer/gl/StateManagerGL.cpp
  • src/libANGLE/renderer/gl/StateManagerGL.h
  • src/tests/angle_end2end_tests_expectations.txt
  • src/tests/capture_replay_tests/capture_replay_expectations.txt
  • src/tests/gl_tests/CopyTextureTest.cpp
From 1c82f3a0bd18d2046fa38ccffffbcc45891f0301 Mon Sep 17 00:00:00 2001
From: Geoff Lang <[email protected]>
Date: Fri, 17 Apr 2026 18:03:58 -0400
Subject: [PATCH] GL: Mark StateManagerGL internal buffer state dirty on bind

When changing state, StateManagerGL would set local dirty bits which
would be synchronized on the next syncState by ORing them with the
frontend dirty bits. This was not done for internal buffer binding
changes and allowed for incorrect pixel buffers to be bound on
ReadPixels or TexImage calls.

Fixed: chromium:498904293
Fixed: chromium:503768143
Change-Id: I42f5acfdb709f327205f0f8cc04c3f11f1bd2b79
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7774027
Commit-Queue: Geoff Lang <[email protected]>
Reviewed-by: Shahbaz Youssefi <[email protected]>
---

diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index c0dea01..0d2bf2a 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -473,6 +473,7 @@
     {
         mBuffers[target] = buffer;
         mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
+        setBufferBindingDirty(target);
     }
 }
 
@@ -491,6 +492,7 @@
         binding.size     = static_cast<size_t>(-1);
         mBuffers[target] = buffer;
         mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
+        setBufferBindingDirty(target);
     }
 }
 
@@ -2949,6 +2951,56 @@
                         "GL_VERTEX_ARRAY_BINDING");
 }
 
+void StateManagerGL::setBufferBindingDirty(gl::BufferBinding binding)
+{
+    switch (binding)
+    {
+        case gl::BufferBinding::Array:
+            // Nothing to do. Array buffer bindings are set before vertex attrib calls.
+            break;
+        case gl::BufferBinding::AtomicCounter:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::CopyRead:
+            // Nothing to do. CopyRead does not affect any operations.
+            break;
+        case gl::BufferBinding::CopyWrite:
+            // Nothing to do. CopyWrite does not affect any operations.
+            break;
+        case gl::BufferBinding::DispatchIndirect:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::DrawIndirect:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::ElementArray:
+            // Managed by the VAO
+            break;
+        case gl::BufferBinding::PixelPack:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_PACK_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::PixelUnpack:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::ShaderStorage:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
+            break;
+        case gl::BufferBinding::Texture:
+            // Not implemented in the GL backend
+            UNREACHABLE();
+            break;
+        case gl::BufferBinding::TransformFeedback:
+            // Transform feedback buffer bindings are tracked in TransformFeedbackGL
+            UNREACHABLE();
+            break;
+        case gl::BufferBinding::Uniform:
+            mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
+            break;
+        default:
+            UNREACHABLE();
+    }
+}
+
 template <>
 void StateManagerGL::get(GLenum name, GLboolean *value)
 {
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index bad9aa5..795a690 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -365,6 +365,8 @@
     void updateDispatchIndirectBufferBinding(const gl::Context *context);
     void updateDrawIndirectBufferBinding(const gl::Context *context);
 
+    void setBufferBindingDirty(gl::BufferBinding binding);
+
     template <typename T>
     void get(GLenum name, T *value);
 
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 003d9b3..3e44278 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -1561,6 +1561,9 @@
 42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8SRGBTest.Test/* = SKIP
 42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8Test.Test/* = SKIP
 
+// NVIDIA GLES specific failures with DXT texture uploads
+498904293 WIN NVIDIA GLES : DXT1CompressedTextureTestWebGL2.InitializeTextureContents/* = SKIP
+
 // Takes several minutes to complete with ASAN / TSAN
 42263997 ASAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
 42266388 TSAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
diff --git a/src/tests/capture_replay_tests/capture_replay_expectations.txt b/src/tests/capture_replay_tests/capture_replay_expectations.txt
index 201c64a..5df1eab 100644
--- a/src/tests/capture_replay_tests/capture_replay_expectations.txt
+++ b/src/tests/capture_replay_tests/capture_replay_expectations.txt
@@ -81,6 +81,7 @@
 42264831 : FramebufferTest_ES3.ChangeAttachmentThenInvalidateAndDraw/* = SKIP_FOR_CAPTURE
 42264831 : FramebufferTest_ES3.RenderAndInvalidateImmutableTextureWithBeyondMaxLevel/* = SKIP_FOR_CAPTURE
 490170083 : CopyTextureTestES3.SRGBWithPackParameters/* = SKIP_FOR_CAPTURE
+498904293 : CopyTextureTestES3.PBOSynchronization/* = SKIP_FOR_CAPTURE
 
 # The following tests fail with forceRobustResourceInit
 # They were accidentally passing until http://crrev/c/5588816
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index 07d490c..6df23a9 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -2725,6 +2725,59 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, kSourceColor);
 }
 
+// Test that copies that trigger internal readbacks do not interfere with the frontend PBO state.
+TEST_P(CopyTextureTestES3, PBOSynchronization)
+{
+    ANGLE_SKIP_TEST_IF(!checkExtensions());
+    ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_sRGB"));
+
+    GLTexture backbufferTex;
+    glBindTexture(GL_TEXTURE_2D, backbufferTex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, backbufferTex, 0);
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    // Set the PBO and write some data to it. It will be synchronized in the backend
+    GLBuffer pbo;
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+    glBufferData(GL_PIXEL_PACK_BUFFER, 4096, nullptr, GL_STATIC_DRAW);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    // Copy into an SRGB texture which does an internal readback
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+                 nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    glCopySubTextureCHROMIUM(mTextures[1], 0, GL_TEXTURE_2D, mTextures[0], 0, 0, 0, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // Read pixels again, should still go to the PBO
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid *>(1024));
+
+    uint8_t *mappedPtr =
+        static_cast<uint8_t *>(glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4096, GL_MAP_READ_BIT));
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr));
+    EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr + 1024));
+
+    glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Test that the right error type is triggered when
 // OES_EGL_image_external_essl3 is required but not supported
 TEST_P(CopyTextureTestES3, CopySubTextureMissingRequiredExtension)
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 003d9b3..3e44278 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -1561,6 +1561,9 @@
 42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8SRGBTest.Test/* = SKIP
 42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8Test.Test/* = SKIP
 
+// NVIDIA GLES specific failures with DXT texture uploads
+498904293 WIN NVIDIA GLES : DXT1CompressedTextureTestWebGL2.InitializeTextureContents/* = SKIP
+
 // Takes several minutes to complete with ASAN / TSAN
 42263997 ASAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
 42266388 TSAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
diff --git a/src/tests/capture_replay_tests/capture_replay_expectations.txt b/src/tests/capture_replay_tests/capture_replay_expectations.txt
index 201c64a..5df1eab 100644
--- a/src/tests/capture_replay_tests/capture_replay_expectations.txt
+++ b/src/tests/capture_replay_tests/capture_replay_expectations.txt
@@ -81,6 +81,7 @@
 42264831 : FramebufferTest_ES3.ChangeAttachmentThenInvalidateAndDraw/* = SKIP_FOR_CAPTURE
 42264831 : FramebufferTest_ES3.RenderAndInvalidateImmutableTextureWithBeyondMaxLevel/* = SKIP_FOR_CAPTURE
 490170083 : CopyTextureTestES3.SRGBWithPackParameters/* = SKIP_FOR_CAPTURE
+498904293 : CopyTextureTestES3.PBOSynchronization/* = SKIP_FOR_CAPTURE
 
 # The following tests fail with forceRobustResourceInit
 # They were accidentally passing until http://crrev/c/5588816
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index 07d490c..6df23a9 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -2725,6 +2725,59 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, kSourceColor);
 }
 
+// Test that copies that trigger internal readbacks do not interfere with the frontend PBO state.
+TEST_P(CopyTextureTestES3, PBOSynchronization)
+{
+    ANGLE_SKIP_TEST_IF(!checkExtensions());
+    ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_sRGB"));
+
+    GLTexture backbufferTex;
+    glBindTexture(GL_TEXTURE_2D, backbufferTex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, backbufferTex, 0);
+
+    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_GL_NO_ERROR();
+
+    // Set the PBO and write some data to it. It will be synchronized in the backend
+    GLBuffer pbo;
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+    glBufferData(GL_PIXEL_PACK_BUFFER, 4096, nullptr, GL_STATIC_DRAW);
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    // Copy into an SRGB texture which does an internal readback
+    glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+                 nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    glCopySubTextureCHROMIUM(mTextures[1], 0, GL_TEXTURE_2D, mTextures[0], 0, 0, 0, 0, 0, 1, 1,
+                             false, false, false);
+    EXPECT_GL_NO_ERROR();
+
+    // Read pixels again, should still go to the PBO
+    glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid *>(1024));
+
+    uint8_t *mappedPtr =
+        static_cast<uint8_t *>(glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4096, GL_MAP_READ_BIT));
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr));
+    EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr + 1024));
+
+    glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Test that the right error type is triggered when
 // OES_EGL_image_external_essl3 is required but not supported
 TEST_P(CopyTextureTestES3, CopySubTextureMissingRequiredExtension)
Loading diff…

Original Bug Report

reported by [email protected]

Arbitrary Memory Read and Write in ANGLE GL Backend via PBO Desync

VULNERABILITY DETAILS

A severe state desynchronization vulnerability exists in the ANGLE OpenGL backend (CopySubTextureCHROMIUM), leading to Arbitrary R/W in the GPU process.

The root cause resides in BlitGL::copySubTextureCPUReadback. When performing a CPU fallback copy, the code explicitly unbinds the PIXEL_PACK_BUFFER mappings through the GL backend StateManagerGL using setPixelPackBuffer(context, nullptr) [0]. An identical mechanism unbinds the PIXEL_UNPACK_BUFFER via setPixelUnpackBuffer [1].

    gl::PixelPackState pack;
    pack.alignment = 1;
    ANGLE_TRY(mStateManager->setPixelPackState(context, pack));
    ANGLE_TRY(mStateManager->setPixelPackBuffer(context, nullptr)); // [0]

    // ...
    gl::PixelUnpackState unpack;
    unpack.alignment = 1;
    ANGLE_TRY(mStateManager->setPixelUnpackState(context, unpack));
    ANGLE_TRY(mStateManager->setPixelUnpackBuffer(context, nullptr)); // [1]

These functions effectively propagate the glBindBuffer command directly to the native GPU driver via StateManagerGL::bindBuffer [2].

angle::Result StateManagerGL::setPixelUnpackBuffer(const gl::Context *context,
                                                   const gl::Buffer *pixelBuffer)
{
    GLuint bufferID = 0;
    if (pixelBuffer != nullptr)
    {
        bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
    }
    bindBuffer(gl::BufferBinding::PixelUnpack, bufferID); // [2]

    return angle::Result::Continue;
}

However, they silently bypass the ANGLE frontend tracking system (gl::State). Crucially, the frontend’s dirty bits (such as DIRTY_BIT_UNPACK_BUFFER_BINDING) are never set.

Because the frontend gl::State tracking and the native OpenGL driver state become desynchronized, the underlying native GL driver lacks the PBO binding (it was set to 0), while the frontend continues to believe the PBO is actively bound. When a subsequent API call takes an offset, the native driver treats the user-supplied offset as a raw CPU/Host pointer, enabling arbitrary memory operations.

[0] https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=865

[1] https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=883

[2] https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=642

Vulnerability Exploit

The PoC leverages the desynchronization bug to transform a PBO offset into an arbitrary memory pointer. The process relies on intentionally triggering a CPU fallback path (e.g., via copyTextureCHROMIUM), which silently unbinds the PIXEL_PACK_BUFFER in the native OpenGL driver while the ANGLE frontend state remains intact.

Steps to achieve an arbitrary write:

  1. Desynchronize the PIXEL_PACK_BUFFER state.
  2. Manipulate the frontend state system (e.g., via dummy readPixels calls) to clear dirty bits, preventing the buffer from re-binding to the driver.
  3. Call readPixels using a controlled integer (e.g. 0x41414141) as the offset.
  4. Since the native OpenGL driver considers the PBO unbound (id = 0), it interprets the offset as an absolute virtual memory pointer, writing pixel data directly to this address.

The arbitrary read is achieved via a similar state desynchronization for PIXEL_UNPACK_BUFFER during operations like texSubImage2D.

Arbitrary Write Crash Site

Thread 1 "chrome" received signal SIGSEGV, Segmentation fault.
__memcpy_avx_unaligned_erms ()
    at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:271
warning: 271	../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory
(gdb) x/i $pc
=> 0x7f264e788aa1 <__memcpy_avx_unaligned_erms+33>:	vmovdqu %ymm0,(%rdi)
(gdb) i r rdi
rdi            0x41414141          1094795585
(gdb) i r ymm0
ymm0           {v16_bfloat16 = {0x4242 <repeats 16 times>}, v16_half = {0x4242 <repeats 16 times>}, v8_float = {0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242}, v4_double = {0x4242424242424242, 0x4242424242424242, 0x4242424242424242, 0x4242424242424242}, v32_int8 = {0x42 <repeats 32 times>}, v16_int16 = {0x4242 <repeats 16 times>}, v8_int32 = {0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242}, v4_int64 = {0x4242424242424242, 0x4242424242424242, 0x4242424242424242, 0x4242424242424242}, v2_int128 = {0x42424242424242424242424242424242, 0x42424242424242424242424242424242}}
(gdb) bt
#0  __memcpy_avx_unaligned_erms ()
    at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:271
#1  0x000056c2930d7edc in __interceptor_memcpy ()
#2  0x00007b221f1b443e in ??? ()
    at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#3  0x00007b221f20cc9b in ??? ()
    at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#4  0x00007b221f1b4d3a in ??? ()
    at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#5  0x00007b221f1b50d5 in ??? ()
    at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#6  0x00007b2241cca380 in readPixelsAllAtOnce ()
    at ../../third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp:1684
#7  0x00007b2241cc9442 in readPixels ()
    at ../../third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp:816
// ...

BISECTION

Introduced by ANGLE upstream commit [0] which added the CPU fallback implementation for CopyTextureCHROMIUM on OpenGL but failed to safely track buffer unbindings within the frontend state.

This regression was rolled into Chromium in commit [1].

[0] https://chromium.googlesource.com/angle/angle/+/aadc8f376a2c797db98d69d308c9980ca818f57f (Implement the CPU fallback for CopyTextureCHROMIUM on OpenGL)

[1] https://chromium.googlesource.com/chromium/src/+/236105a6afc95bfab50b0a3e3487c85cc049b49c (Roll ANGLE 79f7104..92996b0)

VERSION

Chrome Version: HEAD

Operating System: Linux

REPRODUCTION CASE

  1. Apply renderer.patch and build Chromium with ASan.
  2. Host the poc.html on an HTTP server.
  3. Run Chrome against the PoC.
$ python3 -m http.server 8000
$ ./out/asan/chrome "http://localhost:8000/poc.html"

CRASH INFORMATION

Type of crash: GPU process

Crash log: Attached asan_read.txt (Arbitrary Read) and asan_write.txt (Arbitrary Write).

CREDIT INFORMATION

Reporter credit: Anonymous

View on issue tracker