From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 3 --- dlls/ntdll/heap.c | 26 +++++++++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 91f582f36de..99602bd2969 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -354,9 +354,7 @@ static void test_HeapCreate(void) ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() ); align |= (UINT_PTR)ptrs[i]; } - todo_wine_if( sizeof(void *) == 8 ) ok( !(align & (8 * sizeof(void *) - 1)), "got wrong alignment\n" ); - todo_wine_if( sizeof(void *) == 8 ) ok( align & (8 * sizeof(void *)), "got wrong alignment\n" ); for (i = 0; i < ARRAY_SIZE(ptrs); ++i) { @@ -2228,7 +2226,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; - todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 ) ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) ); diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 0ecff6f6cba..3184ae43dab 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -91,6 +91,7 @@ C_ASSERT( sizeof(struct block) == 8 ); #define BLOCK_FLAG_FREE 0x00000001 #define BLOCK_FLAG_PREV_FREE 0x00000002 #define BLOCK_FLAG_FREE_LINK 0x00000003 +#define BLOCK_FLAG_LARGE 0x00000004
/* entry to link free blocks in free lists */ @@ -103,18 +104,21 @@ struct DECLSPEC_ALIGN(ALIGNMENT) entry
C_ASSERT( sizeof(struct entry) == 2 * ALIGNMENT );
-typedef struct +typedef struct region { + SIZE_T __pad[sizeof(SIZE_T) / sizeof(DWORD)]; struct list entry; /* entry in heap large blocks list */ SIZE_T data_size; /* size of user data */ SIZE_T block_size; /* total size of virtual memory block */ - DWORD pad[2]; /* padding to ensure 16-byte alignment of data */ - DWORD size; /* fields for compatibility with normal arenas */ - DWORD magic; /* these must remain at the end of the structure */ + SIZE_T pad; /* padding to ensure 16-byte alignment of data */ + struct block block; } ARENA_LARGE;
+/* block must be last and aligned */ +C_ASSERT( sizeof(struct region) == offsetof(struct region, block) + sizeof(struct block) ); +C_ASSERT( sizeof(struct region) == 4 * ALIGNMENT ); + #define ARENA_SIZE_MASK (~3) -#define ARENA_LARGE_SIZE 0xfedcba90 /* magic value for 'size' field in large blocks */
/* Value for arena 'magic' field */ #define ARENA_INUSE_MAGIC 0x455355 @@ -800,8 +804,8 @@ static void *allocate_large_block( HEAP *heap, DWORD flags, SIZE_T size ) arena = address; arena->data_size = size; arena->block_size = block_size; - arena->size = ARENA_LARGE_SIZE; - arena->magic = ARENA_LARGE_MAGIC; + block_set_type( &arena->block, ARENA_LARGE_MAGIC ); + block_set_size( &arena->block, BLOCK_FLAG_LARGE, 0 ); list_add_tail( &heap->large_list, &arena->entry ); valgrind_make_noaccess( (char *)arena + sizeof(*arena) + arena->data_size, arena->block_size - sizeof(*arena) - arena->data_size ); @@ -875,8 +879,12 @@ static BOOL validate_large_arena( const HEAP *heap, const ARENA_LARGE *arena )
if ((ULONG_PTR)arena & COMMIT_MASK) err = "invalid block alignment"; - else if (arena->size != ARENA_LARGE_SIZE || arena->magic != ARENA_LARGE_MAGIC) - err = "invalid block header"; + else if (block_get_size( &arena->block )) + err = "invalid block size"; + else if (block_get_flags( &arena->block ) != BLOCK_FLAG_LARGE) + err = "invalid block flags"; + else if (block_get_type( &arena->block ) != ARENA_LARGE_MAGIC) + err = "invalid block type"; else if (!contains( arena, arena->block_size, arena + 1, arena->data_size )) err = "invalid block size";