Make sure we commit enough memory in a new subheap.
diff --git a/memory/heap.c b/memory/heap.c
index da3477c..8750588 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -33,16 +33,16 @@
typedef struct tagARENA_INUSE
{
DWORD size; /* Block size; must be the first field */
- WORD threadId; /* Allocating thread id */
WORD magic; /* Magic number */
+ WORD threadId; /* Allocating thread id */
void *callerEIP; /* EIP of caller upon allocation */
} ARENA_INUSE;
typedef struct tagARENA_FREE
{
DWORD size; /* Block size; must be the first field */
- WORD threadId; /* Freeing thread id */
WORD magic; /* Magic number */
+ WORD threadId; /* Freeing thread id */
struct tagARENA_FREE *next; /* Next free arena */
struct tagARENA_FREE *prev; /* Prev free arena */
} ARENA_FREE;
@@ -446,7 +446,8 @@
{
HEAP_CreateFreeBlock( subheap, (char *)(pArena + 1) + size,
(pArena->size & ARENA_SIZE_MASK) - size );
- pArena->size = (pArena->size & ~ARENA_SIZE_MASK) | size;
+ /* assign size plus previous arena flags */
+ pArena->size = size | (pArena->size & ~ARENA_SIZE_MASK);
}
else
{
@@ -636,7 +637,12 @@
(DWORD)heap, size );
return NULL;
}
- size += sizeof(SUBHEAP) + sizeof(ARENA_FREE);
+ /* make sure that we have a big enough size *committed* to fit another
+ * last free arena in !
+ * So just one heap struct, one first free arena which will eventually
+ * get inuse, and HEAP_MIN_BLOCK_SIZE for the second free arena that
+ * might get assigned all remaining free space in HEAP_ShrinkBlock() */
+ size += sizeof(SUBHEAP) + sizeof(ARENA_FREE) + HEAP_MIN_BLOCK_SIZE;
if (!(subheap = HEAP_CreateSubHeap( heap, heap->flags, size,
max( HEAP_DEF_SIZE, size ) )))
return NULL;
@@ -721,6 +727,8 @@
if (!(pArena->prev->size & ARENA_FLAG_FREE) ||
(pArena->prev->magic != ARENA_FREE_MAGIC))
{
+ /* this often means that the prev arena got overwritten
+ * by a memory write before that prev arena */
ERR("Heap %08lx: prev arena %08lx invalid for %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
return FALSE;
@@ -1102,10 +1110,10 @@
if (!heapPtr) return NULL;
flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
flags |= heapPtr->flags;
- if (!(flags & HEAP_NO_SERIALIZE)) EnterCriticalSection( &heapPtr->critSection );
size = (size + 3) & ~3;
if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
+ if (!(flags & HEAP_NO_SERIALIZE)) EnterCriticalSection( &heapPtr->critSection );
/* Locate a suitable free block */
if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap )))