{"record":{"id":"72b48b911794ea54","repo":"stride3d/stride","slug":"invalid-spir-v-instruction","errorCode":null,"errorMessage":"Invalid SPIR-V instruction","messagePattern":"Invalid SPIR-V instruction","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Tests/SpirvProbe.cs","lineNumber":52,"sourceCode":"\n    public List<EntryPointInfo> EntryPoints { get; } = [];\n    public Dictionary<uint, uint> Locations { get; } = [];\n    public Dictionary<uint, string> UserSemantics { get; } = [];\n    public HashSet<uint> BuiltIns { get; } = [];\n    public Dictionary<uint, uint> VariableStorageClasses { get; } = [];\n\n    public SpirvProbe(ReadOnlySpan<byte> spirv)\n    {\n        var words = MemoryMarshal.Cast<byte, uint>(spirv);\n        if (words.Length < 5 || words[0] != 0x07230203)\n            throw new InvalidOperationException(\"Not a SPIR-V module\");\n\n        for (int i = 5; i < words.Length;)\n        {\n            var wordCount = (int)(words[i] >> 16);\n            var opcode = words[i] & 0xFFFF;\n            if (wordCount == 0)\n                throw new InvalidOperationException(\"Invalid SPIR-V instruction\");\n            var operands = words.Slice(i + 1, wordCount - 1);\n\n            switch (opcode)\n            {\n                case OpEntryPoint:\n                {\n                    var name = ReadString(operands.Slice(2), out var nameWords);\n                    EntryPoints.Add(new EntryPointInfo(operands[0], name, operands.Slice(2 + nameWords).ToArray()));\n                    break;\n                }\n                case OpVariable:\n                    VariableStorageClasses[operands[1]] = operands[2];\n                    break;\n                case OpDecorate:\n                    switch (operands[1])\n                    {\n                        case DecorationLocation:\n                            Locations[operands[0]] = operands[2];","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Tests/SpirvProbe.cs#L34-L70","documentation":"Thrown during SpirvProbe's instruction walk when an instruction header declares a word count of zero. SPIR-V requires every instruction's high 16 bits (wordCount) to be at least 1 (the opcode word itself); a zero means the module is corrupt or the parse position has desynchronized.","triggerScenarios":"Parsing a truncated or corrupted .spv file where the offset lands on a word whose upper 16 bits are 0; manually patched/relocated SPIR-V that broke instruction boundaries; a header-valid module whose body was cut short so trailing garbage is read as a header.","commonSituations":"Incomplete file downloads or partial writes producing truncated SPIR-V; byte-level post-processing (e.g. stripping or obfuscation tools) corrupting instruction lengths; hand-crafted fuzz inputs in tests.","solutions":["Regenerate or re-download the SPIR-V module — the file is truncated/corrupted; compare checksums against the build output.","Validate the module with spirv-val before probing to pinpoint where the layout breaks.","Re-run the shader compiler without lossy post-processing steps that rewrite instruction sizes."],"exampleFix":"// before\nvar probe = new SpirvProbe(truncatedBytes);\n// after\nif (!SpirvValidator.IsValid(truncatedBytes)) // e.g. spirv-val\n    throw new InvalidOperationException(\"SPIR-V module is corrupt; recompile shader\");\nvar probe = new SpirvProbe(truncatedBytes);","handlingStrategy":"validation","validationCode":"static bool HasValidLayout(ReadOnlySpan<byte> spirv)\n{\n    var words = MemoryMarshal.Cast<byte, uint>(spirv);\n    if (words.Length < 5) return false;\n    int i = 5;\n    while (i < words.Length)\n    {\n        int wc = (int)(words[i] >> 16);\n        if (wc == 0) return false;\n        i += wc;\n    }\n    return i == words.Length;\n}","typeGuard":null,"tryCatchPattern":"try { var probe = new SpirvProbe(bytes); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Invalid SPIR-V instruction\")\n{\n    // module is corrupt/truncated — recompile or re-fetch the artifact\n}","preventionTips":["Run spirv-val on generated modules in CI before use.","Avoid lossy byte-level post-processing of SPIR-V (strippers/obfuscators) without revalidation.","Verify artifact integrity (size/checksum) when shaders come from network or shared storage."],"tags":["spirv","parsing","corrupt-data"],"backgroundTag":"schema-validation-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}