t8y2/dbx · error · PeFormatError
missing PE signature
Error message
missing PE signature
What it means
PeFormatError raised by imported_dlls when the 4-byte signature at the offset stored in the DOS header (epe_offset, read from 0x3C) is not b"PE\0\0". The file has a valid MZ stub but the DOS-header e_lfanew pointer does not lead to a PE signature, so it is not a parseable Windows PE (it may be an old DOS executable or a corrupted/patched file).
Source
Thrown at agents/scripts/validate_windows_pe_dependencies.py:43
if offset < 0 or offset >= len(data):
raise PeFormatError("PE string offset is outside the file")
end = data.find(b"\0", offset)
if end < 0:
raise PeFormatError("unterminated PE string")
try:
return data[offset:end].decode("ascii")
except UnicodeDecodeError as error:
raise PeFormatError("PE import name is not ASCII") from error
def imported_dlls(path: Path) -> list[str]:
data = path.read_bytes()
if len(data) < 64 or data[:2] != b"MZ":
raise PeFormatError("missing DOS header")
pe_offset = _read_u32(data, 0x3C)
if data[pe_offset : pe_offset + 4] != b"PE\0\0":
raise PeFormatError("missing PE signature")
section_count = _read_u16(data, pe_offset + 6)
optional_header_size = _read_u16(data, pe_offset + 20)
optional_header_offset = pe_offset + 24
optional_magic = _read_u16(data, optional_header_offset)
if optional_magic == 0x20B:
data_directories_offset = optional_header_offset + 112
elif optional_magic == 0x10B:
data_directories_offset = optional_header_offset + 96
else:
raise PeFormatError(f"unsupported PE optional header magic: 0x{optional_magic:04x}")
import_directory_rva = _read_u32(data, data_directories_offset + 8)
import_directory_size = _read_u32(data, data_directories_offset + 12)
if import_directory_rva == 0 or import_directory_size == 0:
return []
size_of_headers = _read_u32(data, optional_header_offset + 60)View on GitHub (pinned to c0390bff16)
Solutions
- Confirm the file is a real PE with `file binary.exe` — output should say 'PE32'/'PE32+', not 'MS-DOS executable'.
- Rebuild or re-obtain the binary; a broken e_lfanew usually means corruption or an incomplete build/pack step.
- If the file is intentionally DOS-only, exclude it from Windows PE dependency validation.
- Catch PeFormatError and fail gracefully in CI with a clear 'missing PE signature' message.
Example fix
// before
result = subprocess.run(["python", "validate_windows_pe_dependencies.py", binary])
// after
result = subprocess.run(["python", "validate_windows_pe_dependencies.py", binary])
if "missing PE signature" in result.stderr:
raise SystemExit(f"{binary} is not a valid Windows PE (bad e_lfanew)") Defensive patterns
Strategy: validation
Validate before calling
import struct
data = path.read_bytes()
if len(data) >= 64 and data[:2] == b"MZ":
pe_offset = struct.unpack_from("<I", data, 0x3C)[0]
if data[pe_offset:pe_offset + 4] != b"PE\0\0":
raise SystemExit(f"{path}: DOS header present but no PE signature (e_lfanew=0x{pe_offset:x})") Type guard
def has_pe_signature(data: bytes) -> bool:
if len(data) < 64 or data[:2] != b"MZ":
return False
pe_offset = int.from_bytes(data[0x3C:0x40], "little")
return pe_offset + 4 <= len(data) and data[pe_offset:pe_offset + 4] == b"PE\0\0" Try / catch
try:
imports = imported_dlls(path)
except PeFormatError as error:
if "missing PE signature" in str(error):
print(f"{path} is a DOS executable or corrupt PE; skipping")
else:
raise Prevention
- Run `file` on artifacts and require PE32/PE32+ output in CI gating
- Never hand-patch e_lfanew; regenerate the binary instead
- Exclude genuine DOS-era executables from PE import validation by design
- Use pefile.PE() as a pre-flight parser to catch header corruption with better diagnostics
When it happens
Trigger: imported_dlls(path) reads _read_u32(data, 0x3C) and slices data[pe_offset:pe_offset+4] on a classic MS-DOS executable, a file whose e_lfanew was overwritten, a PE whose stub was modified by packers/protectors, or a text file that merely starts with 'MZ'.
Common situations: Validating genuine DOS-era .exe/.com files that lack a PE header, binaries mangled by a hex edit or bad patch, files processed by tools that rewrote e_lfanew incorrectly, or scripts that fabricate an MZ header without updating the PE pointer.
Related errors
- missing DOS header
- PE string offset is outside the file
- unterminated PE string
- PE import name is not ASCII
- unsupported PE optional header magic: 0x{optional_magic:04x}
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/b11425cedcc44834.
Report an issue: GitHub.