diff options
| author | Scott Gasch <[email protected]> | 2026-10-25 11:05:10 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-25 11:05:10 -0700 |
| commit | 455accb4cbb1777cb553b6d75136521c6b8d1c01 (patch) | |
| tree | 3f526bf50b58829453799bd876ff2d4e86201338 /src/x86.asm | |
| parent | fc873933e21d9188f2b5a9d13764f00b6ce68ec9 (diff) | |
Fix SIGSEGV in GetNthOfficialMoveRecord on an exact-length index
GetNthOfficialMoveRecord's end-of-list check only tested whether its
decrementing counter n reached 0, not whether the walk pointer p had
also reached the move list's own sentinel head at the same moment.
Requesting index == the list's real length (exactly what every
caller's "walk until NULL" loop does as its final probe) hit both
conditions simultaneously, so the function treated the sentinel's own
DLIST_ENTRY as a GAME_MOVE via CONTAINING_STRUCT and handed back a
pointer to g_GameData.sMoveList's own links field reinterpreted as a
move record -- q->mv.uMove read as nonzero garbage (never actually 0,
so the "is this real" check downstream never caught it), and
q->szMoveInSan was effectively an arbitrary pointer.
Reported as: play a few moves (e.g. e4 e5 Nc3), run "dump moves" ->
crash. Confirmed via lldb: SIGSEGV in vsnprintf/strlen, called from
Trace() in DumpGameList (gamelist.c:575) handed that garbage
szMoveInSan pointer. book.c's two GetNthOfficialMoveRecord loops
(opening-book move matching) have the identical exposure and are fixed
by the same change at the source.
Fix: also require p != &g_GameData.sMoveList before treating it as a
real node.
Verified: "dump moves"/"dump pgn" after several moves (both odd- and
even-length move lists, so the off-by-one's exact trigger condition is
covered on both sides) no longer crash, and a clean DEBUG=1 TEST=1
self-test run shows no regressions.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/x86.asm')
0 files changed, 0 insertions, 0 deletions
