From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 44c9ad53196..e4a307bd23a 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1182,6 +1182,7 @@ static BOOL validate_free_block( const SUBHEAP *subheap, const struct block *blo if (!err && (flags & HEAP_FREE_CHECKING_ENABLED)) { const char *ptr = (char *)(entry + 1), *end = (char *)block + block_get_size( block ); + if (next) end -= sizeof(struct block *); if (end > commit_end) end = commit_end; while (!err && ptr < end) {
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index e4a307bd23a..d0f547faee7 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -383,29 +383,18 @@ static inline void notify_realloc( void const *ptr, SIZE_T size_old, SIZE_T size #endif }
-static void subheap_notify_free_all(SUBHEAP const *subheap) +static void notify_free_all( SUBHEAP *subheap ) { #ifdef VALGRIND_FREELIKE_BLOCK - char const *ptr = (char const *)subheap->base + subheap->headerSize; + struct block *block;
if (!RUNNING_ON_VALGRIND) return; if (!check_subheap( subheap )) return;
- while (ptr < (char const *)subheap->base + subheap->size) + for (block = first_block( subheap ); block; block = next_block( subheap, block )) { - if (*(const DWORD *)ptr & ARENA_FLAG_FREE) - { - ARENA_FREE const *pArena = (ARENA_FREE const *)ptr; - if (pArena->magic!=ARENA_FREE_MAGIC) ERR("bad free_magic @%p\n", pArena); - ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); - } - else - { - ARENA_INUSE const *pArena = (ARENA_INUSE const *)ptr; - if (pArena->magic == ARENA_INUSE_MAGIC) notify_free(pArena + 1); - else if (pArena->magic != ARENA_PENDING_MAGIC) ERR("bad inuse_magic @%p\n", pArena); - ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); - } + if (block_get_flags( block ) & ARENA_FLAG_FREE) continue; + if (block_get_type( block ) == ARENA_INUSE_MAGIC) notify_free( block + 1 ); } #endif } @@ -1531,13 +1520,13 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) LIST_FOR_EACH_ENTRY_SAFE( subheap, next, &heapPtr->subheap_list, SUBHEAP, entry ) { if (subheap == &heapPtr->subheap) continue; /* do this one last */ - subheap_notify_free_all(subheap); + notify_free_all( subheap ); list_remove( &subheap->entry ); size = 0; addr = subheap->base; NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); } - subheap_notify_free_all(&heapPtr->subheap); + notify_free_all( &heapPtr->subheap ); RtlFreeHeap( GetProcessHeap(), 0, heapPtr->pending_free ); size = 0; addr = heapPtr->subheap.base;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 52 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 28 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index d0f547faee7..ac994167f22 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1646,17 +1646,16 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt
static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size, void **ret ) { - struct block *next; - ARENA_INUSE *pArena; + SIZE_T old_data_size, old_size, data_size; + struct block *next, *block; SUBHEAP *subheap; - SIZE_T oldBlockSize, oldActualSize, rounded_size; NTSTATUS status;
- rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags); - if (rounded_size < size) return STATUS_NO_MEMORY; /* overflow */ - if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE; + data_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags); + if (data_size < size) return STATUS_NO_MEMORY; /* overflow */ + if (data_size < HEAP_MIN_DATA_SIZE) data_size = HEAP_MIN_DATA_SIZE;
- if (!(pArena = unsafe_block_from_ptr( heap, ptr, &subheap ))) return STATUS_INVALID_PARAMETER; + if (!(block = unsafe_block_from_ptr( heap, ptr, &subheap ))) return STATUS_INVALID_PARAMETER; if (!subheap) { if (!(*ret = realloc_large_block( heap, flags, ptr, size ))) return STATUS_NO_MEMORY; @@ -1665,49 +1664,46 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size
/* Check if we need to grow the block */
- oldBlockSize = (pArena->size & ARENA_SIZE_MASK); - oldActualSize = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes; - if (rounded_size > oldBlockSize) + old_data_size = (block->size & ARENA_SIZE_MASK); + old_size = (block->size & ARENA_SIZE_MASK) - block->unused_bytes; + if (data_size > old_data_size) { - if ((next = next_block( subheap, pArena )) && (block_get_flags( next ) & ARENA_FLAG_FREE) && - rounded_size < HEAP_MIN_LARGE_BLOCK_SIZE && rounded_size <= oldBlockSize + block_get_size( next )) + if ((next = next_block( subheap, block )) && (block_get_flags( next ) & ARENA_FLAG_FREE) && + data_size < HEAP_MIN_LARGE_BLOCK_SIZE && data_size <= old_data_size + block_get_size( next )) { /* The next block is free and large enough */ struct entry *entry = (struct entry *)next; list_remove( &entry->entry ); - pArena->size += block_get_size( next ); - if (!HEAP_Commit( subheap, pArena, rounded_size )) return STATUS_NO_MEMORY; - notify_realloc( pArena + 1, oldActualSize, size ); - shrink_used_block( subheap, pArena, rounded_size, size ); + block->size += block_get_size( next ); + if (!HEAP_Commit( subheap, block, data_size )) return STATUS_NO_MEMORY; + notify_realloc( block + 1, old_size, size ); + shrink_used_block( subheap, block, data_size, size ); } else { if (flags & HEAP_REALLOC_IN_PLACE_ONLY) return STATUS_NO_MEMORY; if ((status = heap_allocate( heap, flags & ~HEAP_ZERO_MEMORY, size, ret ))) return status; - memcpy( *ret, pArena + 1, oldActualSize ); - if (flags & HEAP_ZERO_MEMORY) memset( (char *)*ret + oldActualSize, 0, size - oldActualSize ); - notify_free( pArena + 1 ); - HEAP_MakeInUseBlockFree( subheap, pArena ); + memcpy( *ret, block + 1, old_size ); + if (flags & HEAP_ZERO_MEMORY) memset( (char *)*ret + old_size, 0, size - old_size ); + notify_free( ptr ); + HEAP_MakeInUseBlockFree( subheap, block ); return STATUS_SUCCESS; } } else { - notify_realloc( pArena + 1, oldActualSize, size ); - shrink_used_block( subheap, pArena, rounded_size, size ); + notify_realloc( block + 1, old_size, size ); + shrink_used_block( subheap, block, data_size, size ); }
/* Clear the extra bytes if needed */
- if (size > oldActualSize) - initialize_block( (char *)(pArena + 1) + oldActualSize, size - oldActualSize, - pArena->unused_bytes, flags ); - else - mark_block_tail( (char *)(pArena + 1) + size, pArena->unused_bytes, flags ); + if (size <= old_size) mark_block_tail( (char *)(block + 1) + size, block->unused_bytes, flags ); + else initialize_block( (char *)(block + 1) + old_size, size - old_size, block->unused_bytes, flags );
/* Return the new arena */
- *ret = pArena + 1; + *ret = block + 1; return STATUS_SUCCESS; }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index ac994167f22..9036d71fa05 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1536,17 +1536,16 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
static NTSTATUS heap_allocate( HEAP *heap, ULONG flags, SIZE_T size, void **ret ) { - ARENA_FREE *pArena; - ARENA_INUSE *pInUse; + struct block *block; + struct entry *entry; + SIZE_T data_size; SUBHEAP *subheap; - SIZE_T rounded_size; - - rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE( flags );
- if (rounded_size < size) return STATUS_NO_MEMORY; /* overflow */ - if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE; + data_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags); + if (data_size < size) return STATUS_NO_MEMORY; /* overflow */ + if (data_size < HEAP_MIN_DATA_SIZE) data_size = HEAP_MIN_DATA_SIZE;
- if (rounded_size >= HEAP_MIN_LARGE_BLOCK_SIZE) + if (data_size >= HEAP_MIN_LARGE_BLOCK_SIZE) { if (!(*ret = allocate_large_block( heap, flags, size ))) return STATUS_NO_MEMORY; return STATUS_SUCCESS; @@ -1554,29 +1553,29 @@ static NTSTATUS heap_allocate( HEAP *heap, ULONG flags, SIZE_T size, void **ret
/* Locate a suitable free block */
- if (!(pArena = HEAP_FindFreeBlock( heap, rounded_size, &subheap ))) return STATUS_NO_MEMORY; + if (!(entry = HEAP_FindFreeBlock( heap, data_size, &subheap ))) return STATUS_NO_MEMORY;
/* Remove the arena from the free list */
- list_remove( &pArena->entry ); + list_remove( &entry->entry );
/* Build the in-use arena */
- pInUse = (ARENA_INUSE *)pArena; + block = (struct block *)entry;
/* in-use arena is smaller than free arena, * so we have to add the difference to the size */ - pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); - pInUse->magic = ARENA_INUSE_MAGIC; + block->size = (block->size & ~ARENA_FLAG_FREE) + sizeof(*entry) - sizeof(*block); + block->magic = ARENA_INUSE_MAGIC;
/* Shrink the block */
- shrink_used_block( subheap, pInUse, rounded_size, size ); + shrink_used_block( subheap, block, data_size, size );
- notify_alloc( pInUse + 1, size, flags & HEAP_ZERO_MEMORY ); - initialize_block( pInUse + 1, size, pInUse->unused_bytes, flags ); + notify_alloc( block + 1, size, flags & HEAP_ZERO_MEMORY ); + initialize_block( block + 1, size, block->unused_bytes, flags );
- *ret = pInUse + 1; + *ret = block + 1; return STATUS_SUCCESS; }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 9036d71fa05..e3bfc3d37e7 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1065,13 +1065,12 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, * Find a free block at least as large as the requested size, and make sure * the requested size is committed. */ -static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, - SUBHEAP **ppSubHeap ) +static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T data_size, SUBHEAP **ppSubHeap ) { SUBHEAP *subheap; struct list *ptr; SIZE_T total_size; - FREE_LIST_ENTRY *pEntry = heap->freeList + get_freelist_index( size + sizeof(ARENA_INUSE) ); + FREE_LIST_ENTRY *pEntry = heap->freeList + get_freelist_index( data_size + sizeof(ARENA_INUSE) );
/* Find a suitable free list, and in it find a block large enough */
@@ -1081,10 +1080,10 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, ARENA_FREE *pArena = LIST_ENTRY( ptr, ARENA_FREE, entry ); SIZE_T arena_size = (pArena->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); - if (arena_size >= size) + if (arena_size >= data_size) { subheap = find_subheap( heap, (struct block *)pArena, FALSE ); - if (!HEAP_Commit( subheap, (ARENA_INUSE *)pArena, size )) return NULL; + if (!HEAP_Commit( subheap, (ARENA_INUSE *)pArena, data_size )) return NULL; *ppSubHeap = subheap; return pArena; } @@ -1094,7 +1093,7 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size,
if (!(heap->flags & HEAP_GROWABLE)) { - WARN("Not enough space in heap %p for %08lx bytes\n", heap, size ); + WARN("Not enough space in heap %p for %08lx bytes\n", heap, data_size ); return NULL; } /* make sure that we have a big enough size *committed* to fit another @@ -1102,8 +1101,8 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, * So just one heap struct, one first free arena which will eventually * get used, and a second free arena that might get assigned all remaining * free space in shrink_used_block() */ - total_size = size + ROUND_SIZE(sizeof(SUBHEAP)) + sizeof(ARENA_INUSE) + sizeof(ARENA_FREE); - if (total_size < size) return NULL; /* overflow */ + total_size = data_size + ROUND_SIZE(sizeof(SUBHEAP)) + sizeof(ARENA_INUSE) + sizeof(ARENA_FREE); + if (total_size < data_size) return NULL; /* overflow */
if ((subheap = HEAP_CreateSubHeap( heap, NULL, heap->flags, total_size, max( heap->grow_size, total_size ) )))
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index e3bfc3d37e7..6e64d0d7dfb 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1662,8 +1662,8 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size
/* Check if we need to grow the block */
- old_data_size = (block->size & ARENA_SIZE_MASK); - old_size = (block->size & ARENA_SIZE_MASK) - block->unused_bytes; + old_data_size = block_get_size( block ) - sizeof(*block); + old_size = block_get_size( block ) - block_get_overhead( block ); if (data_size > old_data_size) { if ((next = next_block( subheap, block )) && (block_get_flags( next ) & ARENA_FLAG_FREE) &&