From c84af670b52f09e9e47587584c0559c508d4a37d Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 7 Jan 2023 19:45:03 +0000 Subject: [PATCH] Guess: Don't allow any moves once the game is solved If the game is solved (either by a win or a loss), interpret_move() can never return a move, but execute_move() should also reject any moves in case we're loading a corrupt or malicious save file. Otherwise a save file with more guesses than the maximum allowed can cause a buffer overrun. This save file demonstrates the problem when loaded into a build of Puzzles with AddressSanitizer: SAVEFILE:41:Simon Tatham's Portable Puzzle Collection VERSION :1:1 GAME :5:Guess PARAMS :9:c6p4g1Bm CPARAMS :9:c6p4g1Bm DESC :8:b5f3faed NSTATES :1:3 STATEPOS:1:3 MOVE :8:G1,1,2,2 MOVE :8:G4,3,1,1 --- guess.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/guess.c b/guess.c index 09f034e..f635fec 100644 --- a/guess.c +++ b/guess.c @@ -942,6 +942,8 @@ static game_state *execute_move(const game_state *from, const char *move) game_state *ret; const char *p; + /* No moves are allowed once the game is solved. */ + if (from->solved) return NULL; if (!strcmp(move, "S")) { ret = dup_game(from); ret->solved = -1;