Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in Dawn
DescriptionUninitialized Use in Dawn
ComponentDawn
Bug ClassUninitialized Memory
Tracker513006745
Fix commitf629bb2bf26b (dawn) +1/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Files Changed

  • src/dawn/native/ApplyClearColorValueWithDrawHelper.h
From f629bb2bf26ba63b8d30a579c835e6a8b04121ed Mon Sep 17 00:00:00 2001
From: dneto <dneto@google.com>
Date: Fri, 15 May 2026 07:19:55 -0700
Subject: [PATCH] [native] Initialize all members of apply clear color value key

The struct is used in hash functions and key equality tests.
Ensure all members are initialized.

Fixed: 513006745
Change-Id: Id14674b1b7bd4c0168de05b7634a17556a6a6964
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/308857
Reviewed-by: Peter McNeeley <petermcneeley@google.com>
Commit-Queue: David Neto <dneto@google.com>
Auto-Submit: David Neto <dneto@google.com>
---

diff --git a/src/dawn/native/ApplyClearColorValueWithDrawHelper.h b/src/dawn/native/ApplyClearColorValueWithDrawHelper.h
index a45b24d..9139b2d 100644
--- a/src/dawn/native/ApplyClearColorValueWithDrawHelper.h
+++ b/src/dawn/native/ApplyClearColorValueWithDrawHelper.h
@@ -52,7 +52,7 @@
     uint32_t sampleCount = 0;
     wgpu::TextureFormat depthStencilFormat = wgpu::TextureFormat::Undefined;
     bool hasPLS = false;
-    uint64_t totalPixelLocalStorageSize;
+    uint64_t totalPixelLocalStorageSize = 0;
     std::vector<wgpu::PipelineLayoutStorageAttachment> plsAttachments;
 };
 
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential uninitialized memory read in Dawn pipeline cache key (ApplyClearColorValueWithDraw)

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 Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: The KeyOfApplyClearColorValueWithDrawPipelines struct in Dawn contains an uninitialized totalPixelLocalStorageSize field used in pipeline cache hash and equality operations. This allows indeterminate GPU-process stack residue to influence cache keys, potentially leading to unbounded memory exhaustion and a timing side-channel for stack information. The issue primarily affects platforms using draw-based clear workarounds, such as Windows D3D backends.

Affected files:

  • third_party/dawn/src/dawn/native/ApplyClearColorValueWithDrawHelper.h
  • third_party/dawn/src/dawn/native/ApplyClearColorValueWithDrawHelper.cpp
  • third_party/dawn/src/dawn/native/CommandEncoder.cpp
  • third_party/dawn/src/dawn/native/InternalPipelineStore.h

Estimated timestamp from git blame: 2024-09-12

Root Cause Analysis

In third_party/dawn/src/dawn/native/ApplyClearColorValueWithDrawHelper.h, the struct KeyOfApplyClearColorValueWithDrawPipelines is used as a key for caching internal pipelines. The struct defines totalPixelLocalStorageSize without a default member initializer:

struct KeyOfApplyClearColorValueWithDrawPipelines {
    uint8_t colorAttachmentCount = 0;
    PerColorAttachment<wgpu::TextureFormat> colorTargetFormats;
    ColorAttachmentMask colorTargetsToApplyClearColorValue;
    uint32_t sampleCount = 0;
    wgpu::TextureFormat depthStencilFormat = wgpu::TextureFormat::Undefined;
    bool hasPLS = false;
    uint64_t totalPixelLocalStorageSize;          // <--- Uninitialized
    std::vector<wgpu::PipelineLayoutStorageAttachment> plsAttachments;
};

Because the struct contains a std::vector, its implicitly-defined default constructor is non-trivial. It default-initializes members that have initializers (like hasPLS), but leaves primitive members like totalPixelLocalStorageSize with an indeterminate value if they are not explicitly initialized.

In third_party/dawn/src/dawn/native/CommandEncoder.cpp, the BeginRenderPass method stack-allocates a ClearWithDrawHelper object, which includes this key as a member. The initialization logic in GetKeyOfApplyClearColorValueWithDrawPipelines only assigns a value to totalPixelLocalStorageSize if a RenderPassPixelLocalStorage chained struct is provided in the render pass descriptor. When this struct is absent, totalPixelLocalStorageSize retains indeterminate stack residue.

The hash and equality functors for this key (used by InternalPipelineStore) read this field unconditionally:

// ApplyClearColorValueWithDrawHelper.cpp:511
HashCombine(&hash, key.totalPixelLocalStorageSize);

// ApplyClearColorValueWithDrawHelper.cpp:538
if (key1.hasPLS != key2.hasPLS ||
    key1.totalPixelLocalStorageSize != key2.totalPixelLocalStorageSize ||
    key1.plsAttachments.size() != key2.plsAttachments.size()) {
    return false;
}

Potential Impact

  1. Unbounded Internal Pipeline Cache Growth (DoS): When performing color clears that trigger the draw-based workaround (enabled by default on D3D11/D3D12 for large integer values), semantically identical render passes may result in different cache keys due to varying stack residue. This causes the per-device applyClearColorValueWithDrawPipelines map in InternalPipelineStore to grow indefinitely as new RenderPipelineBase objects are compiled and stored for each unique (but uninitialized) key, leading to memory exhaustion in the GPU process.

  2. Information Leak (Timing Side-Channel): Since a cache miss triggers a multi-millisecond shader compilation while a cache hit is significantly faster, a malicious renderer process can time beginRenderPass operations. This creates an equality oracle for 8 bytes of GPU-process stack memory residue.

Suggested Potential Reproduction Steps

  1. On a Windows machine using the D3D12 WebGPU backend, create a WebGPU device.
  2. Create a texture with an rgba32sint format and RENDER_ATTACHMENT usage.
  3. Repeatedly call commandEncoder.beginRenderPass with a clear value that triggers the workaround (e.g., 2147483647) without providing a RenderPassPixelLocalStorage struct.
  4. Observe the GPU process memory usage increasing or use high-resolution timing to detect cache hits/misses based on stack residue.

Suggested Fix

Initialize the totalPixelLocalStorageSize field in the struct definition in third_party/dawn/src/dawn/native/ApplyClearColorValueWithDrawHelper.h:

uint64_t totalPixelLocalStorageSize = 0;

Alternatively, modify the hash and equality functions to only access totalPixelLocalStorageSize when hasPLS is true.

Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e


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.

View on issue tracker