Rémi Bernon : ntdll: Raise debug exceptions when invalid heap is destroyed.
Alexandre Julliard
julliard at winehq.org
Fri Nov 20 14:54:32 CST 2020
Module: wine
Branch: master
Commit: 255270373e036f06578f71afa7af8765212e0652
URL: https://source.winehq.org/git/wine.git/?a=commit;h=255270373e036f06578f71afa7af8765212e0652
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Thu Nov 19 10:25:23 2020 +0100
ntdll: Raise debug exceptions when invalid heap is destroyed.
And when PEB->BeingDebugged is set to 1. Lords Of The Fallen anti-tamper
does this and only continues if a DBG_PRINTEXCEPTION_C is received.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/heap.c | 6 +++++
dlls/ntdll/tests/rtl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 1ac0cb24806..88db935746a 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -1589,6 +1589,12 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
void *addr;
TRACE("%p\n", heap );
+ if (!heapPtr && heap && (((HEAP *)heap)->flags & HEAP_VALIDATE_PARAMS) &&
+ NtCurrentTeb()->Peb->BeingDebugged)
+ {
+ DbgPrint( "Attempt to destroy an invalid heap\n" );
+ DbgBreakPoint();
+ }
if (!heapPtr) return heap;
if (heap == processHeap) return heap; /* cannot delete the main process heap */
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index ae8170f41fe..897be4fcd12 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -3599,6 +3599,71 @@ static void test_DbgPrint(void)
RtlRemoveVectoredExceptionHandler( handler );
}
+static BOOL test_heap_destroy_dbgstr = FALSE;
+static BOOL test_heap_destroy_break = FALSE;
+
+static LONG CALLBACK test_heap_destroy_except_handler( EXCEPTION_POINTERS *eptrs )
+{
+ if (eptrs->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
+ {
+#if defined( __i386__ )
+ eptrs->ContextRecord->Eip += 1;
+ test_heap_destroy_break = TRUE;
+ return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+#elif defined( __x86_64__ )
+ eptrs->ContextRecord->Rip += 1;
+ test_heap_destroy_break = TRUE;
+ return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+#endif
+ }
+
+ if (eptrs->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
+ {
+ test_heap_destroy_dbgstr = TRUE;
+ return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ return (LONG)EXCEPTION_CONTINUE_SEARCH;
+}
+
+/* partially copied from ntdll/heap.c */
+#define HEAP_VALIDATE_PARAMS 0x40000000
+
+struct heap
+{
+ DWORD_PTR unknown1[2];
+ DWORD unknown2[2];
+ DWORD_PTR unknown3[4];
+ DWORD unknown4;
+ DWORD_PTR unknown5[2];
+ DWORD unknown6[3];
+ DWORD_PTR unknown7[2];
+ DWORD flags;
+ DWORD force_flags;
+ DWORD_PTR unknown8[6];
+};
+
+static void test_RtlDestroyHeap(void)
+{
+ const struct heap invalid = {{0, 0}, {0, HEAP_VALIDATE_PARAMS}, {0, 0, 0, 0}, 0, {0, 0}, {0, 0, 0}, {0, 0}, HEAP_VALIDATE_PARAMS, 0, {0}};
+ HANDLE heap = (HANDLE)&invalid, ret;
+ PEB *Peb = NtCurrentTeb()->Peb;
+ BOOL debugged;
+ void *handler = RtlAddVectoredExceptionHandler( TRUE, test_heap_destroy_except_handler );
+
+ test_heap_destroy_dbgstr = FALSE;
+ test_heap_destroy_break = FALSE;
+ debugged = Peb->BeingDebugged;
+ Peb->BeingDebugged = TRUE;
+ ret = RtlDestroyHeap( heap );
+ ok( ret == heap, "RtlDestroyHeap(%p) returned %p\n", heap, ret );
+ ok( test_heap_destroy_dbgstr, "HeapDestroy didn't call OutputDebugStrA\n" );
+ ok( test_heap_destroy_break, "HeapDestroy didn't call DbgBreakPoint\n" );
+ Peb->BeingDebugged = debugged;
+
+ RtlRemoveVectoredExceptionHandler( handler );
+}
+
START_TEST(rtl)
{
InitFunctionPtrs();
@@ -3640,4 +3705,5 @@ START_TEST(rtl)
test_RtlMakeSelfRelativeSD();
test_LdrRegisterDllNotification();
test_DbgPrint();
+ test_RtlDestroyHeap();
}
More information about the wine-cvs
mailing list