From d81f24a7caada0206cb96dddfde11c1d3d599a2a Mon Sep 17 00:00:00 2001 From: skyjake Date: Mon, 9 Apr 2012 18:56:13 +0300 Subject: [PATCH] Memory Zone: Attempt to avoid an infinite loop When freeing blocks in Z_Malloc(), make sure the 'start' pointer remains valid. --- doomsday/engine/portable/include/dd_zone.h | 7 ++++- doomsday/engine/portable/src/dd_zone.c | 35 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/doomsday/engine/portable/include/dd_zone.h b/doomsday/engine/portable/include/dd_zone.h index 31b3890db3..d82225609f 100644 --- a/doomsday/engine/portable/include/dd_zone.h +++ b/doomsday/engine/portable/include/dd_zone.h @@ -50,7 +50,12 @@ int Z_Init(void); void Z_Shutdown(void); void* Z_Malloc(size_t size, int tag, void* ptr); -void Z_Free(void* ptr); + +/** + * Free memory that was allocated with Z_Malloc. + */ +void Z_Free(void* ptr); + void Z_FreeTags(int lowTag, int highTag); void Z_CheckHeap(void); void Z_ChangeTag2(void* ptr, int tag); diff --git a/doomsday/engine/portable/src/dd_zone.c b/doomsday/engine/portable/src/dd_zone.c index f10c0d40b1..cd6de7d735 100644 --- a/doomsday/engine/portable/src/dd_zone.c +++ b/doomsday/engine/portable/src/dd_zone.c @@ -260,9 +260,13 @@ memblock_t *Z_GetBlock(void *ptr) #endif /** - * Free memory that was allocated with Z_Malloc. + * Frees a block of memory allocated with Z_Malloc. + * + * @param ptr Memory area to free. + * @param tracked Pointer to a tracked memory block. Will be updated + * if affected by the operation. */ -void Z_Free(void *ptr) +static void freeBlock(void* ptr, memblock_t** tracked) { memblock_t *block, *other; memvolume_t *volume; @@ -320,7 +324,8 @@ void Z_Free(void *ptr) other = block->prev; if(!other->user) - { // Merge with previous free block. + { + // Merge with previous free block. other->size += block->size; other->next = block->next; other->next->prev = other; @@ -329,11 +334,18 @@ void Z_Free(void *ptr) if(block == volume->zone->staticRover) volume->zone->staticRover = other; block = other; + + // Keep track of what happens to the referenced block. + if(tracked && *tracked == block) + { + *tracked = other; + } } other = block->next; if(!other->user) - { // Merge the next free block onto the end. + { + // Merge the next free block onto the end. block->size += other->size; block->next = other->next; block->next->prev = block; @@ -341,11 +353,22 @@ void Z_Free(void *ptr) volume->zone->rover = block; if(other == volume->zone->staticRover) volume->zone->staticRover = block; + + // Keep track of what happens to the referenced block. + if(tracked && *tracked == other) + { + *tracked = block; + } } unlockZone(); } +void Z_Free(void *ptr) +{ + freeBlock(ptr, 0); +} + static __inline boolean isFreeBlock(memblock_t* block) { return !block->user; @@ -536,9 +559,9 @@ void *Z_Malloc(size_t size, int tag, void *user) memblock_t* old = iter; iter = iter->prev; // Step back. #ifdef FAKE_MEMORY_ZONE - Z_Free(old->area); + freeBlock(old->area, &start); #else - Z_Free((byte *) old + sizeof(memblock_t)); + freeBlock((byte *) old + sizeof(memblock_t), &start); #endif } else