A callable value's signature record is misread on 32-bit targets
def q(a, b=7):
return (a, b)
f = q
print(f(1), f(1, 2)) # i386: (, 1) ...; expected (1, 7) (1, 2)
def star(*args):
return len(args)
h = star
print(h(1, 2, 3), h()) # i386: segfault
Mechanism
The compiler writes the signature record at the fixed offsets PYSIG_OFF_* in
defs.inc, where every field is one 8-byte word. The runtime's TPySigRec in
pylib.pas declared Code, Dflts and Names as pointers, which are 4 bytes
on a 32-bit target, so every field after the first was read 4 bytes early.
Fix
Under CPU32, TPySigRec pads each pointer field to 8 bytes (CodePad,
DfltsPad, NamesPad).
Test
test/test_nilpy_cross32_values.py (the callable block), with rows in
test-i386 and test-arm32. Measured wrong with pin v446 (stable_linux_amd64/default/stable_pinned) on 2026-09-28.