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:
@@ -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
|
||||
|
||||
36
src/sp_lev.c
36
src/sp_lev.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user