QL-Win/QuickLook · error · PEImageParseException

Optional header incomplete.

Error message

Optional header incomplete.

What it means

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.

Source

Thrown at QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/PEImage.cs:117

        CoffHeader = new()
        {
            Machine = (ImageMachineType)reader.ReadUInt16(),
            NumberOfSections = reader.ReadUInt16(),
            TimeDateStamp = reader.ReadUInt32(),
            PointerToSymbolTable = reader.ReadUInt32(),
            NumberOfSymbols = reader.ReadUInt32(),
            SizeOfOptionalHeader = reader.ReadUInt16(),
            Characteristics = (ImageCharacteristics)reader.ReadUInt16()
        };

        // Optional Header
        if (reader.BaseStream.Length - reader.BaseStream.Position < 2) throw new PEImageParseException((int)reader.BaseStream.Position, "Optional header not found.");
        ushort magic = reader.ReadUInt16();

        if (magic == 0x10b)
        {
            if (reader.BaseStream.Length - reader.BaseStream.Position < 94) throw new PEImageParseException((int)reader.BaseStream.Position, "Optional header incomplete.");

            OptionalHeader = new ImageOptionalHeader32
            {
                MajorLinkerVersion = reader.ReadByte(),
                MinorLinkerVersion = reader.ReadByte(),
                SizeOfCode = reader.ReadUInt32(),
                SizeOfInitializedData = reader.ReadUInt32(),
                SizeOfUninitializedData = reader.ReadUInt32(),
                AddressOfEntryPoint = reader.ReadUInt32(),
                BaseOfCode = reader.ReadUInt32(),
                BaseOfData = reader.ReadUInt32(),
                ImageBase = reader.ReadUInt32(),
                SectionAlignment = reader.ReadUInt32(),
                FileAlignment = reader.ReadUInt32(),
                MajorOperatingSystemVersion = reader.ReadUInt16(),
                MinorOperatingSystemVersion = reader.ReadUInt16(),
                MajorImageVersion = reader.ReadUInt16(),
                MinorImageVersion = reader.ReadUInt16(),

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. Re-acquire the 32-bit binary from its source and verify the file size and hash match the original
  2. Pre-check that the file length is at least PEHeaderOffset + 4 (signature) + 20 (COFF) + 96 (PE32 optional header) before parsing
  3. Catch PEImageParseException and treat the file as corrupt rather than crashing
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify enough bytes for PE32 optional header (96 bytes total)
static bool IsLargeEnoughForPE32Optional(string path)
{
    byte[] b = File.ReadAllBytes(path);
    if (b.Length < 0x40) return false;
    int peOff = BitConverter.ToInt32(b, 0x3C);
    int optStart = peOff + 4 + 20; // after PE sig + COFF header
    return b.Length >= optStart + 96; // 2 magic + 94 fields
}

Try / catch

try
{
    var image = PEImage.FromFile(path);
}
catch (PEImageParseException ex) when (ex.Message == "Optional header incomplete.")
{
    // File truncated mid-optional-header (PE32 or PE32+)
    logger.Warn($"Truncated optional header at offset {ex.Offset}");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13). Data as JSON: /api/errors/ae8d6b96dda01053. Report an issue: GitHub.