Engine: stricter map load time checking for sprites with oob sectnums.

Sprites are now considered to have out of bounds sector numbers if it is
< 0 or >= numsectors (not merely >= MAXSECTORS). If such a sprite is now
encountered during post-load, an attempt is made first to assign it a sector
number (using updatesector()). If that fails, the sprite is removed from the
map.  The background is that a dozen of maps do come with such sprites and
could previously corrupt the sprite list when loaded.

git-svn-id: https://svn.eduke32.com/eduke32@3696 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-04-21 19:55:18 +00:00
parent 08b10ca03c
commit 520b608094
3 changed files with 83 additions and 28 deletions

View file

@ -8547,7 +8547,7 @@ static int32_t deletesector(int16_t sucksect)
int32_t fixspritesectors(void) int32_t fixspritesectors(void)
{ {
int32_t i, j, dax, day, cz, fz; int32_t i;
int32_t numfixedsprites = 0, printfirsttime = 0; int32_t numfixedsprites = 0, printfirsttime = 0;
for (i=numsectors-1; i>=0; i--) for (i=numsectors-1; i>=0; i--)
@ -8566,11 +8566,12 @@ int32_t fixspritesectors(void)
for (i=0; i<MAXSPRITES; i++) for (i=0; i<MAXSPRITES; i++)
if (sprite[i].statnum < MAXSTATUS) if (sprite[i].statnum < MAXSTATUS)
{ {
dax = sprite[i].x; const int32_t dax=sprite[i].x, day=sprite[i].y;
day = sprite[i].y;
if (inside(dax,day,sprite[i].sectnum) != 1) if (inside(dax,day,sprite[i].sectnum) != 1)
{ {
int32_t j, cz, fz;
spriteoncfz(i, &cz, &fz); spriteoncfz(i, &cz, &fz);
for (j=0; j<numsectors; j++) for (j=0; j<numsectors; j++)
@ -8589,7 +8590,8 @@ int32_t fixspritesectors(void)
initprintf("--------------------\n"); initprintf("--------------------\n");
printfirsttime = 1; printfirsttime = 1;
} }
initprintf_nowarn("Changed sectnum of sprite %d from %d to %d\n", i, TrackerCast(sprite[i].sectnum), j); initprintf_nowarn("Changed sectnum of sprite #%d from %d to %d\n",
i, TrackerCast(sprite[i].sectnum), j);
changespritesect(i, j); changespritesect(i, j);
} }
break; break;

View file

@ -9601,7 +9601,7 @@ static void prepare_loadboard(int32_t fil, vec3_t *dapos, int16_t *daang, int16_
static void finish_loadboard(const vec3_t *dapos, int16_t *dacursectnum, int16_t numsprites, char myflags) static void finish_loadboard(const vec3_t *dapos, int16_t *dacursectnum, int16_t numsprites, char myflags)
{ {
int32_t i; int32_t i, realnumsprites=numsprites;
#if !defined USE_OPENGL || !defined POLYMER #if !defined USE_OPENGL || !defined POLYMER
UNREFERENCED_PARAMETER(myflags); UNREFERENCED_PARAMETER(myflags);
@ -9609,12 +9609,44 @@ static void finish_loadboard(const vec3_t *dapos, int16_t *dacursectnum, int16_t
for (i=0; i<numsprites; i++) for (i=0; i<numsprites; i++)
{ {
int32_t removeit = 0;
if ((sprite[i].cstat & 48) == 48) if ((sprite[i].cstat & 48) == 48)
sprite[i].cstat &= ~48; sprite[i].cstat &= ~48;
if (sprite[i].statnum == MAXSTATUS)
{
// Sprite was removed in loadboard() -> check_sprite(). Insert it
// for now, because we must maintain the sprite numbering.
sprite[i].statnum = sprite[i].sectnum = 0;
removeit = 1;
}
insertsprite(sprite[i].sectnum, sprite[i].statnum); insertsprite(sprite[i].sectnum, sprite[i].statnum);
if (removeit)
{
// Flag .statnum==MAXSTATUS, temporarily creating an inconsistency
// with sprite list.
sprite[i].statnum = MAXSTATUS;
realnumsprites--;
}
} }
if (numsprites != realnumsprites)
{
for (i=0; i<numsprites; i++)
if (sprite[i].statnum == MAXSTATUS)
{
// Now remove it for real!
sprite[i].statnum = 0;
deletesprite(i);
}
}
numsprites = realnumsprites;
Bassert(numsprites == Numsprites);
//Must be after loading sectors, etc! //Must be after loading sectors, etc!
updatesector(dapos->x, dapos->y, dacursectnum); updatesector(dapos->x, dapos->y, dacursectnum);
@ -9645,31 +9677,47 @@ static void finish_loadboard(const vec3_t *dapos, int16_t *dacursectnum, int16_t
#define MYMAXWALLS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXWALLSV7 : MAXWALLSV8) #define MYMAXWALLS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXWALLSV7 : MAXWALLSV8)
#define MYMAXSPRITES() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSPRITESV7 : MAXSPRITESV8) #define MYMAXSPRITES() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSPRITESV7 : MAXSPRITESV8)
// Sprite checking
static void remove_sprite(int32_t i)
{
Bmemset(&sprite[i], 0, sizeof(spritetype));
sprite[i].statnum = MAXSTATUS;
sprite[i].sectnum = MAXSECTORS;
}
// This is only to be run after reading the sprite array!
static void check_sprite(int32_t i) static void check_sprite(int32_t i)
{ {
if ((unsigned)sprite[i].sectnum >= MYMAXSECTORS()) if ((unsigned)sprite[i].statnum >= MAXSTATUS)
{ {
initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal sector (%d). Map is corrupt!\n", initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal statnum (%d) REMOVED.\n",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].statnum));
remove_sprite(i);
}
else if ((unsigned)sprite[i].picnum >= MAXTILES)
{
initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal picnum (%d) REMOVED.\n",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum)); i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum));
remove_sprite(i);
}
else if ((unsigned)sprite[i].sectnum >= (unsigned)numsectors)
{
const int32_t osectnum = sprite[i].sectnum;
sprite[i].sectnum = -1;
updatesector(sprite[i].x, sprite[i].y, &sprite[i].sectnum); updatesector(sprite[i].x, sprite[i].y, &sprite[i].sectnum);
if (sprite[i].sectnum < 0) if (sprite[i].sectnum < 0)
sprite[i].sectnum = 0; remove_sprite(i);
}
if ((unsigned)sprite[i].statnum >= MAXSTATUS) initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal sector (%d) ",
{ i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), osectnum);
initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal statnum (%d). Map is corrupt!\n",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].statnum));
sprite[i].statnum = 0;
}
if ((unsigned)sprite[i].picnum >= MAXTILES) if (sprite[i].statnum != MAXSTATUS)
{ initprintf_nowarn("changed to sector %d.\n", TrackerCast(sprite[i].sectnum));
initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal picnum (%d). Map is corrupt!\n", else
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum)); initprintf_nowarn("REMOVED.\n");
sprite[i].picnum = 0;
} }
} }
@ -9777,6 +9825,9 @@ int32_t loadboard(char *filename, char flags, vec3_t *dapos, int16_t *daang, int
kread(fil, sprite, sizeof(spritetype)*numsprites); kread(fil, sprite, sizeof(spritetype)*numsprites);
kclose(fil);
// Done reading file.
for (i=numsprites-1; i>=0; i--) for (i=numsprites-1; i>=0; i--)
{ {
sprite[i].x = B_LITTLE32(sprite[i].x); sprite[i].x = B_LITTLE32(sprite[i].x);
@ -9798,9 +9849,6 @@ int32_t loadboard(char *filename, char flags, vec3_t *dapos, int16_t *daang, int
check_sprite(i); check_sprite(i);
} }
kclose(fil);
// Done reading file.
#ifdef YAX_ENABLE #ifdef YAX_ENABLE
yax_update(mapversion<9); yax_update(mapversion<9);
if (editstatus) if (editstatus)

View file

@ -11467,20 +11467,25 @@ static int32_t check_spritelist_consistency()
for (i=0; i<MAXSPRITES; i++) for (i=0; i<MAXSPRITES; i++)
{ {
const int32_t sectnum=sprite[i].sectnum, statnum=sprite[i].statnum;
csc_i = i; csc_i = i;
if ((sprite[i].statnum==MAXSTATUS) != (sprite[i].sectnum==MAXSECTORS)) if ((statnum==MAXSTATUS) != (sectnum==MAXSECTORS))
return 2; // violation of .statnum==MAXSTATUS iff .sectnum==MAXSECTORS return 2; // violation of .statnum==MAXSTATUS iff .sectnum==MAXSECTORS
if ((unsigned)sprite[i].statnum > MAXSTATUS || (unsigned)sprite[i].sectnum > MAXSECTORS) if ((unsigned)statnum > MAXSTATUS || (sectnum!=MAXSECTORS && (unsigned)sectnum > (unsigned)numsectors))
return 3; // oob sectnum or statnum return 3; // oob sectnum or statnum
if (sprite[i].statnum != MAXSTATUS) if (statnum != MAXSTATUS)
ournumsprites++; ournumsprites++;
} }
if (ournumsprites != Numsprites) if (ournumsprites != Numsprites)
{
initprintf("ournumsprites=%d, Numsprites=%d\n", ournumsprites, Numsprites);
return 4; // counting sprites by statnum!=MAXSTATUS inconsistent with Numsprites return 4; // counting sprites by statnum!=MAXSTATUS inconsistent with Numsprites
}
// SECTOR LIST // SECTOR LIST
@ -11917,8 +11922,8 @@ int32_t CheckMapCorruption(int32_t printfromlev, uint64_t tryfixing)
{ {
int32_t onumct = numcorruptthings; int32_t onumct = numcorruptthings;
CORRUPTCHK_PRINT(3, CORRUPT_SPRITE|i, "SPRITE %d at [%d, %d] is out of the maximal grid range [%d, %d]", CORRUPTCHK_PRINT(3, CORRUPT_SPRITE|i, "SPRITE %d at [%d, %d] is outside the maximal grid range [%d, %d]",
TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), i, -BXY_MAX, BXY_MAX); i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), -BXY_MAX, BXY_MAX);
if (onumct < MAXCORRUPTTHINGS) if (onumct < MAXCORRUPTTHINGS)
{ {