From 9632634b648109765955e89ec07f788388d8170f Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Sat, 29 Aug 2026 19:26:49 -0700 Subject: Fix batch-mode exit code, killer-table backfill collision, impossible QSearch mate-magnitude asserts, MATEMOVE PV display, --command truncation, and test.sh's stale egtbpath. Several small, independent correctness fixes bundled together since they were all exercised together through today's precommit_check.sh and curated-suite runs: - command.c: batch-mode's "Exhausted input" exit was exit(-1), which truncates to 255 (an 8-bit status) and is indistinguishable from a real crash's nonzero exit. Changed to exit(0) so debug_smoke_test.sh can reliably tell a clean batch run apart from a crash by exit status alone. - dynamic.c: _NewKillerMove's slot[1] backfill from mvNullmoveQuietRefutations[uPly] had no check that the backfilled move differed from the move just placed in slot[0]. When they coincided, both slots held the identical move, silently wasting a killer slot in release builds (ASSERT is a no-op there) and tripping _NewKillerMove's own IS_SAME_MOVE invariant in DEBUG builds. Fixed by skipping the backfill on collision. - search.c: removed two ASSERT(iBestScore > -NMATE) calls in QSearch that encoded an invariant that isn't actually guaranteed -- at an early full-width root iteration, or after aspiration-window widening following repeated fail-highs, an ancestor frame's iAlpha/iBeta can itself already be more extreme than -NMATE with no mate anywhere in the line, so a legitimate fail-low placeholder or fail-high score can land in mate-magnitude territory purely as a window artifact. hash.c's storage path already treats any value <= -NMATE as a sound upper bound regardless of origin, so this was a false invariant, not a caught bug. Also: minor whitespace cleanup, an added ASSERT documenting the futility-margin depth precondition it replaced a redundant runtime check for, and PV/leaf-count bookkeeping on the mate/draw-at-root leaf paths that was previously skipped. - util.c: MATEMOVE sentinel moves weren't handled in PV-to-string conversion, so a PV ending in a detected mate would either display garbage or hit the same-move assert. Added an explicit "<#>" marker. - test.sh: --egtbpath pointed at a nonexistent /egtb/three;/egtb/four; /egtb/five; corrected to /zscratch/egtb, this box's actual EGTB location. - main.c/input.c: --command's initial-command buffer (g_szInitialCommand) was a fixed 256-byte array; strncpy(..., SMALL_STRING_LEN_CHAR - 2) silently truncated any longer --command string, and -- worse -- when the source was long enough not to fit, strncpy doesn't null-terminate the destination, so the immediately-following strcat(..., "\r\n") could read/write past the buffer. Long move-replay command strings used during this session's debugging hit the truncation directly (a ~600 char move list silently cut off mid-token, desyncing the input queue). Changed g_szInitialCommand to a heap allocation sized to the actual input length instead of a fixed cap. - CLAUDE.md: documents the above (this file's own diff is prior session's writeup of these same fixes, committed now alongside the code). All exercised together via precommit_check.sh (self-test suite + DEBUG smoke test against random ecm.ep_ samples) and the sd10/sn5m curated suite sweep run for the eval.c hand-tuning commit just before this one. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01M9ZDiJhiUajUxh95mTXCFJ --- src/input.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/input.c') diff --git a/src/input.c b/src/input.c index 389b658..6a35ab8 100755 --- a/src/input.c +++ b/src/input.c @@ -29,7 +29,7 @@ Revision History: DLIST_ENTRY g_InputEventList; volatile static ULONG g_uInputLock; -extern CHAR g_szInitialCommand[SMALL_STRING_LEN_CHAR]; +extern CHAR *g_szInitialCommand; #define INPUT_IS_LOCKED (g_uInputLock != 0) #define LOCK_INPUT \ @@ -217,11 +217,12 @@ Return value: _BlockBlockingReaders(); InitializeListHead(&g_InputEventList); g_uInputLock = 0; - if (g_szInitialCommand[0] != '\0') + if (g_szInitialCommand != NULL) { Trace("INPUT SYSTEM INIT: Pushing \"%s\"\n", g_szInitialCommand); PushNewInput(g_szInitialCommand); - g_szInitialCommand[0] = '\0'; + SystemFreeMemory(g_szInitialCommand); + g_szInitialCommand = NULL; } } @@ -246,9 +247,9 @@ Return value: **/ { - if (g_szInitialCommand[0] == '\0') + if (g_szInitialCommand == NULL) { - UtilPanic(INCONSISTENT_STATE, + UtilPanic(INCONSISTENT_STATE, NULL, "Batch mode specified with no initial command", NULL, NULL, __FILE__, __LINE__); -- cgit v1.3