ref: 3bed35a90afe33571048edff4b38db07138aaaed
parent: 1bcff874c52aca3134cee636178ab5d6272fef58
author: Simon Howard <[email protected]>
date: Sun Apr 26 16:24:29 EDT 2015
zone: Add -zonezero parameter. As seen in bug #530, some of the game code can in some situations hold pointers to, and dereference, freed sections of the zone heap. Add a new command line parameter that zeroes out memory of blocks when they are freed with Z_Free(), hopefully exposing code that depends on reading freed memory.
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -16,10 +16,11 @@
// Zone Memory Allocation. Neat.
//
+#include "doomtype.h"
+#include "i_system.h"
+#include "m_argv.h"
#include "z_zone.h"
-#include "i_system.h"
-#include "doomtype.h"
//
@@ -61,10 +62,10 @@
-memzone_t* mainzone;
+static memzone_t *mainzone;
+static boolean zero_on_free;
-
//
// Z_ClearZone
//
@@ -110,13 +111,19 @@
mainzone->blocklist.user = (void *)mainzone;
mainzone->blocklist.tag = PU_STATIC;
mainzone->rover = block;
-
+
block->prev = block->next = &mainzone->blocklist;
// free block
block->tag = PU_FREE;
-
+
block->size = mainzone->size - sizeof(memzone_t);
+
+ //!
+ // Zone memory debugging flag. If set, zero memory after it is freed
+ // to deliberately break any code that attempts to use it after free.
+ //
+ zero_on_free = M_ParmExists("-zonezero");
}
@@ -127,12 +134,12 @@
{
memblock_t* block;
memblock_t* other;
-
+
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
I_Error ("Z_Free: freed a pointer without ZONEID");
-
+
if (block->tag != PU_FREE && block->user != NULL)
{
// clear the user's mark
@@ -143,7 +150,14 @@
block->tag = PU_FREE;
block->user = NULL;
block->id = 0;
-
+
+ // If the -zonezero flag is provided, we zero out the block on free
+ // to break code that depends on reading freed memory.
+ if (zero_on_free)
+ {
+ memset(ptr, 0, block->size - sizeof(memblock_t));
+ }
+
other = block->prev;
if (other->tag == PU_FREE)
@@ -158,7 +172,7 @@
block = other;
}
-
+
other = block->next;
if (other->tag == PU_FREE)
{
@@ -285,7 +299,7 @@
mainzone->rover = base->next;
base->id = ZONEID;
-
+
return result;
}