diff options
| author | Ben Harris <bjh21@bjh21.me.uk> | 2023-01-07 20:28:23 +0000 |
|---|---|---|
| committer | Ben Harris <bjh21@bjh21.me.uk> | 2023-01-15 16:21:37 +0000 |
| commit | 5279fd24b2f4a51e760bfde873fe1d29547220a6 (patch) | |
| tree | 4b3674eca01ec402907d6a3494c35a2722ccb2ba /guess.c | |
| parent | c84af670b52f09e9e47587584c0559c508d4a37d (diff) | |
| download | puzzles-5279fd24b2f4a51e760bfde873fe1d29547220a6.zip puzzles-5279fd24b2f4a51e760bfde873fe1d29547220a6.tar.gz puzzles-5279fd24b2f4a51e760bfde873fe1d29547220a6.tar.bz2 puzzles-5279fd24b2f4a51e760bfde873fe1d29547220a6.tar.xz | |
Guess: validate peg colours in decode_ui()
Peg colours in the current guess must be within the range of colours
for the current game, just as they must be for completed moves.
Otherwise is_markable() can cause a buffer overrun.
Since there's no way for decode_ui() to report an error, it just ignores
the bad peg colours. I've also added an assertion to catch this problem
in is_markable().
The following save file demonstrates the problem when loaded in a build
with AddressSanitizer:
SAVEFILE:41:Simon Tatham's Portable Puzzle Collection
VERSION :1:1
GAME :5:Guess
PARAMS :9:c6p4g10Bm
CPARAMS :9:c6p4g10Bm
DESC :8:2de917c0
UI :7:7,7,7,7
NSTATES :1:1
STATEPOS:1:1
Diffstat (limited to 'guess.c')
| -rw-r--r-- | guess.c | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -380,6 +380,7 @@ static bool is_markable(const game_params *params, pegrow pegs) for (i = 0; i < params->npegs; i++) { int c = pegs->pegs[i]; if (c > 0) { + assert(c <= params->ncolours); colcount->pegs[c-1]++; nset++; } @@ -462,6 +463,9 @@ static void decode_ui(game_ui *ui, const char *encoding) const char *p = encoding; for (i = 0; i < ui->curr_pegs->npegs; i++) { ui->curr_pegs->pegs[i] = atoi(p); + if (ui->curr_pegs->pegs[i] < 0 || + ui->curr_pegs->pegs[i] > ui->params.ncolours) + ui->curr_pegs->pegs[i] = 0; /* Remove invalid pegs. */ while (*p && isdigit((unsigned char)*p)) p++; if (*p == '_') { /* NB: old versions didn't store holds */ |