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.
This commit is contained in:
rillig 2022-05-29 20:21:28 +00:00
parent 6084941245
commit 2a44525455
1 changed files with 76 additions and 30 deletions

View File

@ -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';