diff options
| author | Scott Gasch <[email protected]> | 2026-10-15 16:26:43 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-15 16:26:43 -0700 |
| commit | c179ae5ad9f1a0efb68904033621705fd060aea4 (patch) | |
| tree | 2f0639b4699a7825b6983f27518497d388eb0e2d /src/fen.c | |
| parent | 1ea81bae240912efb8cebabae35fe58bc5d12afb (diff) | |
Fix overlapping-buffer sprintf/snprintf bugs in fen.c and gamelist.c
Both FenFromPosition and the status-line builder in gamelist.c were
reading and writing the same buffer within a single sprintf/snprintf
call (e.g. sprintf(pHeap, "%s...", pHeap, ...)) -- undefined behavior
per the C standard since the source and destination overlap, caught
by valgrind as uninitialised-value reads even though no DEBUG ASSERT
ever tripped. Fixed by building each piece into a separate buffer (or
appending via snprintf/strncat into the already-terminated prefix)
instead of re-reading the destination as a source argument.
debug_smoke_test.sh: added a valgrind pass over the same sampled
smoke-test positions, since this class of bug produces no ASSERT
failure and was otherwise invisible to the existing smoke test.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/fen.c')
| -rw-r--r-- | src/fen.c | 17 |
1 files changed, 9 insertions, 8 deletions
@@ -188,15 +188,16 @@ Return value: // queenside. There is no white space between the letters. // *pch++ = ' '; - *pch++ = '\0'; + *pch = '\0'; + ASSERT(strlen(pHeap) < MAX_FEN_LEN_BYTES); + snprintf(pch, + MAX_FEN_LEN_BYTES - (size_t)(pch - pHeap), + "%s %s %u %u", + CastleInfoString(pos->bvCastleInfo), + CoorToString(pos->cEpSquare), + pos->uFifty, + 0); ASSERT(strlen(pHeap) < MAX_FEN_LEN_BYTES); - sprintf(pHeap, - "%s%s %s %u %u", - pHeap, - CastleInfoString(pos->bvCastleInfo), - CoorToString(pos->cEpSquare), - pos->uFifty, - 0); return(pHeap); // Note: caller must free } |
