shithub: choc

Download patch

ref: 4070ecd92c45dadc80e048e1bc929bced925c232
parent: 13d87ff8f1f839a9b10178e00cfbe58aca1c6124
author: Simon Howard <[email protected]>
date: Fri Apr 23 16:46:29 EDT 2010

Add REJECT buffer overflow emulation, based on code from PrBoom+ (thanks
entryway). Fixes YDFEAR25.LMP.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 1914

--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -76,6 +76,7 @@
 int		numsides;
 side_t*		sides;
 
+static int      totallines;
 
 // BLOCKMAP
 // Created from axis aligned bounding box
@@ -534,7 +535,6 @@
     line_t**		linebuffer;
     int			i;
     int			j;
-    int			total;
     line_t*		li;
     sector_t*		sector;
     subsector_t*	ss;
@@ -552,21 +552,21 @@
 
     // 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,7 +643,78 @@
 	
 }
 
+// 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_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;