SW: Sanitize all uses of wall.nextwall to prevent OOBs

git-svn-id: https://svn.eduke32.com/eduke32@8322 1a8010ca-5511-0410-912e-c29ae57300e0

# Conflicts:
#	source/sw/src/jnstub.cpp
#	source/sw/src/sector.cpp
This commit is contained in:
hendricks266 2019-11-27 07:33:34 +00:00 committed by Christoph Oelckers
parent ece20928a0
commit 0a70c5e55f
12 changed files with 124 additions and 209 deletions

View file

@ -63,20 +63,23 @@ void CopySectorWalls(short dest_sectnum, short src_sectnum)
wall[dest_wall_num].lotag = wall[src_wall_num].lotag;
wall[dest_wall_num].extra = wall[src_wall_num].extra;
if (wall[dest_wall_num].nextwall >= 0 && wall[src_wall_num].nextwall >= 0)
uint16_t const dest_nextwall = wall[dest_wall_num].nextwall;
uint16_t const src_nextwall = wall[src_wall_num].nextwall;
if (dest_nextwall < MAXWALLS && src_nextwall < MAXWALLS)
{
wall[wall[dest_wall_num].nextwall].picnum = wall[wall[src_wall_num].nextwall].picnum;
wall[wall[dest_wall_num].nextwall].xrepeat = wall[wall[src_wall_num].nextwall].xrepeat;
wall[wall[dest_wall_num].nextwall].yrepeat = wall[wall[src_wall_num].nextwall].yrepeat;
wall[wall[dest_wall_num].nextwall].overpicnum = wall[wall[src_wall_num].nextwall].overpicnum;
wall[wall[dest_wall_num].nextwall].pal = wall[wall[src_wall_num].nextwall].pal;
wall[wall[dest_wall_num].nextwall].cstat = wall[wall[src_wall_num].nextwall].cstat;
wall[wall[dest_wall_num].nextwall].shade = wall[wall[src_wall_num].nextwall].shade;
wall[wall[dest_wall_num].nextwall].xpanning = wall[wall[src_wall_num].nextwall].xpanning;
wall[wall[dest_wall_num].nextwall].ypanning = wall[wall[src_wall_num].nextwall].ypanning;
wall[wall[dest_wall_num].nextwall].hitag = wall[wall[src_wall_num].nextwall].hitag;
wall[wall[dest_wall_num].nextwall].lotag = wall[wall[src_wall_num].nextwall].lotag;
wall[wall[dest_wall_num].nextwall].extra = wall[wall[src_wall_num].nextwall].extra;
wall[dest_nextwall].picnum = wall[src_nextwall].picnum;
wall[dest_nextwall].xrepeat = wall[src_nextwall].xrepeat;
wall[dest_nextwall].yrepeat = wall[src_nextwall].yrepeat;
wall[dest_nextwall].overpicnum = wall[src_nextwall].overpicnum;
wall[dest_nextwall].pal = wall[src_nextwall].pal;
wall[dest_nextwall].cstat = wall[src_nextwall].cstat;
wall[dest_nextwall].shade = wall[src_nextwall].shade;
wall[dest_nextwall].xpanning = wall[src_nextwall].xpanning;
wall[dest_nextwall].ypanning = wall[src_nextwall].ypanning;
wall[dest_nextwall].hitag = wall[src_nextwall].hitag;
wall[dest_nextwall].lotag = wall[src_nextwall].lotag;
wall[dest_nextwall].extra = wall[src_nextwall].extra;
}
dest_wall_num = wall[dest_wall_num].point2;

View file

@ -2413,7 +2413,8 @@ drawscreen(PLAYERp pp)
i = wal->nextsector;
if (i < 0) continue;
if (wal->cstat&0x0071) continue;
if (wall[wal->nextwall].cstat&0x0071) continue;
uint16_t const nextwall = wal->nextwall;
if (nextwall < MAXWALLS && wall[nextwall].cstat&0x0071) continue;
if (sector[i].lotag == 32767) continue;
if (sector[i].ceilingz >= sector[i].floorz) continue;
show2dsector[i>>3] |= (1<<(i&7));

View file

@ -4442,7 +4442,7 @@ void drawoverheadmap(int cposx, int cposy, int czoom, short cang)
for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
{
k = wal->nextwall;
if (k < 0)
if ((unsigned)k >= MAXWALLS)
continue;
if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)
@ -4695,7 +4695,7 @@ SHOWSPRITE:
for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
{
if (wal->nextwall >= 0)
if ((uint16_t)wal->nextwall < MAXWALLS)
continue;
if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)

View file

@ -360,9 +360,6 @@ extern char MessageOutputString[256];
#define SET_SPRITE_TAG13(sp,val) (*((short*)&sprite[sp].xoffset)) = B_LITTLE16(val)
#define SET_SPRITE_TAG14(sp,val) (*((short*)&sprite[sp].xrepeat)) = B_LITTLE16(val)
// this will get you the other wall moved by dragpoint
#define DRAG_WALL(w) (wall[wall[(w)].nextwall].point2)
// OVER and UNDER water macros
#define SpriteInDiveArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_DIVE_AREA) ? TRUE : FALSE)
#define SpriteInUnderwaterArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_UNDERWATER|SECTFX_UNDERWATER2) ? TRUE : FALSE)

View file

@ -93,13 +93,17 @@ void SectorLightShade(SPRITEp sp, short intensity)
wall[w].pal = sp->pal;
wallcount++;
if (TEST(sp->extra, SPRX_BOOL5) && wall[w].nextwall >= 0)
if (TEST(sp->extra, SPRX_BOOL5))
{
base_shade = wall_shade[wallcount];
wall[wall[w].nextwall].shade = base_shade + intensity;
if (!TEST_BOOL6(sp))
wall[wall[w].nextwall].pal = sp->pal;
wallcount++;
uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{
base_shade = wall_shade[wallcount];
wall[nextwall].shade = base_shade + intensity;
if (!TEST_BOOL6(sp))
wall[nextwall].pal = sp->pal;
wallcount++;
}
}
}
}

View file

@ -126,7 +126,7 @@ void SetWallWarpHitscan(short sectnum)
// Travel all the way around loop setting wall bits
do
{
if (wall[wall_num].nextwall >= 0)
if ((uint16_t)wall[wall_num].nextwall < MAXWALLS)
SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN);
wall_num = wall[wall_num].point2;
}

View file

@ -280,8 +280,12 @@ void DoRotatorSetInterp(short SpriteNum)
setinterpolation(&wall[w].x);
setinterpolation(&wall[w].y);
setinterpolation(&wall[DRAG_WALL(w)].x);
setinterpolation(&wall[DRAG_WALL(w)].y);
uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{
setinterpolation(&wall[wall[nextwall].point2].x);
setinterpolation(&wall[wall[nextwall].point2].y);
}
}
}
@ -299,8 +303,12 @@ void DoRotatorStopInterp(short SpriteNum)
stopinterpolation(&wall[w].x);
stopinterpolation(&wall[w].y);
stopinterpolation(&wall[DRAG_WALL(w)].x);
stopinterpolation(&wall[DRAG_WALL(w)].y);
uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{
stopinterpolation(&wall[wall[nextwall].point2].x);
stopinterpolation(&wall[wall[nextwall].point2].y);
}
}
}

View file

@ -107,8 +107,12 @@ void SetSectorWallBits(short sectnum, int bit_mask, SWBOOL set_sectwall, SWBOOL
if (set_sectwall)
SET(wall[wall_num].extra, bit_mask);
if (set_nextwall && wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, bit_mask);
if (set_nextwall)
{
uint16_t const nextwall = wall[wall_num].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, bit_mask);
}
wall_num = wall[wall_num].point2;
}
@ -143,6 +147,28 @@ void WallSetupDontMove(void)
}
}
static void WallSetupLoop(WALLp wp, int16_t lotag, int16_t extra)
{
// set first wall
{
SET(wp->extra, extra);
uint16_t const nextwall = wp->nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, extra);
}
// Travel all the way around loop setting wall bits
for (uint16_t wall_num = wp->point2;
wall[wall_num].lotag != lotag;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, extra);
uint16_t const nextwall = wall[wall_num].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, extra);
}
}
void
WallSetup(void)
{
@ -181,112 +207,33 @@ WallSetup(void)
{
case TAG_WALL_LOOP_DONT_SPIN:
{
short wall_num, start_wall;
// set first wall
SET(wp->extra, WALLFX_LOOP_DONT_SPIN);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_DONT_SPIN);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_DONT_SPIN;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_DONT_SPIN);
auto const nextwall = wall[wall_num].nextwall;
if ((unsigned)nextwall < MAXSECTORS)
SET(wall[nextwall].extra, WALLFX_LOOP_DONT_SPIN);
}
WallSetupLoop(wp, TAG_WALL_LOOP_DONT_SPIN, WALLFX_LOOP_DONT_SPIN);
break;
}
case TAG_WALL_LOOP_DONT_SCALE:
{
short wall_num, start_wall;
// set first wall
SET(wp->extra, WALLFX_DONT_SCALE);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_DONT_SCALE);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_DONT_SCALE;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_DONT_SCALE);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_DONT_SCALE);
}
WallSetupLoop(wp, TAG_WALL_LOOP_DONT_SCALE, WALLFX_DONT_SCALE);
wp->lotag = 0;
break;
}
case TAG_WALL_LOOP_OUTER_SECONDARY:
{
short wall_num, start_wall;
// make sure its a red wall
ASSERT(wp->nextwall >= 0);
// set first wall
SET(wp->extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_OUTER_SECONDARY;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
}
// make sure it's a red wall
ASSERT((uint16_t)wp->nextwall < MAXWALLS);
WallSetupLoop(wp, TAG_WALL_LOOP_OUTER_SECONDARY, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
break;
}
case TAG_WALL_LOOP_OUTER:
{
short wall_num, start_wall;
// make sure its a red wall
ASSERT(wp->nextwall >= 0);
// set first wall
SET(wp->extra, WALLFX_LOOP_OUTER);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_OUTER);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_OUTER;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_OUTER);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_OUTER);
}
// make sure it's a red wall
ASSERT((uint16_t)wp->nextwall < MAXWALLS);
WallSetupLoop(wp, TAG_WALL_LOOP_OUTER, WALLFX_LOOP_OUTER);
wp->lotag = 0;
break;
}
@ -299,76 +246,19 @@ WallSetup(void)
case TAG_WALL_LOOP_SPIN_2X:
{
short wall_num, start_wall;
// set first wall
SET(wp->extra, WALLFX_LOOP_SPIN_2X);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_SPIN_2X);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_SPIN_2X;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_SPIN_2X);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_SPIN_2X);
}
WallSetupLoop(wp, TAG_WALL_LOOP_SPIN_2X, WALLFX_LOOP_SPIN_2X);
break;
}
case TAG_WALL_LOOP_SPIN_4X:
{
short wall_num, start_wall;
// set first wall
SET(wp->extra, WALLFX_LOOP_SPIN_4X);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_SPIN_4X);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_SPIN_4X;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_SPIN_4X);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_SPIN_4X);
}
WallSetupLoop(wp, TAG_WALL_LOOP_SPIN_4X, WALLFX_LOOP_SPIN_4X);
break;
}
case TAG_WALL_LOOP_REVERSE_SPIN:
{
short wall_num, start_wall;
// set first wall
SET(wp->extra, WALLFX_LOOP_REVERSE_SPIN);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_REVERSE_SPIN);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_REVERSE_SPIN;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_REVERSE_SPIN);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_REVERSE_SPIN);
}
WallSetupLoop(wp, TAG_WALL_LOOP_REVERSE_SPIN, WALLFX_LOOP_REVERSE_SPIN);
break;
}

View file

@ -273,13 +273,14 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
switch (wall[w].lotag)
{
case TAG_WALL_SLIDOR_LEFT:
{
// prev wall
pw = w - 1;
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{
// white wall - move 4 points
interp_func(&wall[w].x);
@ -291,21 +292,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
{
// red wall - move 2 points
interp_func(&wall[w].x);
interp_func(&wall[DRAG_WALL(w)].x);
interp_func(&wall[wall[nextwall].point2].x);
interp_func(&wall[wall[w].point2].x);
interp_func(&wall[DRAG_WALL(wall[w].point2)].x);
interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].x);
}
break;
}
case TAG_WALL_SLIDOR_RIGHT:
{
// prev wall
pw = w - 1;
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{
// white wall - move 4 points
interp_func(&wall[w].x);
@ -317,21 +320,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
{
// red wall - move 2 points
interp_func(&wall[w].x);
interp_func(&wall[DRAG_WALL(w)].x);
interp_func(&wall[wall[nextwall].point2].x);
interp_func(&wall[wall[w].point2].x);
interp_func(&wall[DRAG_WALL(wall[w].point2)].x);
interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].x);
}
break;
}
case TAG_WALL_SLIDOR_UP:
{
// prev wall
pw = w - 1;
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{
interp_func(&wall[w].y);
interp_func(&wall[pw].y);
@ -341,21 +346,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
else
{
interp_func(&wall[w].y);
interp_func(&wall[DRAG_WALL(w)].y);
interp_func(&wall[wall[nextwall].point2].y);
interp_func(&wall[wall[w].point2].y);
interp_func(&wall[DRAG_WALL(wall[w].point2)].y);
interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].y);
}
break;
}
case TAG_WALL_SLIDOR_DOWN:
{
// prev wall
pw = w - 1;
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{
interp_func(&wall[w].y);
interp_func(&wall[pw].y);
@ -365,14 +372,14 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
else
{
interp_func(&wall[w].y);
interp_func(&wall[DRAG_WALL(w)].y);
interp_func(&wall[wall[nextwall].point2].y);
interp_func(&wall[wall[w].point2].y);
interp_func(&wall[DRAG_WALL(wall[w].point2)].y);
interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].y);
}
break;
}
}
w = wall[w].point2;
}
@ -397,7 +404,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{
// white wall - move 4 points
wall[w].x -= amt;
@ -421,7 +428,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{
// white wall - move 4 points
wall[w].x += amt;
@ -445,7 +452,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{
wall[w].y -= amt;
wall[pw].y -= amt;
@ -467,7 +474,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall)
pw = endwall;
if (wall[w].nextwall < 0)
if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{
wall[w].y += amt;
wall[pw].y += amt;

View file

@ -2616,7 +2616,8 @@ SpriteSetup(void)
wallcount++;
if (TEST_BOOL5(sp))
{
if (wall[w].nextwall >= 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{
wall_shade[wallcount] = wall[wall[w].nextwall].shade;
wallcount++;
@ -2672,7 +2673,8 @@ SpriteSetup(void)
wallcount++;
if (TEST_BOOL5(sp))
{
if (wall[w].nextwall >= 0)
uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{
wall_shade[wallcount] = wall[wall[w].nextwall].shade;
wallcount++;
@ -2955,7 +2957,7 @@ SpriteSetup(void)
do
{
// DO NOT TAG WHITE WALLS!
if (wall[wall_num].nextwall >= 0)
if ((uint16_t)wall[wall_num].nextwall < MAXWALLS)
{
SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN);
}
@ -3070,8 +3072,9 @@ SpriteSetup(void)
do
{
SET(wall[wall_num].cstat, CSTAT_WALL_BLOCK_ACTOR);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].cstat, CSTAT_WALL_BLOCK_ACTOR);
uint16_t const nextwall = wall[wall_num].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].cstat, CSTAT_WALL_BLOCK_ACTOR);
wall_num = wall[wall_num].point2;
}
while (wall_num != start_wall);

View file

@ -872,8 +872,9 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop)
// each wall has this set - for collision detection
SET(wall[k].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
if (wall[k].nextwall >= 0)
SET(wall[wall[k].nextwall].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
uint16_t const nextwall = wall[k].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
}
}
@ -2117,7 +2118,8 @@ DetectSectorObjectByWall(WALLp wph)
// if outer wall check the NEXTWALL also
if (TEST(wp->extra, WALLFX_LOOP_OUTER))
{
if (wph == &wall[wp->nextwall])
uint16_t const nextwall = wp->nextwall;
if (nextwall < MAXWALLS && wph == &wall[nextwall])
return sop;
}

View file

@ -20654,7 +20654,7 @@ SWBOOL TestDontStick(short SpriteNum, short hit_sect, short hit_wall, int hit_z)
return TRUE;
// if blocking red wallo
if (TEST(wp->cstat, CSTAT_WALL_BLOCK) && wp->nextwall >= 0)
if (TEST(wp->cstat, CSTAT_WALL_BLOCK) && (uint16_t)wp->nextwall < MAXWALLS)
return TRUE;
return FALSE;