#230 printer: FMT-PRINT-LIST-BODY (~S of a list) segfaults on a corrupt/out-of-heap cons — masks errors as cores
openSummary
The error printer segfaults when asked to ~S/print a value whose cons cells are corrupt or point outside the heap, turning what should be a readable ; Error: into a hard SIGSEGV (a silent core). This masks the underlying bug and forces gdb to diagnose what should have been a printed error.
Evidence (walkable backtrace via JIT .eh_frame)
Hit while formatting a type-error during an asdf.lisp load experiment:
#0 FMT-PRINT-LIST-BODY (DEST=#<byte-vector len=11>, C=#<cons 0x16a2a1a92aa7a98 unreadable>)
#1 FMT-PRINT-THING (V=#<byte-vector len=11>)
#5 FORMAT-WALK (FMT="The value ~S is not of type NUMBER.", ARGS=(#<cons 0x16a2a1a92aa7a98 unreadable>))
#6 FORMAT (ARGS="The value is not of type NUMBER.")
The heap base is 0x800000000; 0x16a2a1a92aa7a98 is far outside it — FMT-PRINT-LIST-BODY walked (car/cdr) a garbage cons and faulted.
Ask
Make the list/~S printer defensive: before dereferencing a cons in FMT-PRINT-LIST-BODY (and peers), sanity-check the pointer is in the heap range (or bound the traversal depth) and, on failure, print a placeholder like #<unreadable 0x…> instead of faulting. This converts a class of cores into readable errors — high leverage for every future compiler/runtime bug whose offending value is malformed.
Context
Surfaced during the cave#229 gensym→symbol experiment (a not of type NUMBER type-error whose culprit value was a corrupt cons). The type-error itself is a separate bug; this issue is only about the printer not surviving a bad value.
STILL RELEVANT; now part of a family with #286 (filed 2026-07-11: prelude printer has NO cycle/depth guard — cyclic mc instances segfault prin1). The fix for both is the same hardening pass on fmt-print-cons/fmt-print-vector: depth cap + EQ visited set (the REPL echo printer got exactly this in 21f15f2) + a bounds/heap-range sanity check for the corrupt-cons case here. Suggest fixing together.