t8y2/dbx · error · PeFormatError
PE import descriptor table is not terminated
Error message
PE import descriptor table is not terminated
What it means
A PE import descriptor array must end with an all-zero (20-byte) terminator. The parser walks at most 4096 descriptors; if it exhausts that bound without hitting the terminator, it raises this error. This guards against runaway or cyclic descriptor tables that would otherwise cause unbounded parsing.
Source
Thrown at agents/scripts/validate_windows_pe_dependencies.py:101
break
return raw_offset + delta
raise PeFormatError(f"PE RVA 0x{rva:x} is not backed by file data")
descriptor_offset = rva_to_offset(import_directory_rva)
imports = []
for _ in range(4096):
if descriptor_offset + 20 > len(data):
raise PeFormatError("truncated PE import descriptor")
descriptor = data[descriptor_offset : descriptor_offset + 20]
if descriptor == b"\0" * 20:
return sorted(set(imports), key=str.casefold)
name_rva = _read_u32(data, descriptor_offset + 12)
if name_rva == 0:
raise PeFormatError("PE import descriptor has no DLL name")
imports.append(_read_c_string(data, rva_to_offset(name_rva)))
descriptor_offset += 20
raise PeFormatError("PE import descriptor table is not terminated")
def forbidden_msvc_runtime_dlls(imports: list[str]) -> list[str]:
return sorted(
{name for name in imports if name.casefold().startswith(("msvcp", "vcruntime"))},
key=str.casefold,
)
def main() -> int:
parser = argparse.ArgumentParser(description="Reject Windows PE files that require the Visual C++ runtime")
parser.add_argument("binary", type=Path)
args = parser.parse_args()
try:
imports = imported_dlls(args.binary)
except (OSError, PeFormatError) as error:
parser.error(str(error))View on GitHub (pinned to c0390bff16)
Solutions
- Check the real import count with dumpbin /imports or pefile; if it exceeds 4096, raise the loop bound in the script.
- Verify the import directory RVA/size (data directory index 1) actually points at a descriptor array; a wrong RVA makes the terminator unreachable.
- Rebuild the binary with a standard linker; a missing terminator indicates a malformed or hand-patched import table.
- Treat the file as unverifiable: catch PeFormatError and fail the specific artifact rather than the whole batch.
Example fix
// before
for _ in range(4096):
...
raise PeFormatError("PE import descriptor table is not terminated")
// after
max_descriptors = import_directory_size // 20
for _ in range(max_descriptors):
... Defensive patterns
Strategy: validation
Validate before calling
import pefile
def import_count_within_limits(path, max_descriptors: int = 4096) -> bool:
pe = pefile.PE(path)
return len(getattr(pe, "DIRECTORY_ENTRY_IMPORT", [])) <= max_descriptors Try / catch
try:
imports = imported_dlls(path)
except PeFormatError as err:
if "not terminated" in str(err):
fail_artifact(path, "unterminated or oversized import table")
else:
raise Prevention
- If you link binaries with thousands of imports, raise the 4096 descriptor bound before validating.
- Confirm the import directory RVA points at actual descriptor data (index 1 of the data directories).
- Sanity-check that the last descriptor read via pefile is the zero terminator.
- Treat fuzzed/untrusted samples in a sandbox with pre-validation via pefile.
When it happens
Trigger: imported_dlls(path) on a PE with more than 4096 import descriptors, or with a descriptor array that never contains the all-zero terminator (corrupt/forged import directory RVA pointing at non-descriptor data, or a crafted cyclic table).
Common situations: Extremely large binaries linking thousands of DLLs (rare but possible in monolithic builds); deliberately malformed PE samples; import directory RVA pointing into unrelated data so terminator bytes never appear; automated fuzzing corpora.
Related errors
- truncated PE import descriptor
- PE import descriptor has no DLL name
- unexpected end of PE file
- unsupported PE optional header magic: 0x{optional_magic:04x}
- PE RVA 0x{rva:x} is not backed by file data
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/2ddb7175ad4cdce3.
Report an issue: GitHub.