preprocessor: guard against OOB read in handlePragma for #pragma STDGL#4342
Conversation
5b81b71 to
1032879
Compare
|
Hi @arcady-lunarg @jeremy-lunarg @saddamr3e — this PR adds a bounds check in |
arcady-lunarg
left a comment
There was a problem hiding this comment.
You're going to need to add your test to the appropriate list of tests and add an expected result file so the test is actually run.
When a shader contains '#pragma STDGL' with fewer than 4 tokens, the
condition at ParseHelper.cpp:422 accessed tokens[1] and tokens[3]
without first checking tokens.size(), causing an out-of-bounds read
and a SEGV under AddressSanitizer.
Every other tokens[N] access in handlePragma() already has an explicit
size check (see lines 340, 366). Apply the same guard here:
} else if (spvVersion.spv > 0 && tokens[0].compare("STDGL") == 0 &&
tokens.size() >= 4 &&
tokens[1].compare("invariant") == 0 &&
tokens[3].compare("all") == 0) {
Minimal reproducer (15 bytes, requires Vulkan/SPIR-V target):
#pragma STDGL
Found by libFuzzer + ASan on fuzz_glslang_direct harness.
Fixes: SEGV in glslang::TParseContext::handlePragma() (ParseHelper.cpp:422)
1032879 to
8bf014d
Compare
|
Hi @arcady-lunarg — addressed your feedback:
Without the fix, the test crashes (SIGSEGV / exit 139) under Vulkan semantics. With it, it compiles to a minimal SPIR-V module cleanly. Force-pushed to update the PR. |
arcady-lunarg
left a comment
There was a problem hiding this comment.
The parsing of this pragma syntax is really not very robust but that's a pre-existing problem that should probably be a separate fix, so I'm inclined to merge this
Summary
Fixes an out-of-bounds heap read (SEGV) in
glslang::TParseContext::handlePragma()atParseHelper.cpp:422when a shader contains#pragma STDGLwith fewer than 4 tokens.Confirmed crash in production (non-ASan) builds — not a sanitizer-only artifact. The
_M_pfield of the out-of-boundsstd::stringobject always resolves to a non-readable address (NULL under standard allocator; code-segment address under the pool allocator), causingmemcmp()to SEGV without any sanitizer involvement.Also reproducible via the OSS-Fuzz target
shaderc_general_fuzzer(google/shaderc) with a 34-byte input.Root Cause
The condition at line 422 accesses
tokens[1]andtokens[3]without first checkingtokens.size():Every other
tokens[N]access inhandlePragma()has an explicit size check (lines 340, 366). This branch was the only exception.For input
#pragma STDGLwith no trailing tokens:tokens={"STDGL"}→tokens.size() == 1tokens[1]→ OOB heap read (32 bytes past vector end)tokens[3]→ OOB heap read (96 bytes past vector end)Fix
Reproducer
Via glslang directly (requires
setEnvClient(EShClientVulkan))#pragma STDGLVia shaderc / OSS-Fuzz
shaderc_general_fuzzer(34-byte input)ASan output
Production crash (no sanitizer)
Test
Added
Test/pragma.stdgl.oob.vertcovering the three short-token forms that previously triggered the crash.