{"record":{"id":"ae8d6b96dda01053","repo":"QL-Win/QuickLook","slug":"optional-header-incomplete","errorCode":null,"errorMessage":"Optional header incomplete.","messagePattern":"Optional header incomplete\\.","errorType":"exception","errorClass":"PEImageParseException","httpStatus":null,"severity":"error","filePath":"QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/PEImage.cs","lineNumber":117,"sourceCode":"\n        CoffHeader = new()\n        {\n            Machine = (ImageMachineType)reader.ReadUInt16(),\n            NumberOfSections = reader.ReadUInt16(),\n            TimeDateStamp = reader.ReadUInt32(),\n            PointerToSymbolTable = reader.ReadUInt32(),\n            NumberOfSymbols = reader.ReadUInt32(),\n            SizeOfOptionalHeader = reader.ReadUInt16(),\n            Characteristics = (ImageCharacteristics)reader.ReadUInt16()\n        };\n\n        // Optional Header\n        if (reader.BaseStream.Length - reader.BaseStream.Position < 2) throw new PEImageParseException((int)reader.BaseStream.Position, \"Optional header not found.\");\n        ushort magic = reader.ReadUInt16();\n\n        if (magic == 0x10b)\n        {\n            if (reader.BaseStream.Length - reader.BaseStream.Position < 94) throw new PEImageParseException((int)reader.BaseStream.Position, \"Optional header incomplete.\");\n\n            OptionalHeader = new ImageOptionalHeader32\n            {\n                MajorLinkerVersion = reader.ReadByte(),\n                MinorLinkerVersion = reader.ReadByte(),\n                SizeOfCode = reader.ReadUInt32(),\n                SizeOfInitializedData = reader.ReadUInt32(),\n                SizeOfUninitializedData = reader.ReadUInt32(),\n                AddressOfEntryPoint = reader.ReadUInt32(),\n                BaseOfCode = reader.ReadUInt32(),\n                BaseOfData = reader.ReadUInt32(),\n                ImageBase = reader.ReadUInt32(),\n                SectionAlignment = reader.ReadUInt32(),\n                FileAlignment = reader.ReadUInt32(),\n                MajorOperatingSystemVersion = reader.ReadUInt16(),\n                MinorOperatingSystemVersion = reader.ReadUInt16(),\n                MajorImageVersion = reader.ReadUInt16(),\n                MinorImageVersion = reader.ReadUInt16(),","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/QL-Win/QuickLook/blob/cb5d9c429c81d9796fac469da2a68efb5626946d/QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/PEImage.cs#L99-L135","documentation":"When the optional header magic is 0x10b (PE32, 32-bit image), the fixed portion of the optional header is 96 bytes total — 2 bytes of magic plus 94 bytes of fields. The parser checks that at least 94 bytes remain after the magic; if fewer remain, the PE32 optional header is incomplete and fields such as ImageBase, SectionAlignment, SizeOfImage, and NumberOfRvaAndSizes cannot be safely read. The exception Offset is the position right after the magic.","triggerScenarios":"The optional header magic was read as 0x10b but the stream has fewer than 94 bytes left. The file is a 32-bit PE that is truncated in the middle of its optional header, after the magic but before all 94 remaining fields are present.","commonSituations":"A 32-bit .exe or .dll truncated during download or transfer, cut off within the optional header region; a malformed or crafted binary with a valid PE32 magic but an incomplete optional header body.","solutions":["Re-acquire the 32-bit binary from its source and verify the file size and hash match the original","Pre-check that the file length is at least PEHeaderOffset + 4 (signature) + 20 (COFF) + 96 (PE32 optional header) before parsing","Catch PEImageParseException and treat the file as corrupt rather than crashing"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify enough bytes for PE32 optional header (96 bytes total)\nstatic bool IsLargeEnoughForPE32Optional(string path)\n{\n    byte[] b = File.ReadAllBytes(path);\n    if (b.Length < 0x40) return false;\n    int peOff = BitConverter.ToInt32(b, 0x3C);\n    int optStart = peOff + 4 + 20; // after PE sig + COFF header\n    return b.Length >= optStart + 96; // 2 magic + 94 fields\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var image = PEImage.FromFile(path);\n}\ncatch (PEImageParseException ex) when (ex.Message == \"Optional header incomplete.\")\n{\n    // File truncated mid-optional-header (PE32 or PE32+)\n    logger.Warn($\"Truncated optional header at offset {ex.Offset}\");\n}","preventionTips":["Verify file integrity via hash before parsing 32-bit PE images","Pre-check file size is at least PEHeaderOffset + 120 bytes (sig + COFF + PE32 optional header)","Treat PEImageParseException as a signal of a corrupt or incomplete file"],"tags":["pe-format","binary-parsing","truncated-file","pe32"],"backgroundTag":null,"analyzedSha":"cb5d9c429c81d9796fac469da2a68efb5626946d","analyzedAt":"2026-08-13T11:51:01.370Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}