summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Howard2015-04-26 20:24:29 -0400
committerSimon Howard2015-04-26 20:24:29 -0400
commit3bed35a90afe33571048edff4b38db07138aaaed (patch)
tree8460832a9d4657e0ed68e8e09861cfc0a3801523 /src
parent1bcff874c52aca3134cee636178ab5d6272fef58 (diff)
downloadchocolate-doom-3bed35a90afe33571048edff4b38db07138aaaed.tar.gz
chocolate-doom-3bed35a90afe33571048edff4b38db07138aaaed.tar.bz2
chocolate-doom-3bed35a90afe33571048edff4b38db07138aaaed.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/z_zone.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/z_zone.c b/src/z_zone.c
index 16da22b9..91f31fb2 100644
--- 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,8 +62,8 @@ typedef struct
-memzone_t* mainzone;
-
+static memzone_t *mainzone;
+static boolean zero_on_free;
//
@@ -110,13 +111,19 @@ void Z_Init (void)
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 @@ void Z_Free (void* ptr)
{
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 @@ void Z_Free (void* ptr)
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 @@ void Z_Free (void* ptr)
block = other;
}
-
+
other = block->next;
if (other->tag == PU_FREE)
{
@@ -285,7 +299,7 @@ Z_Malloc
mainzone->rover = base->next;
base->id = ZONEID;
-
+
return result;
}