fix #H7352 - panic when floodfilling large areas

Special levels with FLAGS:inaccessibles could trigger a panic if
a large enough area was subjected to floodfill handling.  The buffer
intended to be enough to hold an entire level wasn't big enough when
individual coordinates were being added multiple times.  I don't
really understand what this code is doing but the recommended fix
does work to prevent the panic.

None of the levels included with 3.6.x were affected.
This commit is contained in:
PatR
2018-08-13 18:33:15 -07:00
parent 3774cb29f3
commit 34c1d30370
2 changed files with 31 additions and 7 deletions

View File

@@ -81,6 +81,8 @@ succubus/incubus seduction might result in loss of levitation which in turn
seduction was proceeding as if nothing unusual had happened
#turn command which aggravated monsters did so without using a turn (not a pun)
fix hole/trapdoor passage inconsistency when polymorphed into a giant
making a wide-open special level with FLAGS:inaccessibles could trigger a
"floodfill stack overrun" panic (no 3.6.x levels were affected)
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -126,6 +126,8 @@ STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *,
STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int));
STATIC_DCL int FDECL(floodfillchk_match_under, (int, int));
STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int));
STATIC_DCL boolean FDECL(sel_flood_havepoint, (int, int,
xchar *, xchar *, int));
STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int,
int, int, int));
STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long));
@@ -3895,6 +3897,23 @@ int x, y;
|| levl[x][y].typ == SCORR);
}
/* check whethere <x,y> is already in xs[],ys[] */
STATIC_OVL boolean
sel_flood_havepoint(x, y, xs, ys, n)
int x, y;
xchar xs[], ys[];
int n;
{
xchar xx = (xchar) x, yy = (xchar) y;
while (n > 0) {
if (xs[n] == xx && ys[n] == yy)
return TRUE;
--n;
}
return FALSE;
}
void
selection_floodfill(ov, x, y, diagonals)
struct opvar *ov;
@@ -3904,7 +3923,7 @@ boolean diagonals;
static const char nhFunc[] = "selection_floodfill";
struct opvar *tmp = selection_opvar((char *) 0);
#define SEL_FLOOD_STACK (COLNO * ROWNO)
#define SEL_FLOOD(nx, ny) \
#define SEL_FLOOD(nx, ny) \
do { \
if (idx < SEL_FLOOD_STACK) { \
dx[idx] = (nx); \
@@ -3913,17 +3932,20 @@ boolean diagonals;
} else \
panic(floodfill_stack_overrun); \
} while (0)
#define SEL_FLOOD_CHKDIR(mx,my,sel) \
if (isok((mx), (my)) \
&& (*selection_flood_check_func)((mx), (my)) \
&& !selection_getpoint((mx), (my), (sel))) \
SEL_FLOOD((mx), (my))
#define SEL_FLOOD_CHKDIR(mx, my, sel) \
do { \
if (isok((mx), (my)) \
&& (*selection_flood_check_func)((mx), (my)) \
&& !selection_getpoint((mx), (my), (sel)) \
&& !sel_flood_havepoint((mx), (my), dx, dy, idx)) \
SEL_FLOOD((mx), (my)); \
} while (0)
static const char floodfill_stack_overrun[] = "floodfill stack overrun";
int idx = 0;
xchar dx[SEL_FLOOD_STACK];
xchar dy[SEL_FLOOD_STACK];
if (selection_flood_check_func == NULL) {
if (selection_flood_check_func == (int FDECL((*), (int, int))) 0) {
opvar_free(tmp);
return;
}