diff options
Diffstat (limited to 'src/fen.c')
| -rwxr-xr-x | src/fen.c | 84 |
1 files changed, 73 insertions, 11 deletions
@@ -588,32 +588,94 @@ Return value: **/ { - ULONG u = 0; + ULONG u = 1; + ULONG uChunkIndex = 0; int i; CHAR *q, *op; - + p->uFifty = 0; + // + // A FEN that omits the halfmove-clock/fullmove-number suffix + // entirely (routine in EPD test suites like tests/ecm.ep_ -- e.g. + // "... w - -" with nothing after the en passant field) makes + // szFifty NULL here (FindChunk(szCapturedFen, 5) found no 5th + // chunk at all). The original code happened to survive that + // silently because FindChunk(NULL, 0) hits its "0 means whole + // string" fast path and returns NULL without ever dereferencing + // sz; starting at chunk 1 below (see the comment further down) + // loses that accidental safety net since chunk-1 lookups always + // dereference sz. Handle it explicitly instead of relying on + // FindChunk's early-return shape again -- found live by + // precommit_check.sh's debug_smoke_test.sh crashing on the very + // first random ecm.ep_ position after the chunk-index fix below + // was added. + // + if (NULL == szFifty) + { + return; + } + // + // Start at chunk 1 (FindChunk's convention: 0 means "whole + // remaining string", 1 means "the first token"), not 0. Starting + // at 0 here made this loop visit the first token twice -- once via + // the u==0 "whole string" fetch below, again via the very first + // u==1 fetch inside the loop -- throwing off the uChunkIndex + // bookkeeping used to tell the halfmove clock (real chunk 1) apart + // from the fullmove number (real chunk 2) below. + // q = FindChunk(szFifty, u); u++; while(NULL != q) { //printf("%u: %s\n", u-1, q); - - i = atoi(q); - if ((i > 0) && (i < 100)) + + if (0 == uChunkIndex) + { + // + // In a real FEN string this chunk is always the halfmove + // (fifty-move-rule) clock -- unlike every later chunk, 0 is + // a legitimate value here (a fresh game, or right after a + // capture/pawn move), not "absent". The generic i>0 check + // below would skip a genuine 0 and fall through to the + // *next* chunk (the fullmove number) instead, silently + // assigning that to uFifty. Confirmed live: the engine's + // own hardcoded starting-position FEN ("... - 0 1") was + // parsed as uFifty=1 (the fullmove number) rather than 0. + // + i = atoi(q); + if ((i >= 0) && (i < 100)) + { + p->uFifty = (ULONG)i; + } + } + else if (1 == uChunkIndex) { - p->uFifty = (ULONG)i; + // + // The second chunk is the fullmove number, not used by + // this engine -- just consumed here so the generic + // EPD-opcode scan below doesn't misread it as a repeated + // (and wrong) fifty-move value. + // } else { - if (!STRCMPI(q, "bm")) + i = atoi(q); + if ((i > 0) && (i < 100)) { - op = FindChunk(szFifty, u); - u++; - if (NULL == op) break; + p->uFifty = (ULONG)i; + } + else + { + if (!STRCMPI(q, "bm")) + { + op = FindChunk(szFifty, u); + u++; + if (NULL == op) break; + } + } - } + uChunkIndex++; q = FindChunk(szFifty, u); u++; } |
