shithub: puzzles

Download patch

ref: 1aded127eb3fb7194a1752d96bfba95a5b7fa4dc
parent: a539f38efd0d821c8325846fc879a3e46d6412bf
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sat Jan 7 17:05:33 EST 2023

Netslide: Reject moves wider than the grid

Also add a corresponding assertion to the underlying move primitive.
Without this limit, long moves cause a buffer overrun.

To demonstrate the problem, build Netslide with AddressSanitizer and
load this save file:

SAVEFILE:41:Simon Tatham's Portable Puzzle Collection
VERSION :1:1
GAME    :8:Netslide
PARAMS  :3:4x4
CPARAMS :3:4x4
DESC    :16:49b59aca247714b4
NSTATES :1:2
STATEPOS:1:2
MOVE    :5:R3,51

--- a/netslide.c
+++ b/netslide.c
@@ -1004,7 +1004,9 @@
     int x = dir > 0 ? -1 : w;
     int tx = x + dir;
     int n = w - 1;
-    unsigned char endtile = tiles[row * w + tx];
+    unsigned char endtile;
+    assert(0 <= tx && tx < w);
+    endtile = tiles[row * w + tx];
     do {
         x = tx;
         tx = (x + dir + w) % w;
@@ -1018,7 +1020,9 @@
     int y = dir > 0 ? -1 : h;
     int ty = y + dir;
     int n = h - 1;
-    unsigned char endtile = tiles[ty * w + col];
+    unsigned char endtile;
+    assert(0 <= ty && ty < h);
+    endtile = tiles[ty * w + col];
     do {
         y = ty;
         ty = (y + dir + h) % h;
@@ -1139,7 +1143,9 @@
 
     if ((move[0] == 'C' || move[0] == 'R') &&
 	sscanf(move+1, "%d,%d", &c, &d) == 2 &&
-	c >= 0 && c < (move[0] == 'C' ? from->width : from->height)) {
+	c >= 0 && c < (move[0] == 'C' ? from->width : from->height) &&
+        d <= (move[0] == 'C' ? from->width : from->height) &&
+        d >= -(move[0] == 'C' ? from->width : from->height) && d != 0) {
 	col = (move[0] == 'C');
     } else if (move[0] == 'S' &&
 	       strlen(move) == from->width * from->height + 1) {