[PATCH 1/6] ntdll: Use a block member in large blocks.

Rémi Bernon wine at gitlab.winehq.org
Fri Jun 3 03:14:23 CDT 2022


From: Rémi Bernon <rbernon at codeweavers.com>

Signed-off-by: Rémi Bernon <rbernon at 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";
 
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/178



More information about the wine-devel mailing list