Alexandre Julliard : ntdll: Verify free block contents when validating the heap.

Alexandre Julliard julliard at winehq.org
Tue Jan 26 11:21:09 CST 2010


Module: wine
Branch: master
Commit: 6864777a107268ad1f05ebbe408be8dd38e7219e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6864777a107268ad1f05ebbe408be8dd38e7219e

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Jan 26 14:35:08 2010 +0100

ntdll: Verify free block contents when validating the heap.

---

 dlls/ntdll/heap.c |   35 ++++++++++++++++++++++++++---------
 1 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 9a80116..72a0069 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -1005,6 +1005,8 @@ static BOOL HEAP_IsValidArenaPtr( const HEAP *heap, const ARENA_FREE *ptr )
  */
 static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
 {
+    DWORD flags = subheap->heap->flags;
+    SIZE_T size;
     ARENA_FREE *prev, *next;
     char *heapEnd = (char *)subheap->base + subheap->size;
 
@@ -1030,10 +1032,10 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
         return FALSE;
     }
     /* Check arena size */
-    if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd)
+    size = pArena->size & ARENA_SIZE_MASK;
+    if ((char *)(pArena + 1) + size > heapEnd)
     {
-        ERR("Heap %p: bad size %08x for free arena %p\n",
-            subheap->heap, pArena->size & ARENA_SIZE_MASK, pArena );
+        ERR("Heap %p: bad size %08lx for free arena %p\n", subheap->heap, size, pArena );
         return FALSE;
     }
     /* Check that next pointer is valid */
@@ -1069,25 +1071,40 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
         return FALSE;
     }
     /* Check that next block has PREV_FREE flag */
-    if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd)
+    if ((char *)(pArena + 1) + size < heapEnd)
     {
-        if (!(*(DWORD *)((char *)(pArena + 1) +
-            (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE))
+        if (!(*(DWORD *)((char *)(pArena + 1) + size) & ARENA_FLAG_PREV_FREE))
         {
             ERR("Heap %p: free arena %p next block has no PREV_FREE flag\n",
                 subheap->heap, pArena );
             return FALSE;
         }
         /* Check next block back pointer */
-        if (*((ARENA_FREE **)((char *)(pArena + 1) +
-            (pArena->size & ARENA_SIZE_MASK)) - 1) != pArena)
+        if (*((ARENA_FREE **)((char *)(pArena + 1) + size) - 1) != pArena)
         {
             ERR("Heap %p: arena %p has wrong back ptr %p\n",
                 subheap->heap, pArena,
-                *((ARENA_FREE **)((char *)(pArena+1) + (pArena->size & ARENA_SIZE_MASK)) - 1));
+                *((ARENA_FREE **)((char *)(pArena+1) + size) - 1));
             return FALSE;
         }
     }
+    if (flags & HEAP_FREE_CHECKING_ENABLED)
+    {
+        DWORD *ptr = (DWORD *)(pArena + 1);
+        char *end = (char *)(pArena + 1) + size;
+
+        if (end >= heapEnd) end = (char *)subheap->base + subheap->commitSize;
+        while (ptr < (DWORD *)end - 1)
+        {
+            if (*ptr != ARENA_FREE_FILLER)
+            {
+                ERR("Heap %p: free block %p overwritten at %p by %08x\n",
+                    subheap->heap, (ARENA_INUSE *)pArena + 1, ptr, *ptr );
+                return FALSE;
+            }
+            ptr++;
+        }
+    }
     return TRUE;
 }
 




More information about the wine-cvs mailing list