forked from arti/vt1200
The TFTP font path loads through 3F96B850 and parses with the metadata reader 3F97EF00, which handles only PROPERTIES/ACCELERATORS/METRICS/ ENCODINGS and silently skips BITMAPS. A font with num_chars=0x40000001 therefore passes the loader (LOADER-A-SUCCESS) without the field ever being read, and pcfReadBitmaps (3F984970, multiply 3F985050) is never entered. pcfReadBitmaps has exactly one caller, 3F98BB70, in the X11 font-request reader 3F98AC20, not the TFTP fetch path. The 'refused after 1024 bytes' of evil-real.pcf is the METRICS table: its big-endian compressed count 0x00DF is read little-endian as 57088, so fosAlloc(57088*16) fails at ~906 bytes; BITMAPS (offset 2024) is never reached. Baseline.pcf fails the same way; baseline_le.pcf puts that one 2-byte field in the order the loader reads it, parses cleanly, and still ignores the crafted BITMAPS count. No ROM patch, no check disabled, no serve.py edit. Baselines unchanged: no env samples=198, stub samples=53.
57 lines
2.1 KiB
Python
57 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the two PCF candidates used in PCF_VALIDATION_REPORT.md.
|
|
|
|
`baseline_le.pcf` is the project's valid 680-byte font with ONE change: the
|
|
compressed-metrics count in the METRICS table is byte-swapped from `00 01`
|
|
(big-endian 1, what bdftopcf emits) to `01 00`. The VT1200's font loader reads
|
|
that INT16 raw (little-endian), so the stock file is read as 0x0100 = 256
|
|
characters and the metrics parse runs off the end of the table. The swap makes
|
|
the loader read the intended count of 1. It is a construction of a font the
|
|
loader accepts, not a disabled check.
|
|
|
|
`baseline_le_evil.pcf` is that font with the BITMAPS `num_chars` set to
|
|
0x40000001 (the value overflow.lua used) -- to show the loaded path ignores it.
|
|
|
|
python3 harness/mame/pcfwork/make_candidates.py
|
|
"""
|
|
import os
|
|
import struct
|
|
import sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(HERE)))
|
|
sys.path.insert(0, os.path.join(ROOT, "tools"))
|
|
import fontgen # noqa: E402
|
|
|
|
SRC = os.path.join(ROOT, "reference", "fonts", "baseline.pcf")
|
|
|
|
|
|
def main():
|
|
with open(SRC, "rb") as fh:
|
|
data = bytearray(fh.read())
|
|
|
|
metrics = fontgen.find_table(bytes(data), fontgen.METRICS)
|
|
if metrics is None:
|
|
raise SystemExit("baseline.pcf has no METRICS table")
|
|
off = metrics["offset"]
|
|
fmt = struct.unpack_from("<I", data, off)[0]
|
|
if (fmt & 0xFFFFFF00) != 0x100:
|
|
raise SystemExit(f"METRICS format 0x{fmt:x} is not compressed (0x100)")
|
|
# compressed-metrics body: format CARD32, then count INT16, then INT8 fields
|
|
data[off + 4], data[off + 5] = data[off + 5], data[off + 4]
|
|
|
|
le = os.path.join(HERE, "baseline_le.pcf")
|
|
with open(le, "wb") as fh:
|
|
fh.write(data)
|
|
print(f"wrote {le} ({len(data)} bytes)")
|
|
|
|
evil = fontgen.set_num_chars(bytes(data), 0x40000001)
|
|
evil_path = os.path.join(HERE, "baseline_le_evil.pcf")
|
|
with open(evil_path, "wb") as fh:
|
|
fh.write(evil)
|
|
print(f"wrote {evil_path} ({len(evil)} bytes), BITMAPS num_chars=0x40000001")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|