summaryrefslogtreecommitdiff
path: root/src/fen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fen.c')
-rwxr-xr-xsrc/fen.c84
1 files changed, 73 insertions, 11 deletions
diff --git a/src/fen.c b/src/fen.c
index b42ee04..33810e6 100755
--- a/src/fen.c
+++ b/src/fen.c
@@ -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++;
}