diff options
author | Simon Howard | 2015-04-26 20:24:29 -0400 |
---|---|---|
committer | Simon Howard | 2015-04-26 20:24:29 -0400 |
commit | 3bed35a90afe33571048edff4b38db07138aaaed (patch) | |
tree | 8460832a9d4657e0ed68e8e09861cfc0a3801523 /src | |
parent | 1bcff874c52aca3134cee636178ab5d6272fef58 (diff) | |
download | chocolate-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.c | 36 |
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; } |