QL-Win/QuickLook · error · PEImageParseException
Data directories incomplete.
Error message
Data directories incomplete.
What it means
After the optional header, the PE format stores a data directory table consisting of NumberOfRvaAndSizes entries, each 8 bytes (a 4-byte RVA + 4-byte Size). The parser computes NumberOfRvaAndSizes * 8 and checks that many bytes remain; if not, the data directory table is truncated. The standard value for NumberOfRvaAndSizes is 16 (0x10) in modern PE images.
Source
Thrown at QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/PEImage.cs:198
SizeOfStackReserve = reader.ReadUInt64(),
SizeOfStackCommit = reader.ReadUInt64(),
SizeOfHeapReserve = reader.ReadUInt64(),
SizeOfHeapCommit = reader.ReadUInt64(),
LoaderFlags = reader.ReadUInt32(),
NumberOfRvaAndSizes = reader.ReadUInt32()
};
}
else if (magic == 0x107)
{
throw new PEImageParseException((int)reader.BaseStream.Position - 2, "Optional header for ROM's is not supported.");
}
else
{
throw new PEImageParseException((int)reader.BaseStream.Position - 2, "Optional header magic value of '0x" + magic.ToString("x4") + "' unknown.");
}
// Data Directories
if (reader.BaseStream.Length - reader.BaseStream.Position < OptionalHeader.NumberOfRvaAndSizes * 8) throw new PEImageParseException((int)reader.BaseStream.Position, "Data directories incomplete.");
OptionalHeader.DataDirectories = Create.Array((int)OptionalHeader.NumberOfRvaAndSizes, i => new ImageDataDirectory((ImageDataDirectoryName)i, reader.ReadUInt32(), reader.ReadUInt32()));
// Section Headers
if (reader.BaseStream.Length - reader.BaseStream.Position < CoffHeader.NumberOfSections * 40) throw new PEImageParseException((int)reader.BaseStream.Position, "Section headers incomplete.");
Sections = Create
.Enumerable(CoffHeader.NumberOfSections, i => new ImageSectionHeader
{
Name = reader.ReadBytes(8).TakeWhile(c => c != 0).ToArray().ToUTF8String(),
VirtualSize = reader.ReadUInt32(),
VirtualAddress = reader.ReadUInt32(),
SizeOfRawData = reader.ReadUInt32(),
PointerToRawData = reader.ReadUInt32(),
PointerToRelocations = reader.ReadUInt32(),
PointerToLineNumbers = reader.ReadUInt32(),
NumberOfRelocations = reader.ReadUInt16(),
NumberOfLineNumbers = reader.ReadUInt16(),View on GitHub (pinned to cb5d9c429c)
Solutions
- Inspect the file with a PE viewer to check whether NumberOfRvaAndSizes is a sane value (standard is 16)
- Re-acquire the file if it appears to be truncated
- Pre-validate by reading NumberOfRvaAndSizes from the optional header and sanity-checking it is <= 16 before full parsing
- Catch PEImageParseException for robust handling of malformed PE inputs
Defensive patterns
Strategy: validation
Validate before calling
// Sanity-check NumberOfRvaAndSizes (standard value is 16, max 16 per spec)
static bool HasValidRvaCount(string path)
{
byte[] b = File.ReadAllBytes(path);
if (b.Length < 0x40) return false;
int peOff = BitConverter.ToInt32(b, 0x3C);
int magicOff = peOff + 4 + 20;
if (magicOff + 2 > b.Length) return false;
ushort magic = BitConverter.ToUInt16(b, magicOff);
// NumberOfRvaAndSizes is the last 4 bytes of the fixed optional header
int rvaOff = magic == 0x20b ? magicOff + 108 : magicOff + 92;
if (rvaOff + 4 > b.Length) return false;
uint rvaCount = BitConverter.ToUInt32(b, rvaOff);
return rvaCount <= 16 && (long)b.Length - (rvaOff + 4) >= rvaCount * 8;
} Try / catch
try
{
var image = PEImage.FromFile(path);
}
catch (PEImageParseException ex) when (ex.Message.Contains("Data directories"))
{
// NumberOfRvaAndSizes is corrupt or file is truncated after optional header
logger.Warn($"Corrupt data directory table: {ex.Message} at offset {ex.Offset}");
} Prevention
- Sanity-check NumberOfRvaAndSizes before full parsing — the standard value is 16 and should never exceed 16
- Verify file integrity when processing untrusted PE files
- Treat an abnormally large NumberOfRvaAndSizes as evidence of corruption
When it happens
Trigger: OptionalHeader.NumberOfRvaAndSizes multiplied by 8 exceeds the remaining bytes in the stream. This can happen because the NumberOfRvaAndSizes field is corrupted to an abnormally large value, or because the file is physically truncated after the optional header.
Common situations: A corrupted NumberOfRvaAndSizes field (e.g. garbage data making it millions instead of 16); a file truncated after the optional header but before the data directory table; a malformed PE produced by a buggy or obfuscating toolchain.
Related errors
- Section headers incomplete.
- COFF header not found.
- COFF header incomplete.
- Optional header not found.
- Optional header incomplete.
AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13).
Data as JSON: /api/errors/fbbcbc1aa8e765fc.
Report an issue: GitHub.