{"record":{"id":"46dd07faca43f39e","repo":"t8y2/dbx","slug":"missing-dos-header","errorCode":null,"errorMessage":"missing DOS header","messagePattern":"missing DOS header","errorType":"exception","errorClass":"PeFormatError","httpStatus":null,"severity":"error","filePath":"agents/scripts/validate_windows_pe_dependencies.py","lineNumber":39,"sourceCode":"    return struct.unpack_from(\"<I\", data, offset)[0]\n\n\ndef _read_c_string(data: bytes, offset: int) -> str:\n    if offset < 0 or offset >= len(data):\n        raise PeFormatError(\"PE string offset is outside the file\")\n    end = data.find(b\"\\0\", offset)\n    if end < 0:\n        raise PeFormatError(\"unterminated PE string\")\n    try:\n        return data[offset:end].decode(\"ascii\")\n    except UnicodeDecodeError as error:\n        raise PeFormatError(\"PE import name is not ASCII\") from error\n\n\ndef imported_dlls(path: Path) -> list[str]:\n    data = path.read_bytes()\n    if len(data) < 64 or data[:2] != b\"MZ\":\n        raise PeFormatError(\"missing DOS header\")\n\n    pe_offset = _read_u32(data, 0x3C)\n    if data[pe_offset : pe_offset + 4] != b\"PE\\0\\0\":\n        raise PeFormatError(\"missing PE signature\")\n\n    section_count = _read_u16(data, pe_offset + 6)\n    optional_header_size = _read_u16(data, pe_offset + 20)\n    optional_header_offset = pe_offset + 24\n    optional_magic = _read_u16(data, optional_header_offset)\n    if optional_magic == 0x20B:\n        data_directories_offset = optional_header_offset + 112\n    elif optional_magic == 0x10B:\n        data_directories_offset = optional_header_offset + 96\n    else:\n        raise PeFormatError(f\"unsupported PE optional header magic: 0x{optional_magic:04x}\")\n\n    import_directory_rva = _read_u32(data, data_directories_offset + 8)\n    import_directory_size = _read_u32(data, data_directories_offset + 12)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/scripts/validate_windows_pe_dependencies.py#L21-L57","documentation":"PeFormatError raised by imported_dlls when the file is shorter than 64 bytes or does not start with the b\"MZ\" DOS magic. Every Windows PE must begin with an MZ DOS stub containing at least a 64-byte header that holds the PE-offset pointer at 0x3C; without it the file is not a PE and cannot be parsed at all.","triggerScenarios":"Calling imported_dlls(path) (directly or via main / the validator CLI) on: a text file, an ELF/Mach-O binary, an empty or near-empty file, a script, or any file whose first two bytes are not 'MZ'.","commonSituations":"Pointing the validator at the wrong build artifact (e.g. a Linux .so in cross-platform CI), passing a source file or config instead of a compiled exe, running on a zero-byte placeholder created by a failed build, or validating a renamed non-Windows binary.","solutions":["Check that the path points to an actual Windows PE (.exe/.dll/.sys) built for Windows; verify first bytes are 'MZ' (e.g. `head -c2 file`).","Fix the build/CI artifact path — the file is likely a Linux binary or an empty/failed build output.","Catch PeFormatError around imported_dlls and report 'not a Windows PE' to the user.","If the file should be a PE, rebuild it; a 0–63 byte file means the build or download failed."],"exampleFix":"# before\nimports = imported_dlls(Path(args.file))\n# after\nif not args.file.is_file() or args.file.read_bytes()[:2] != b\"MZ\":\n    raise SystemExit(f\"{args.file} is not a Windows PE\")\nimports = imported_dlls(args.file)","handlingStrategy":"validation","validationCode":"def ensure_pe_file(path: Path) -> None:\n    if not path.is_file():\n        raise SystemExit(f\"{path}: not a file\")\n    data = path.read_bytes()\n    if len(data) < 64 or data[:2] != b\"MZ\":\n        raise SystemExit(f\"{path}: not a Windows PE (missing MZ header)\")","typeGuard":"def is_pe_candidate(path: Path) -> bool:\n    try:\n        with path.open(\"rb\") as f:\n            return f.read(2) == b\"MZ\" and path.stat().st_size >= 64\n    except OSError:\n        return False","tryCatchPattern":"try:\n    imports = imported_dlls(path)\nexcept PeFormatError as error:\n    if \"missing DOS header\" in str(error):\n        print(f\"{path} is not a Windows PE; check the artifact path\")\n    else:\n        raise","preventionTips":["Check `file <artifact>` output says PE32/PE32+ before running Windows-specific validators","Verify the build actually produced the exe (non-empty, expected size) before validation steps","In cross-platform CI, select the Windows artifact explicitly rather than by extension","Guard the call with a 2-byte MZ magic read to fail fast with a clear message"],"tags":["pe","file-format","input-validation","wrong-file-type"],"backgroundTag":"not-a-pe-file","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}