Commit 1526ac75 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

ntdll: Compute block size before calling heap_(re)allocate.

parent e7827fc8
...@@ -1481,7 +1481,7 @@ static SIZE_T heap_get_block_size( const struct heap *heap, ULONG flags, SIZE_T ...@@ -1481,7 +1481,7 @@ static SIZE_T heap_get_block_size( const struct heap *heap, ULONG flags, SIZE_T
{ {
static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS | HEAP_ADD_USER_INFO; static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS | HEAP_ADD_USER_INFO;
static const ULONG check_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_CHECKING_ENABLED; static const ULONG check_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_CHECKING_ENABLED;
SIZE_T overhead; SIZE_T overhead, block_size;
if ((flags & check_flags)) overhead = BLOCK_ALIGN; if ((flags & check_flags)) overhead = BLOCK_ALIGN;
else overhead = sizeof(struct block); else overhead = sizeof(struct block);
...@@ -1490,19 +1490,19 @@ static SIZE_T heap_get_block_size( const struct heap *heap, ULONG flags, SIZE_T ...@@ -1490,19 +1490,19 @@ static SIZE_T heap_get_block_size( const struct heap *heap, ULONG flags, SIZE_T
if (flags & padd_flags) overhead += BLOCK_ALIGN; if (flags & padd_flags) overhead += BLOCK_ALIGN;
if (size < BLOCK_ALIGN) size = BLOCK_ALIGN; if (size < BLOCK_ALIGN) size = BLOCK_ALIGN;
return ROUND_SIZE( size + overhead, BLOCK_ALIGN - 1 ); block_size = ROUND_SIZE( size + overhead, BLOCK_ALIGN - 1 );
if (block_size < size) return ~0U; /* overflow */
if (block_size < HEAP_MIN_BLOCK_SIZE) block_size = HEAP_MIN_BLOCK_SIZE;
return block_size;
} }
static NTSTATUS heap_allocate( struct heap *heap, ULONG flags, SIZE_T size, void **ret ) static NTSTATUS heap_allocate( struct heap *heap, ULONG flags, SIZE_T block_size, SIZE_T size, void **ret )
{ {
SIZE_T old_block_size, block_size; SIZE_T old_block_size;
struct block *block; struct block *block;
SUBHEAP *subheap; SUBHEAP *subheap;
block_size = heap_get_block_size( heap, flags, size );
if (block_size < size) return STATUS_NO_MEMORY; /* overflow */
if (block_size < HEAP_MIN_BLOCK_SIZE) block_size = HEAP_MIN_BLOCK_SIZE;
if (block_size >= HEAP_MIN_LARGE_BLOCK_SIZE) if (block_size >= HEAP_MIN_LARGE_BLOCK_SIZE)
{ {
if (!(block = allocate_large_block( heap, flags, size ))) return STATUS_NO_MEMORY; if (!(block = allocate_large_block( heap, flags, size ))) return STATUS_NO_MEMORY;
...@@ -1533,16 +1533,19 @@ static NTSTATUS heap_allocate( struct heap *heap, ULONG flags, SIZE_T size, void ...@@ -1533,16 +1533,19 @@ static NTSTATUS heap_allocate( struct heap *heap, ULONG flags, SIZE_T size, void
void *WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE handle, ULONG flags, SIZE_T size ) void *WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE handle, ULONG flags, SIZE_T size )
{ {
struct heap *heap; struct heap *heap;
SIZE_T block_size;
void *ptr = NULL; void *ptr = NULL;
ULONG heap_flags; ULONG heap_flags;
NTSTATUS status; NTSTATUS status;
if (!(heap = unsafe_heap_from_handle( handle, flags, &heap_flags ))) if (!(heap = unsafe_heap_from_handle( handle, flags, &heap_flags )))
status = STATUS_INVALID_HANDLE; status = STATUS_INVALID_HANDLE;
else if ((block_size = heap_get_block_size( heap, heap_flags, size )) == ~0U)
status = STATUS_NO_MEMORY;
else else
{ {
heap_lock( heap, heap_flags ); heap_lock( heap, heap_flags );
status = heap_allocate( heap, heap_flags, size, &ptr ); status = heap_allocate( heap, heap_flags, block_size, size, &ptr );
heap_unlock( heap, heap_flags ); heap_unlock( heap, heap_flags );
} }
...@@ -1594,17 +1597,14 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE handle, ULONG flags, void * ...@@ -1594,17 +1597,14 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE handle, ULONG flags, void *
} }
static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE_T size, void **ret ) static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr,
SIZE_T block_size, SIZE_T size, void **ret )
{ {
SIZE_T old_block_size, old_size, block_size; SIZE_T old_block_size, old_size;
struct block *next, *block; struct block *next, *block;
SUBHEAP *subheap; SUBHEAP *subheap;
NTSTATUS status; NTSTATUS status;
block_size = heap_get_block_size( heap, flags, size );
if (block_size < size) return STATUS_NO_MEMORY; /* overflow */
if (block_size < HEAP_MIN_BLOCK_SIZE) block_size = HEAP_MIN_BLOCK_SIZE;
if (!(block = 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 (block_get_flags( block ) & BLOCK_FLAG_LARGE) if (block_get_flags( block ) & BLOCK_FLAG_LARGE)
{ {
...@@ -1632,7 +1632,7 @@ static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE ...@@ -1632,7 +1632,7 @@ static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE
else else
{ {
if (flags & HEAP_REALLOC_IN_PLACE_ONLY) return STATUS_NO_MEMORY; if (flags & HEAP_REALLOC_IN_PLACE_ONLY) return STATUS_NO_MEMORY;
if ((status = heap_allocate( heap, flags & ~HEAP_ZERO_MEMORY, size, ret ))) return status; if ((status = heap_allocate( heap, flags & ~HEAP_ZERO_MEMORY, block_size, size, ret ))) return status;
valgrind_notify_alloc( *ret, size, 0 ); valgrind_notify_alloc( *ret, size, 0 );
memcpy( *ret, block + 1, old_size ); memcpy( *ret, block + 1, old_size );
if (flags & HEAP_ZERO_MEMORY) memset( (char *)*ret + old_size, 0, size - old_size ); if (flags & HEAP_ZERO_MEMORY) memset( (char *)*ret + old_size, 0, size - old_size );
...@@ -1659,6 +1659,7 @@ static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE ...@@ -1659,6 +1659,7 @@ static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE
void *WINAPI RtlReAllocateHeap( HANDLE handle, ULONG flags, void *ptr, SIZE_T size ) void *WINAPI RtlReAllocateHeap( HANDLE handle, ULONG flags, void *ptr, SIZE_T size )
{ {
struct heap *heap; struct heap *heap;
SIZE_T block_size;
ULONG heap_flags; ULONG heap_flags;
void *ret = NULL; void *ret = NULL;
NTSTATUS status; NTSTATUS status;
...@@ -1667,10 +1668,12 @@ void *WINAPI RtlReAllocateHeap( HANDLE handle, ULONG flags, void *ptr, SIZE_T si ...@@ -1667,10 +1668,12 @@ void *WINAPI RtlReAllocateHeap( HANDLE handle, ULONG flags, void *ptr, SIZE_T si
if (!(heap = unsafe_heap_from_handle( handle, flags, &heap_flags ))) if (!(heap = unsafe_heap_from_handle( handle, flags, &heap_flags )))
status = STATUS_INVALID_HANDLE; status = STATUS_INVALID_HANDLE;
else if ((block_size = heap_get_block_size( heap, heap_flags, size )) == ~0U)
status = STATUS_NO_MEMORY;
else else
{ {
heap_lock( heap, heap_flags ); heap_lock( heap, heap_flags );
status = heap_reallocate( heap, heap_flags, ptr, size, &ret ); status = heap_reallocate( heap, heap_flags, ptr, block_size, size, &ret );
heap_unlock( heap, heap_flags ); heap_unlock( heap, heap_flags );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment