diff options
-rw-r--r-- | src/p_setup.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/src/p_setup.c b/src/p_setup.c index 2a3a8f85..385759f8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -76,6 +76,7 @@ line_t* lines; int numsides; side_t* sides; +static int totallines; // BLOCKMAP // Created from axis aligned bounding box @@ -534,7 +535,6 @@ void P_GroupLines (void) line_t** linebuffer; int i; int j; - int total; line_t* li; sector_t* sector; subsector_t* ss; @@ -552,21 +552,21 @@ void P_GroupLines (void) // count number of lines in each sector li = lines; - total = 0; + totallines = 0; for (i=0 ; i<numlines ; i++, li++) { - total++; + totallines++; li->frontsector->linecount++; if (li->backsector && li->backsector != li->frontsector) { li->backsector->linecount++; - total++; + totallines++; } } // build line tables for each sector - linebuffer = Z_Malloc (total*sizeof(line_t *), PU_LEVEL, 0); + linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0); for (i=0; i<numsectors; ++i) { @@ -643,6 +643,77 @@ void P_GroupLines (void) } +// Pad the REJECT lump with extra data when the lump is too small, +// to simulate a REJECT buffer overflow in Vanilla Doom. + +static void PadRejectArray(byte *array, unsigned int len) +{ + unsigned int i; + unsigned int byte_num; + byte *dest; + + // Values to pad the REJECT array with: + + unsigned int rejectpad[4] = + { + ((totallines * 4 + 3) & ~3) + 24, // Size + 0, // Part of z_zone block header + 50, // PU_LEVEL + 0x1d4a11 // DOOM_CONST_ZONEID + }; + + // Copy values from rejectpad into the destination array. + + dest = array; + + for (i=0; i<len && i<sizeof(rejectpad); ++i) + { + byte_num = i % 4; + *dest = (rejectpad[i / 4] >> (byte_num * 8)) & 0xff; + ++dest; + } + + // We only have a limited pad size. Print a warning if the + // REJECT lump is too small. + + if (len > sizeof(rejectpad)) + { + fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%i > %i)\n", + len, sizeof(rejectpad)); + + // Pad remaining space with 0xff. + + memset(array + sizeof(rejectpad), 0x00, len - sizeof(rejectpad)); + } +} + +static void P_LoadReject(int lumpnum) +{ + int minlength; + int lumplen; + + // Calculate the size that the REJECT lump *should* be. + + minlength = (numsectors * numsectors + 7) / 8; + + // If the lump meets the minimum length, it can be loaded directly. + // Otherwise, we need to allocate a buffer of the correct size + // and pad it with appropriate data. + + lumplen = W_LumpLength(lumpnum); + + if (lumplen >= minlength) + { + rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + else + { + rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); + W_ReadLump(lumpnum, rejectmatrix); + + PadRejectArray(rejectmatrix + lumplen, minlength - lumplen); + } +} // // P_SetupLevel @@ -719,9 +790,9 @@ P_SetupLevel P_LoadSubsectors (lumpnum+ML_SSECTORS); P_LoadNodes (lumpnum+ML_NODES); P_LoadSegs (lumpnum+ML_SEGS); - - rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL); + P_GroupLines (); + P_LoadReject (lumpnum+ML_REJECT); bodyqueslot = 0; deathmatch_p = deathmatchstarts; |