From 21193eaf9308ace41004a19180ff382ec6e8754b Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 12 Jan 2023 20:55:56 +0000 Subject: [PATCH] Palisade: forbid moves that remove grid edges Without this check, a corrupt save file can include a move that removes an edge of the grid, and then is_solved() walks off the edge of the grid causing a buffer over- or under-run. To demonstrate the bug, load this save file in a build with AddressSanitizer: SAVEFILE:41:Simon Tatham's Portable Puzzle Collection VERSION :1:1 GAME :8:Palisade PARAMS :5:5x5n5 CPARAMS :5:5x5n5 DESC :0: NSTATES :1:2 STATEPOS:1:2 MOVE :6:F0,0,1 --- palisade.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/palisade.c b/palisade.c index 6661f5b..4096d12 100644 --- a/palisade.c +++ b/palisade.c @@ -1010,10 +1010,9 @@ static game_state *execute_move(const game_state *state, const char *move) { int w = state->shared->params.w, h = state->shared->params.h, wh = w * h; game_state *ret = dup_game(state); - int nchars, x, y, flag; + int nchars, x, y, flag, i; if (*move == 'S') { - int i; ++move; for (i = 0; i < wh && move[i]; ++i) ret->borders[i] = @@ -1026,6 +1025,11 @@ static game_state *execute_move(const game_state *state, const char *move) while (sscanf(move, "F%d,%d,%d%n", &x, &y, &flag, &nchars) == 3 && !OUT_OF_BOUNDS(x, y, w, h)) { move += nchars; + for (i = 0; i < 4; i++) + if ((flag & BORDER(i)) && + OUT_OF_BOUNDS(x+dx[i], y+dy[i], w, h)) + /* No toggling the borders of the grid! */ + goto badmove; ret->borders[y*w + x] ^= flag; } @@ -1036,6 +1040,10 @@ static game_state *execute_move(const game_state *state, const char *move) ret->borders); return ret; + + badmove: + sfree(ret); + return NULL; } /* --- Drawing routines --------------------------------------------- */