Module Name:    src
Committed By:   rillig
Date:           Sun May 29 20:21:29 UTC 2022

Modified Files:
        src/games/gomoku: main.c

Log Message:
gomoku: make parsing of the debug command 'o' robust

Previously, the (invalid) debug command 'o,' succeeded to parse and led
to out-of-bounds memory access. Add proper parsing for the arguments of
that debug command. Add a short usage for that debug command, as
guessing the usage from the previous code was time-consuming due to the
large amount of ad-hoc low-level parsing code.

When leaving debug mode, clear the debug prompt.


To generate a diff of this commit:
cvs rdiff -u -r1.71 -r1.72 src/games/gomoku/main.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/games/gomoku/main.c
diff -u src/games/gomoku/main.c:1.71 src/games/gomoku/main.c:1.72
--- src/games/gomoku/main.c:1.71	Sun May 29 17:01:42 2022
+++ src/games/gomoku/main.c	Sun May 29 20:21:28 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.71 2022/05/29 17:01:42 rillig Exp $	*/
+/*	$NetBSD: main.c,v 1.72 2022/05/29 20:21:28 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -36,7 +36,7 @@
 __COPYRIGHT("@(#) Copyright (c) 1994\
  The Regents of the University of California.  All rights reserved.");
 /*	@(#)main.c	8.4 (Berkeley) 5/4/95	*/
-__RCSID("$NetBSD: main.c,v 1.71 2022/05/29 17:01:42 rillig Exp $");
+__RCSID("$NetBSD: main.c,v 1.72 2022/05/29 20:21:28 rillig Exp $");
 
 #include <sys/stat.h>
 #include <curses.h>
@@ -412,6 +412,59 @@ readinput(FILE *fp)
 }
 
 #ifdef DEBUG
+
+static bool
+skip_any(const char **pp, const char *s)
+{
+	while (strchr(s, **pp) != NULL)
+		(*pp)++;
+	return true;
+}
+
+static bool
+parse_char_index(const char **pp, const char *s, unsigned int *out)
+{
+	const char *found = strchr(s, **pp);
+	if (found != NULL)
+		*out = (unsigned int)(found - s), (*pp)++;
+	return found != NULL;
+}
+
+static bool
+parse_direction(const char **pp, direction *out)
+{
+	unsigned int u;
+	if (!parse_char_index(pp, "-\\|/", &u))
+		return false;
+	*out = (direction)u;
+	return true;
+}
+
+static bool
+parse_row(const char **pp, unsigned int *out)
+{
+	if (!('0' <= **pp && **pp <= '9'))
+		return false;
+	unsigned int u = *(*pp)++ - '0';
+	if ('0' <= **pp && **pp <= '9')
+		u = 10 * u + *(*pp)++ - '0';
+	*out = u;
+	return 1 <= u && u <= BSZ;
+}
+
+static bool
+parse_spot(const char **pp, spot_index *out)
+{
+	unsigned row, col;
+	if (!parse_char_index(pp, "abcdefghjklmnopqrst", &col) &&
+	    !parse_char_index(pp, "ABCDEFGHJKLMNOPQRST", &col))
+		return false;
+	if (!parse_row(pp, &row))
+		return false;
+	*out = PT(col + 1, row);
+	return true;
+}
+
 /*
  * Handle strange situations and ^C.
  */
@@ -419,12 +472,13 @@ readinput(FILE *fp)
 void
 whatsup(int signum __unused)
 {
-	int n, d1, d2;
+	unsigned int n;
 	player_color color;
 	spot_index s, s1, s2;
+	direction r1, r2;
 	struct spotstr *sp;
 	FILE *fp;
-	char *str;
+	const char *str;
 	struct elist *ep;
 	struct combostr *cbp;
 	char input[128];
@@ -447,7 +501,8 @@ top:
 		debuglog("Debug set to %d", debug);
 		goto top;
 	case 'c':
-		break;
+		ask("");
+		return;
 	case 'b':		/* back up a move */
 		if (game.nmoves > 0) {
 			game.nmoves--;
@@ -485,30 +540,21 @@ top:
 		fclose(fp);
 		goto top;
 	case 'o':
-		/* avoid use w/o initialization on invalid input */
-		d1 = s1 = 0;
-
-		n = 0;
-		for (str = input + 1; *str != '\0'; str++)
-			if (*str == ',') {
-				for (d1 = 0; d1 < 4; d1++)
-					if (str[-1] == pdir[d1])
-						break;
-				str[-1] = '\0';
-				sp = &board[s1 = ctos(input + 1)];
-				n = sp->s_frame[d1] * FAREA;
-				*str++ = '\0';
-				break;
-			}
-		sp = &board[s2 = ctos(str)];
-		while (*str != '\0')
-			str++;
-		for (d2 = 0; d2 < 4; d2++)
-			if (str[-1] == pdir[d2])
-				break;
-		n += sp->s_frame[d2];
-		debuglog("overlap %s%c,%s%c = %x", stoc(s1), pdir[d1],
-		    stoc(s2), pdir[d2], overlap[n]);
+		str = input + 1;
+		if (skip_any(&str, " ") &&
+		    parse_spot(&str, &s1) &&
+		    parse_direction(&str, &r1) &&
+		    skip_any(&str, ", ") &&
+		    parse_spot(&str, &s2) &&
+		    parse_direction(&str, &r2) &&
+		    *str == '\0') {
+			n = board[s1].s_frame[r1] * FAREA
+			    + board[s2].s_frame[r2];
+			debuglog("overlap %s%c,%s%c = %02x",
+			    stoc(s1), pdir[r1], stoc(s2), pdir[r2],
+			    overlap[n]);
+		} else
+			debuglog("usage: o <spot><dir> <spot><dir>");
 		goto top;
 	case 'p':
 		sp = &board[s = ctos(input + 1)];
@@ -524,7 +570,7 @@ top:
 			sp->s_fval[WHITE][0].s, sp->s_fval[WHITE][1].s,
 			sp->s_fval[WHITE][2].s, sp->s_fval[WHITE][3].s);
 		goto top;
-	case 'e':	/* e {b|w} [0-9] spot */
+	case 'e':	/* e [0-9] spot */
 		str = input + 1;
 		if (*str >= '0' && *str <= '9')
 			n = *str++ - '0';

Reply via email to