Skip to content

Commit 494ebd6

Browse files
fix: validate SPIR-V magic number in shader_build to prevent Vulkan hang
Passing GLSL text with a SPIRV encoding caused buildShader to silently create a corrupt shader module. When shader_replace later called ReplaceResource → RefreshDerivedReplacements → vkCreateGraphicsPipelines with the invalid SPIR-V, the Vulkan driver would hang indefinitely, crashing the MCP server process. Add magic number (0x07230203) and minimum size validation for SPIRV and OpenGLSPIRV encodings, returning a clear error message that suggests using GLSL encoding instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ef29edb commit 494ebd6

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

src/core/shader_edit.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,33 @@ ShaderBuildResult buildShader(Session& session,
144144
throw CoreError(CoreError::Code::InternalError,
145145
"Unknown shader encoding: " + encoding);
146146

147+
// Validate SPIR-V binary encodings: source must start with the SPIR-V
148+
// magic number (0x07230203). Passing GLSL text with a SPIRV encoding
149+
// produces a corrupt shader module that can hang the Vulkan driver
150+
// during pipeline recreation in ReplaceResource.
151+
if (enc == ::ShaderEncoding::SPIRV ||
152+
enc == ::ShaderEncoding::OpenGLSPIRV) {
153+
constexpr uint32_t kSpirvMagic = 0x07230203;
154+
constexpr size_t kSpirvHeaderSize = 20; // 5 × uint32
155+
156+
if (source.size() < kSpirvHeaderSize) {
157+
throw CoreError(CoreError::Code::InternalError,
158+
"Source too small for SPIR-V binary (need >= 20 bytes, got " +
159+
std::to_string(source.size()) + "). "
160+
"If this is GLSL text, use encoding \"GLSL\" instead of \"" +
161+
encoding + "\".");
162+
}
163+
164+
uint32_t magic = 0;
165+
std::memcpy(&magic, source.data(), sizeof(magic));
166+
if (magic != kSpirvMagic) {
167+
throw CoreError(CoreError::Code::InternalError,
168+
"Source does not start with SPIR-V magic number (0x07230203). "
169+
"If this is GLSL text, use encoding \"GLSL\" instead of \"" +
170+
encoding + "\".");
171+
}
172+
}
173+
147174
bytebuf sourceBytes;
148175
sourceBytes.assign((const byte*)source.data(), source.size());
149176

0 commit comments

Comments
 (0)