From 520b6080944e8c89bcafb7f3a90f0a6697f344e4 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 21 Apr 2013 19:55:18 +0000 Subject: [PATCH] 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 --- polymer/eduke32/build/src/build.c | 10 ++-- polymer/eduke32/build/src/engine.c | 86 +++++++++++++++++++++++------- polymer/eduke32/source/astub.c | 15 ++++-- 3 files changed, 83 insertions(+), 28 deletions(-) diff --git a/polymer/eduke32/build/src/build.c b/polymer/eduke32/build/src/build.c index 9b65803d1..4444b52db 100644 --- a/polymer/eduke32/build/src/build.c +++ b/polymer/eduke32/build/src/build.c @@ -8547,7 +8547,7 @@ static int32_t deletesector(int16_t sucksect) int32_t fixspritesectors(void) { - int32_t i, j, dax, day, cz, fz; + int32_t i; int32_t numfixedsprites = 0, printfirsttime = 0; for (i=numsectors-1; i>=0; i--) @@ -8566,11 +8566,12 @@ int32_t fixspritesectors(void) for (i=0; i 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); + + if (removeit) + { + // Flag .statnum==MAXSTATUS, temporarily creating an inconsistency + // with sprite list. + sprite[i].statnum = MAXSTATUS; + realnumsprites--; + } } + if (numsprites != realnumsprites) + { + for (i=0; ix, 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 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) { - 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)); + 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); 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 statnum (%d). Map is corrupt!\n", - i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].statnum)); - sprite[i].statnum = 0; - } + initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal sector (%d) ", + i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), osectnum); - if ((unsigned)sprite[i].picnum >= MAXTILES) - { - initprintf_nowarn(OSD_ERROR "Map error: sprite #%d (%d,%d) with illegal picnum (%d). Map is corrupt!\n", - i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum)); - sprite[i].picnum = 0; + if (sprite[i].statnum != MAXSTATUS) + initprintf_nowarn("changed to sector %d.\n", TrackerCast(sprite[i].sectnum)); + else + initprintf_nowarn("REMOVED.\n"); } } @@ -9777,6 +9825,9 @@ int32_t loadboard(char *filename, char flags, vec3_t *dapos, int16_t *daang, int kread(fil, sprite, sizeof(spritetype)*numsprites); + kclose(fil); + // Done reading file. + for (i=numsprites-1; i>=0; i--) { 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); } - kclose(fil); - // Done reading file. - #ifdef YAX_ENABLE yax_update(mapversion<9); if (editstatus) diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index eadef6944..28675454b 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -11467,20 +11467,25 @@ static int32_t check_spritelist_consistency() for (i=0; i MAXSTATUS || (unsigned)sprite[i].sectnum > MAXSECTORS) + if ((unsigned)statnum > MAXSTATUS || (sectnum!=MAXSECTORS && (unsigned)sectnum > (unsigned)numsectors)) return 3; // oob sectnum or statnum - if (sprite[i].statnum != MAXSTATUS) + if (statnum != MAXSTATUS) ournumsprites++; } if (ournumsprites != Numsprites) + { + initprintf("ournumsprites=%d, Numsprites=%d\n", ournumsprites, Numsprites); return 4; // counting sprites by statnum!=MAXSTATUS inconsistent with Numsprites + } // SECTOR LIST @@ -11917,8 +11922,8 @@ int32_t CheckMapCorruption(int32_t printfromlev, uint64_t tryfixing) { int32_t onumct = numcorruptthings; - CORRUPTCHK_PRINT(3, CORRUPT_SPRITE|i, "SPRITE %d at [%d, %d] is out of the maximal grid range [%d, %d]", - TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), i, -BXY_MAX, BXY_MAX); + CORRUPTCHK_PRINT(3, CORRUPT_SPRITE|i, "SPRITE %d at [%d, %d] is outside the maximal grid range [%d, %d]", + i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), -BXY_MAX, BXY_MAX); if (onumct < MAXCORRUPTTHINGS) {