https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7246909a80cdb8dc420981974c21bbbdbf0bd48b

commit 7246909a80cdb8dc420981974c21bbbdbf0bd48b
Author:     Thomas Faber <[email protected]>
AuthorDate: Sun Feb 3 13:57:21 2019 +0100
Commit:     Thomas Faber <[email protected]>
CommitDate: Sun Feb 17 09:51:12 2019 +0100

    [RTL] Protect pointer validity check in RtlFreeHeap with SEH.
    
    Fixes crash in kernel32_winetest:heap.
---
 sdk/lib/rtl/heap.c | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/sdk/lib/rtl/heap.c b/sdk/lib/rtl/heap.c
index 1c6df2996f..4d47ee2ec9 100644
--- a/sdk/lib/rtl/heap.c
+++ b/sdk/lib/rtl/heap.c
@@ -2180,28 +2180,36 @@ BOOLEAN NTAPI RtlFreeHeap(
     if (RtlpHeapIsSpecial(Flags))
         return RtlDebugFreeHeap(Heap, Flags, Ptr);
 
-    /* Lock if necessary */
-    if (!(Flags & HEAP_NO_SERIALIZE))
-    {
-        RtlEnterHeapLock(Heap->LockVariable, TRUE);
-        Locked = TRUE;
-    }
-
     /* Get pointer to the heap entry */
     HeapEntry = (PHEAP_ENTRY)Ptr - 1;
 
-    /* Check this entry, fail if it's invalid */
-    if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY) ||
-        (((ULONG_PTR)Ptr & 0x7) != 0) ||
-        (HeapEntry->SegmentOffset >= HEAP_SEGMENTS))
+    /* Protect with SEH in case the pointer is not valid */
+    _SEH2_TRY
+    {
+        /* Check this entry, fail if it's invalid */
+        if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY) ||
+            (((ULONG_PTR)Ptr & 0x7) != 0) ||
+            (HeapEntry->SegmentOffset >= HEAP_SEGMENTS))
+        {
+            /* This is an invalid block */
+            DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
+            
RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
+            _SEH2_YIELD(return FALSE);
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        /* This is an invalid block */
+        /* The pointer was invalid */
         DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
+        _SEH2_YIELD(return FALSE);
+    }
 
-        /* Release the heap lock */
-        if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
-        return FALSE;
+    /* Lock if necessary */
+    if (!(Flags & HEAP_NO_SERIALIZE))
+    {
+        RtlEnterHeapLock(Heap->LockVariable, TRUE);
+        Locked = TRUE;
     }
 
     if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)

Reply via email to