CVE-2026-106395
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Psrc/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp |
modified |
Files Changed
src/dawn/tests/white_box/GLFramebufferCompletenessTests.cppsrc/dawn/native/opengl/UtilsGL.cppsrc/dawn/native/opengl/TextureGL.cppsrc/dawn/native/opengl/SwapChainEGL.cpp
Patch
From b911f1a5ae55ae23de2088c90cc32422fc6b024d Mon Sep 17 00:00:00 2001
From: Shrek Shao <shrekshao@google.com>
Date: Thu, 03 Sep 2026 16:36:21 -0700
Subject: [PATCH] gl: Check framebuffer completeness in ClearTexture and helpers
Texture::ClearTexture in the OpenGL backend creates temporary
framebuffers to clear texture subresources without querying framebuffer
completeness. On OpenGL ES drivers where certain formats cannot be
attached as complete framebuffer attachments (e.g. returning
GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
glClearBuffer* silently fails with GL_INVALID_FRAMEBUFFER_OPERATION
while Dawn marks the subresource as initialized, leaving uninitialized
GPU memory.
This CL adds CheckFramebufferComplete checks to Texture::ClearTexture,
CopyImageSubData, and SwapChainEGL::PresentImpl to ensure all temporary
framebuffer attachments are valid and complete before drawing/clearing.
Adds white-box tests in GLFramebufferCompletenessTests using error
injection to simulate framebuffer incompleteness during lazy texture
clearing (2D, 3D, and depth/stencil) and blit subdata copies.
Fixed: 553121488
Change-Id: Iabcc1f4e49b41bcc7147c5100c21907cd9662a9b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/338396
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Shrek Shao <shrekshao@google.com>
---
diff --git a/src/dawn/native/opengl/SwapChainEGL.cpp b/src/dawn/native/opengl/SwapChainEGL.cpp
index 55e0a09..db9a736 100644
--- a/src/dawn/native/opengl/SwapChainEGL.cpp
+++ b/src/dawn/native/opengl/SwapChainEGL.cpp
@@ -118,6 +118,7 @@
DAWN_GL_TRY(gl, GenFramebuffers(1, &readFbo));
DAWN_GL_TRY(gl, BindFramebuffer(GL_READ_FRAMEBUFFER, readFbo));
DAWN_TRY(mTextureView->BindToFramebuffer(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_READ_FRAMEBUFFER));
DAWN_GL_TRY(gl, BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
DAWN_GL_TRY(gl, Scissor(0, 0, surfaceWidth, surfaceHeight));
diff --git a/src/dawn/native/opengl/TextureGL.cpp b/src/dawn/native/opengl/TextureGL.cpp
index 00a3089..717779e 100644
--- a/src/dawn/native/opengl/TextureGL.cpp
+++ b/src/dawn/native/opengl/TextureGL.cpp
@@ -464,6 +464,7 @@
}
DAWN_TRY(FramebufferTextureHelper(gl, mTarget, GL_DRAW_FRAMEBUFFER, attachment,
GetTextureHandle(), level, layer));
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_DRAW_FRAMEBUFFER));
DAWN_TRY(DoClear(aspectsToClear));
}
}
@@ -570,12 +571,14 @@
for (GLint z = 0; z < static_cast<GLint>(depth); ++z) {
DAWN_GL_TRY(gl, FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment,
GetTextureHandle(), level, z));
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_DRAW_FRAMEBUFFER));
DAWN_TRY(DoClear());
}
} else {
DAWN_TRY(FramebufferTextureHelper(gl, mTarget, GL_DRAW_FRAMEBUFFER,
attachment, GetTextureHandle(), level,
layer));
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_DRAW_FRAMEBUFFER));
DAWN_TRY(DoClear());
}
diff --git a/src/dawn/native/opengl/UtilsGL.cpp b/src/dawn/native/opengl/UtilsGL.cpp
index df219b6..e33e7d7 100644
--- a/src/dawn/native/opengl/UtilsGL.cpp
+++ b/src/dawn/native/opengl/UtilsGL.cpp
@@ -161,6 +161,8 @@
dstHandle, dstLevel, dst.z + layer));
}
}
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_READ_FRAMEBUFFER));
+ DAWN_TRY(CheckFramebufferComplete(gl, GL_DRAW_FRAMEBUFFER));
DAWN_GL_TRY(
gl, BlitFramebuffer(src.x, src.y, src.x + size.width, src.y + size.height, dst.x, dst.y,
dst.x + size.width, dst.y + size.height, blitMask, GL_NEAREST));
diff --git a/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp b/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
index 0a9fc63..d58cfaf 100644
--- a/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
+++ b/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
@@ -26,7 +26,9 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/dawn/native/ErrorData.h"
+#include "src/dawn/native/ErrorInjector.h"
#include "src/dawn/native/opengl/DeviceGL.h"
+#include "src/dawn/native/opengl/TextureGL.h"
#include "src/dawn/native/opengl/UtilsGL.h"
#include "src/dawn/tests/DawnTest.h"
@@ -88,6 +90,125 @@
GLFramebufferStatusAsString(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
}
+#if defined(DAWN_ENABLE_ERROR_INJECTION)
+
+// Test that Texture::EnsureSubresourceContentInitialized (which calls Texture::ClearTexture)
+// verifies framebuffer completeness before clearing.
+// Injecting GL_FRAMEBUFFER_UNSUPPORTED on glCheckFramebufferStatus mimics OpenGL ES drivers
+// where certain formats (such as floating-point textures on drivers without
+// GL_EXT_color_buffer_float, or drivers returning GL_FRAMEBUFFER_UNSUPPORTED) cannot be attached
+// as complete framebuffer attachments. On such drivers, glClearBuffer* generates
+// GL_INVALID_FRAMEBUFFER_OPERATION and performs no writes; verifying completeness ensures Dawn
+// catches the error instead of silently marking uninitialized/dirty GPU memory as initialized.
+TEST_P(GLFramebufferCompletenessTests, LazyClearChecksCompleteness) {
+ Device* deviceGL = ToBackend(FromAPI(device.Get()));
+ const OpenGLFunctions& gl = deviceGL->GetGL();
+
+ // 1. 2D Color Texture (e.g. RGBA16Float)
+ {
+ wgpu::TextureDescriptor desc;
+ desc.size = {4, 4, 1};
+ desc.format = wgpu::TextureFormat::RGBA16Float;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+
+ // 2. Depth/Stencil Texture
+ {
+ wgpu::TextureDescriptor desc;
+ desc.size = {4, 4, 1};
+ desc.format = wgpu::TextureFormat::Depth24PlusStencil8;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+
+ // 3. 3D Color Texture
+ {
+ wgpu::TextureDescriptor desc;
+ desc.dimension = wgpu::TextureDimension::e3D;
+ desc.size = {4, 4, 4};
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+}
+
+// Test that CopyImageSubData checks framebuffer completeness for both read and draw framebuffers.
+TEST_P(GLFramebufferCompletenessTests, CopyImageSubDataChecksCompleteness) {
+ Device* deviceGL = ToBackend(FromAPI(device.Get()));
+ const OpenGLFunctions& gl = deviceGL->GetGL();
+
+ GLuint srcTex = 0;
+ GLuint dstTex = 0;
+ gl.GenTextures(1, &srcTex);
+ gl.GenTextures(1, &dstTex);
+ gl.BindTexture(GL_TEXTURE_2D, srcTex);
+ gl.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4);
+ gl.BindTexture(GL_TEXTURE_2D, dstTex);
+ gl.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4);
+
+ EnableErrorInjector();
+
+ // 1. Error on GL_READ_FRAMEBUFFER (index 0)
+ {
+ InjectErrorAt(0u);
+ MaybeError err = CopyImageSubData(gl, Aspect::Color, srcTex, GL_TEXTURE_2D, 0, {0, 0, 0},
+ dstTex, GL_TEXTURE_2D, 0, {0, 0, 0}, {4, 4, 1});
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ }
+
+ // 2. Error on GL_DRAW_FRAMEBUFFER (index 1)
+ {
+ InjectErrorAt(1u);
+ MaybeError err = CopyImageSubData(gl, Aspect::Color, srcTex, GL_TEXTURE_2D, 0, {0, 0, 0},
+ dstTex, GL_TEXTURE_2D, 0, {0, 0, 0}, {4, 4, 1});
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 2u);
+ }
+
+ DisableErrorInjector();
+ gl.DeleteTextures(1, &srcTex);
+ gl.DeleteTextures(1, &dstTex);
+}
+
+#endif // defined(DAWN_ENABLE_ERROR_INJECTION)
+
DAWN_INSTANTIATE_TEST(GLFramebufferCompletenessTests, OpenGLESBackend());
} // anonymous namespace
Regression Test / PoC
diff --git a/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp b/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
index 0a9fc63..d58cfaf 100644
--- a/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
+++ b/src/dawn/tests/white_box/GLFramebufferCompletenessTests.cpp
@@ -26,7 +26,9 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/dawn/native/ErrorData.h"
+#include "src/dawn/native/ErrorInjector.h"
#include "src/dawn/native/opengl/DeviceGL.h"
+#include "src/dawn/native/opengl/TextureGL.h"
#include "src/dawn/native/opengl/UtilsGL.h"
#include "src/dawn/tests/DawnTest.h"
@@ -88,6 +90,125 @@
GLFramebufferStatusAsString(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
}
+#if defined(DAWN_ENABLE_ERROR_INJECTION)
+
+// Test that Texture::EnsureSubresourceContentInitialized (which calls Texture::ClearTexture)
+// verifies framebuffer completeness before clearing.
+// Injecting GL_FRAMEBUFFER_UNSUPPORTED on glCheckFramebufferStatus mimics OpenGL ES drivers
+// where certain formats (such as floating-point textures on drivers without
+// GL_EXT_color_buffer_float, or drivers returning GL_FRAMEBUFFER_UNSUPPORTED) cannot be attached
+// as complete framebuffer attachments. On such drivers, glClearBuffer* generates
+// GL_INVALID_FRAMEBUFFER_OPERATION and performs no writes; verifying completeness ensures Dawn
+// catches the error instead of silently marking uninitialized/dirty GPU memory as initialized.
+TEST_P(GLFramebufferCompletenessTests, LazyClearChecksCompleteness) {
+ Device* deviceGL = ToBackend(FromAPI(device.Get()));
+ const OpenGLFunctions& gl = deviceGL->GetGL();
+
+ // 1. 2D Color Texture (e.g. RGBA16Float)
+ {
+ wgpu::TextureDescriptor desc;
+ desc.size = {4, 4, 1};
+ desc.format = wgpu::TextureFormat::RGBA16Float;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+
+ // 2. Depth/Stencil Texture
+ {
+ wgpu::TextureDescriptor desc;
+ desc.size = {4, 4, 1};
+ desc.format = wgpu::TextureFormat::Depth24PlusStencil8;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+
+ // 3. 3D Color Texture
+ {
+ wgpu::TextureDescriptor desc;
+ desc.dimension = wgpu::TextureDimension::e3D;
+ desc.size = {4, 4, 4};
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+ desc.usage = wgpu::TextureUsage::TextureBinding;
+ wgpu::Texture tex = device.CreateTexture(&desc);
+
+ Texture* texGL = ToBackend(FromAPI(tex.Get()));
+
+ EnableErrorInjector();
+ InjectErrorAt(0u);
+ MaybeError err =
+ texGL->EnsureSubresourceContentInitialized(gl, texGL->GetAllSubresources());
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ DisableErrorInjector();
+ }
+}
+
+// Test that CopyImageSubData checks framebuffer completeness for both read and draw framebuffers.
+TEST_P(GLFramebufferCompletenessTests, CopyImageSubDataChecksCompleteness) {
+ Device* deviceGL = ToBackend(FromAPI(device.Get()));
+ const OpenGLFunctions& gl = deviceGL->GetGL();
+
+ GLuint srcTex = 0;
+ GLuint dstTex = 0;
+ gl.GenTextures(1, &srcTex);
+ gl.GenTextures(1, &dstTex);
+ gl.BindTexture(GL_TEXTURE_2D, srcTex);
+ gl.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4);
+ gl.BindTexture(GL_TEXTURE_2D, dstTex);
+ gl.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4);
+
+ EnableErrorInjector();
+
+ // 1. Error on GL_READ_FRAMEBUFFER (index 0)
+ {
+ InjectErrorAt(0u);
+ MaybeError err = CopyImageSubData(gl, Aspect::Color, srcTex, GL_TEXTURE_2D, 0, {0, 0, 0},
+ dstTex, GL_TEXTURE_2D, 0, {0, 0, 0}, {4, 4, 1});
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 1u);
+ }
+
+ // 2. Error on GL_DRAW_FRAMEBUFFER (index 1)
+ {
+ InjectErrorAt(1u);
+ MaybeError err = CopyImageSubData(gl, Aspect::Color, srcTex, GL_TEXTURE_2D, 0, {0, 0, 0},
+ dstTex, GL_TEXTURE_2D, 0, {0, 0, 0}, {4, 4, 1});
+ EXPECT_TRUE(err.IsError());
+ err.AcquireError();
+ EXPECT_EQ(AcquireErrorInjectorCallCount(), 2u);
+ }
+
+ DisableErrorInjector();
+ gl.DeleteTextures(1, &srcTex);
+ gl.DeleteTextures(1, &dstTex);
+}
+
+#endif // defined(DAWN_ENABLE_ERROR_INJECTION)
+
DAWN_INSTANTIATE_TEST(GLFramebufferCompletenessTests, OpenGLESBackend());
} // anonymous namespace
Original Bug Report
GPU Memory Leak in Dawn GL Texture::ClearTexture via Missing FBO Completeness Check
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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: In Dawn’s OpenGL backend, Texture::ClearTexture performs lazy zero-initialization using temporary framebuffers without checking framebuffer completeness. When an incomplete framebuffer is encountered, glClearBuffer* silently fails in release builds, but the subresource is still marked initialized. Web content could potentially sample the uninitialized texture to disclose uninitialized GPU memory across origins.
Affected files:
third_party/dawn/src/dawn/native/opengl/TextureGL.cppthird_party/dawn/src/dawn/native/opengl/PhysicalDeviceGL.cpp
Estimated timestamp from git blame: 2026-07-20
Summary
In Dawn’s OpenGL backend (src/dawn/native/opengl/TextureGL.cpp), Texture::ClearTexture implements lazy zero-clearing of textures by creating temporary framebuffers (FBOs), attaching the target subresource, and issuing glClearBuffer*. However, Texture::ClearTexture does not verify framebuffer completeness via CheckFramebufferComplete() before issuing clear calls. If the framebuffer is incomplete, glClearBuffer* generates GL_INVALID_FRAMEBUFFER_OPERATION and performs no writes, but release builds swallow the GL error and unconditionally mark the subresource as initialized. This can allow web applications to read uninitialized GPU process memory.
Root Cause Analysis
-
Missing Completeness Gate: Dawn introduced
CheckFramebufferComplete(const OpenGLFunctions& gl, GLenum target)insrc/dawn/native/opengl/UtilsGL.h:59to guarantee that callers relying on framebuffer operations never proceed past an incomplete framebuffer. While this check was integrated intoCommandBufferGL.cppfor render passes, resolves, and readbacks, it is absent inTexture::ClearTexture(TextureGL.cpp:431-472for depth/stencil andTextureGL.cpp:525-585for color):// third_party/dawn/src/dawn/native/opengl/TextureGL.cpp:525-580 GLuint framebuffer = 0; DAWN_GL_TRY(gl, GenFramebuffers(1, &framebuffer)); DAWN_GL_TRY(gl, BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer)); ... DAWN_TRY(FramebufferTextureHelper(gl, mTarget, GL_DRAW_FRAMEBUFFER, attachment, GetTextureHandle(), level, layer)); DAWN_TRY(DoClear()); // Issues glClearBufferfv / glClearBufferuiv / glClearBufferiv -
Silent Failure in Release Builds: In release builds (
!defined(DAWN_ENABLE_ASSERTS)),DAWN_GL_TRY(gl, call)expands to(gl.call)(UtilsGL.h:85). Per OpenGL ES 3.2 §9.4.4, callingglClearBuffer*on an incomplete draw framebuffer generatesGL_INVALID_FRAMEBUFFER_OPERATIONand performs no write operation. The error is not checked and execution continues normally. -
Unconditional State Update: Regardless of whether the clear succeeded,
TextureGL.cpp:657-658unconditionally marks the subresource as initialized:if (clearValue == TextureBase::ClearValue::Zero) { SetIsSubresourceContentInitialized(true, range); device->IncrementLazyClearCountForTesting(); } -
Incomplete FBO Precondition:
Format.cpp:255-301marks floating-point formats (R16Float,RG16Float,RGBA16Float,R32Float,RG32Float,RGBA32Float) asCap::Renderableunconditionally. Meanwhile,PhysicalDeviceGL.cpp:161-164permits GLES 3.2 contexts without checking forGL_EXT_color_buffer_float, relying on a debug-only assertion atPhysicalDeviceGL.cpp:455-459. Under GLES 3.2 core specifications, float formats are not required to be color-renderable; on drivers withoutGL_EXT_color_buffer_float(or on drivers returningGL_FRAMEBUFFER_UNSUPPORTED), attaching a float texture yields an incomplete framebuffer, triggering this silent clear failure.
Potential Trigger Steps
(Note: These are potential steps based on source code analysis; our analysis tooling does not have code-execution capabilities to run live PoCs.)
- Run Chrome on an Android platform where WebGPU defaults to the OpenGLES backend (or where compatibility mode is active).
- From web JavaScript, request a WebGPU adapter and device.
- Create an uninitialized floating-point texture:
const tex = device.createTexture({format: 'rgba16float', size: [256, 256, 1], usage: GPUTextureUsage.TEXTURE_BINDING});. - Create a compute pipeline and shader that reads
texusing WGSLtextureLoad()and writes values into a storage buffer. - Encode and submit a command buffer executing the compute pass and copying the storage buffer to a mappable readback buffer.
- During submit,
LazyClearSyncScope(CommandBufferGL.cpp:849) invokesClearTexture(). On affected GLES drivers, the temporary FBO is incomplete,glClearBufferfvsilently no-ops, and Dawn marks the subresource initialized. - The compute shader executes and reads stale texel data from raw GPU driver memory.
- The web page calls
buffer.mapAsync(GPUMapMode.READ)to read the uninitialized GPU memory bytes.
Impact
Potential disclosure of uninitialized GPU process memory across origins to web JavaScript. On platforms such as Android where the GPU process is shared across origins and unsandboxed, leaked heap data may include other origins’ rendered graphics or GPU process internal memory.
Suggested Fix
- Add
DAWN_TRY(CheckFramebufferComplete(gl, GL_DRAW_FRAMEBUFFER));immediately following texture attachment inTexture::ClearTexture(TextureGL.cpp:467,TextureGL.cpp:573, andTextureGL.cpp:579), or - Fall back to CPU buffer upload via
DoTexSubImage(TextureGL.cpp:588-656) if the format is not confirmed to be color-renderable by the underlying GL driver. - Ensure
SetIsSubresourceContentInitialized(true, range)is only called after the clear has verifiably succeeded.
Evaluated with Chrome root at commit: c6718ebbf2c677c6f63691e28c7801c563f6b19c
Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:
- If you are familiar with the severity guidelines, you may adjust the severity.
- If this is a false positive, and there’s no work to be done, please close as WAI.
- If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.
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.