Skip to content

Commit

Permalink
Memory Zone: Attempt to avoid an infinite loop
Browse files Browse the repository at this point in the history
When freeing blocks in Z_Malloc(), make sure the 'start' pointer remains valid.
  • Loading branch information
skyjake committed Apr 9, 2012
1 parent 9315f2d commit d81f24a
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
7 changes: 6 additions & 1 deletion doomsday/engine/portable/include/dd_zone.h
Expand Up @@ -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);
Expand Down
35 changes: 29 additions & 6 deletions doomsday/engine/portable/src/dd_zone.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -329,23 +334,41 @@ 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;
if(other == volume->zone->rover)
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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit d81f24a

Please sign in to comment.