tools: a layout control for structural claims -- and the obvious version does not work
sylpheed-port named a gap in their own rule: the fourth aside of mine to reach their authored data was a STRUCTURE, not a decoration, and 'the unchecked things carry no weight' did not cover it because a wrong field order looks like a fact. It carried no weight only by luck. The fix belongs at my end, so this is the control that should have existed when I published the layout. The obvious form fails, and its failure is the useful part: checking that all records are type-plausible passes on the SHIFTED alignments too, 69 of 70 in both directions. A homogeneous repeated table has the same field types in sequence, so any window starting on a field boundary type-checks and the interior carries no information about phase. Only the BOUNDARIES do. A shifted reading must consume a word from outside the table at one end, and that word does not obey the field's type -- which is exactly how the original error surfaced, record 0's handler reading as 0x10000000. Two-sided: the published alignment survives at both edges and both shifts fail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
111
tools/re-capture/struct_layout_control.py
Normal file
111
tools/re-capture/struct_layout_control.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Type-plausibility control for a published record layout.
|
||||
|
||||
🔴 WHY THIS EXISTS. I published the dialog table as `{handler, id, name_ptr}`.
|
||||
It is `{id, name_ptr, handler}` -- the same three fields shifted one word, so every
|
||||
record was credited with the PREVIOUS record's handler. sylpheed-port had copied it
|
||||
into their authored data before either of us noticed.
|
||||
|
||||
Their rule -- "the claims that go unchecked are the ones that carry no weight" --
|
||||
did NOT protect them here, and they named the gap precisely: a wrong FIELD ORDER
|
||||
looks like a fact rather than an aside, and a later reader builds on it. It carried
|
||||
no weight only by luck.
|
||||
|
||||
So a structural claim needs a control that FAILS when the alignment is wrong. Every
|
||||
field has a type, and a wrong alignment breaks the types: an id stops being small,
|
||||
a string pointer stops pointing at a string, a code pointer stops looking like code.
|
||||
|
||||
⚠️ TWO-SIDED BY CONSTRUCTION: it checks the published layout passes AND that the
|
||||
shifted alignments fail. A layout check that only confirms the current reading is
|
||||
the same defect one level up.
|
||||
|
||||
struct_layout_control.py
|
||||
"""
|
||||
import struct
|
||||
import sys
|
||||
|
||||
PE = open("/image/sylpheed.pe", "rb").read()
|
||||
BASE = 0x82000000
|
||||
CODE_LO, CODE_HI = 0x82000000, 0x82600000
|
||||
|
||||
|
||||
def rd(va):
|
||||
o = va - BASE
|
||||
return struct.unpack_from(">I", PE, o)[0] if 0 <= o < len(PE) - 4 else None
|
||||
|
||||
|
||||
def is_id(v):
|
||||
return v is not None and v < 100_000
|
||||
|
||||
|
||||
def is_dlg_name(v):
|
||||
if v is None or not (BASE <= v < BASE + len(PE)):
|
||||
return False
|
||||
o = v - BASE
|
||||
e = PE.find(b"\x00", o)
|
||||
return e > o and PE[o:e].startswith(b"DLG_")
|
||||
|
||||
|
||||
def is_code(v):
|
||||
"""A code pointer whose target opens with a real PowerPC prologue."""
|
||||
if v is None or not (CODE_LO <= v < CODE_HI) or v % 4:
|
||||
return False
|
||||
w = rd(v)
|
||||
return w is not None and (w == 0x7D8802A6 or (w >> 26) == 37) # mflr r12 / stwu
|
||||
|
||||
|
||||
def check(first_field_va, order, n=70):
|
||||
"""order: sequence of predicates, one per 4-byte field."""
|
||||
ok = 0
|
||||
for k in range(n):
|
||||
b = first_field_va + 12 * k
|
||||
vals = [rd(b + 4 * i) for i in range(len(order))]
|
||||
if all(p(v) for p, v in zip(order, vals)):
|
||||
ok += 1
|
||||
return ok
|
||||
|
||||
|
||||
ID_NAME_HANDLER = (is_id, is_dlg_name, is_code)
|
||||
HANDLER_ID_NAME = (is_code, is_id, is_dlg_name)
|
||||
NAME_HANDLER_ID = (is_dlg_name, is_code, is_id)
|
||||
|
||||
TABLE = 0x820A0A30 # first record under the published layout
|
||||
N = 70
|
||||
|
||||
# 🔴 THE OBVIOUS CONTROL DOES NOT WORK, AND THAT IS THE POINT.
|
||||
# Checking "are all records type-plausible" passes on the SHIFTED alignments too:
|
||||
# 69/70 in both directions. A homogeneous repeated table has the same field types
|
||||
# in sequence -- id, name, handler, id, name, handler -- so ANY window starting on
|
||||
# a field boundary type-checks. The interior carries no information about phase.
|
||||
#
|
||||
# ✅ ONLY THE BOUNDARIES DO. A shifted reading must consume a word from OUTSIDE the
|
||||
# table at one end, and that word does not obey the field's type. That is exactly
|
||||
# how the original error surfaced: under the shifted alignment record 0's "handler"
|
||||
# was 0x10000000, the word sitting before the table.
|
||||
print("── dialog table: alignment control (boundaries, not interior) ──")
|
||||
print(" interior is UNINFORMATIVE, shown so nobody rebuilds it:")
|
||||
for label, base, order in (("published ", TABLE, ID_NAME_HANDLER),
|
||||
("shifted -1", TABLE - 4, HANDLER_ID_NAME),
|
||||
("shifted +1", TABLE + 4, NAME_HANDLER_ID)):
|
||||
print(f" {label} {check(base, order, N)}/{N} records type-plausible")
|
||||
|
||||
def edges_ok(base, order):
|
||||
"""Both terminal records must type-check under this alignment."""
|
||||
for k in (0, N - 1):
|
||||
b = base + 12 * k
|
||||
if not all(p(rd(b + 4 * i)) for i, p in enumerate(order)):
|
||||
return False
|
||||
return True
|
||||
|
||||
print("\n boundaries -- the discriminating test:")
|
||||
res = [("PUBLISHED {id, name_ptr, handler}", edges_ok(TABLE, ID_NAME_HANDLER), True),
|
||||
("shifted -1 {handler, id, name_ptr}", edges_ok(TABLE - 4, HANDLER_ID_NAME), False),
|
||||
("shifted +1 {name_ptr, handler, id}", edges_ok(TABLE + 4, NAME_HANDLER_ID), False)]
|
||||
bad = 0
|
||||
for label, got, want in res:
|
||||
good = (got == want)
|
||||
bad += not good
|
||||
print(f" {'✅' if good else '🔴'} {label} edges type-check: {got} (want {want})")
|
||||
if bad:
|
||||
print("🔴 LAYOUT CONTROL FAILED"); sys.exit(2)
|
||||
print("\n ✅ only the published alignment survives at both boundaries")
|
||||
Reference in New Issue
Block a user