QL-Win/QuickLook · error · PEImageParseException

DOS header incomplete.

Error message

DOS header incomplete.

What it means

Thrown when, after the 'MZ' mark, fewer than 64 bytes remain in the stream — insufficient to hold the full IMAGE_DOS_HEADER (which is 64 bytes). PEImageParseException records the current position. The file started as an executable but is too short to contain the DOS header it claims to need.

Source

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

    public ImageOptionalHeader OptionalHeader { get; private set; }

    /// <summary>
    /// Gets the collection of section headers and data of this PE image file.
    /// </summary>
    public ImageSection[] Sections { get; private set; }

    private PEImage(byte[] originalImage)
    {
        OriginalImage = originalImage;

        using BinaryReader reader = new(new MemoryStream(OriginalImage));

        // MZ
        if (reader.BaseStream.Length < 2) throw new PEImageParseException(0, "DOS signature not found.");
        if (reader.ReadUInt16() != 0x5a4d) throw new PEImageParseException(0, "DOS header not found.");

        // DOS Header
        if (reader.BaseStream.Length - reader.BaseStream.Position < 64) throw new PEImageParseException((int)reader.BaseStream.Position, "DOS header incomplete.");

        DosHeader = new()
        {
            LastPageSize = reader.ReadUInt16(),
            PageCount = reader.ReadUInt16(),
            RelocationCount = reader.ReadUInt16(),
            HeaderSize = reader.ReadUInt16(),
            MinAlloc = reader.ReadUInt16(),
            MaxAlloc = reader.ReadUInt16(),
            InitialSS = reader.ReadUInt16(),
            InitialSP = reader.ReadUInt16(),
            Checksum = reader.ReadUInt16(),
            InitialIP = reader.ReadUInt16(),
            InitialCS = reader.ReadUInt16(),
            RelocationOffset = reader.ReadUInt16(),
            OverlayNumber = reader.ReadUInt16(),
            Reserved1 = reader.ReadUInt16(),
            Reserved2 = reader.ReadUInt16(),

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. Pre-check that the file is at least 64 bytes before constructing PEImage.
  2. If the file is expected to be a real PE, re-acquire it — truncation here means it cannot be valid.
  3. Catch PEImageParseException and report 'incomplete DOS header / not a valid PE'.
  4. Validate download integrity (size/hash) before parsing.

Example fix

// before
if (reader.BaseStream.Length - reader.BaseStream.Position < 64) throw new PEImageParseException((int)reader.BaseStream.Position, "DOS header incomplete.");

// after — single upfront size guard
if (reader.BaseStream.Length < 64) return null;
Defensive patterns

Strategy: validation

Validate before calling

if (new FileInfo(path).Length < 64) return; // cannot contain a full DOS header

Type guard

static bool HasFullDosHeader(long len) => len >= 64;

Try / catch

try { var img = PEImage.FromFile(path); }
catch (PEImageParseException ex) when (ex.Message.Contains("DOS header incomplete")) { /* truncated PE */ }

Prevention

When it happens

Trigger: reader.BaseStream.Length - reader.BaseStream.Position < 64 immediately after consuming the 2-byte 'MZ' magic — e.g. a 3–65 byte file, or a stream truncated just past the magic.

Common situations: A stub/sentinel file that begins with 'MZ' but is incomplete; a PE truncated during copy; a deliberately malformed 'MZ' file used as a marker; an SFX header fragment.

Related errors


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