Alexandre Julliard : kernel32: Catch stack overflow faults in IsBad*Ptr() functions.

Alexandre Julliard julliard at winehq.org
Mon Jan 13 16:11:52 CST 2020


Module: wine
Branch: master
Commit: 21876b998ce3dbb3245cc0a85aee80e0d6b03168
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=21876b998ce3dbb3245cc0a85aee80e0d6b03168

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jan 13 16:09:53 2020 +0100

kernel32: Catch stack overflow faults in IsBad*Ptr() functions.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48444
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/virtual.c | 12 ++++++++++++
 dlls/kernel32/virtual.c       | 29 +++++++++++++++++++++++------
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 120e9f16f0..c534e310ef 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -1533,6 +1533,12 @@ static void test_IsBadReadPtr(void)
 
     ret = IsBadReadPtr(&stackvar, sizeof(char));
     ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
+
+    ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
+    ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
+
+    ret = IsBadReadPtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
+    ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
 }
 
 static void test_IsBadWritePtr(void)
@@ -1558,6 +1564,12 @@ static void test_IsBadWritePtr(void)
 
     ret = IsBadWritePtr(&stackval, sizeof(char));
     ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
+
+    ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
+    ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
+
+    ret = IsBadWritePtr((char *)NtCurrentTeb()->DeallocationStack + 4096, sizeof(DWORD));
+    ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
 }
 
 static void test_IsBadCodePtr(void)
diff --git a/dlls/kernel32/virtual.c b/dlls/kernel32/virtual.c
index b9b0e08653..a35471f526 100644
--- a/dlls/kernel32/virtual.c
+++ b/dlls/kernel32/virtual.c
@@ -48,6 +48,23 @@ WINE_DECLARE_DEBUG_CHANNEL(seh);
 WINE_DECLARE_DEBUG_CHANNEL(file);
 
 
+static LONG WINAPI badptr_handler( EXCEPTION_POINTERS *eptr )
+{
+    EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
+
+    if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION) return EXCEPTION_EXECUTE_HANDLER;
+    if (rec->ExceptionCode == STATUS_STACK_OVERFLOW)
+    {
+        /* restore stack guard page */
+        void *addr = (char *)NtCurrentTeb()->DeallocationStack + system_info.PageSize;
+        SIZE_T size = (char *)rec - (char *)addr;
+        ULONG old_prot;
+        NtProtectVirtualMemory( GetCurrentProcess(), &addr, &size, PAGE_GUARD|PAGE_READWRITE, &old_prot );
+        return EXCEPTION_EXECUTE_HANDLER;
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
 /***********************************************************************
  *             IsBadReadPtr   (KERNEL32.@)
  *
@@ -79,7 +96,7 @@ BOOL WINAPI IsBadReadPtr( LPCVOID ptr, UINT_PTR size )
         dummy = p[0];
         dummy = p[count - 1];
     }
-    __EXCEPT_PAGE_FAULT
+    __EXCEPT( badptr_handler )
     {
         TRACE_(seh)("%p caused page fault during read\n", ptr);
         return TRUE;
@@ -120,7 +137,7 @@ BOOL WINAPI IsBadWritePtr( LPVOID ptr, UINT_PTR size )
         p[0] |= 0;
         p[count - 1] |= 0;
     }
-    __EXCEPT_PAGE_FAULT
+    __EXCEPT( badptr_handler )
     {
         TRACE_(seh)("%p caused page fault during write\n", ptr);
         return TRUE;
@@ -202,13 +219,13 @@ BOOL WINAPI IsBadCodePtr( FARPROC ptr )
 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
 {
     if (!str) return TRUE;
-    
+
     __TRY
     {
         volatile const char *p = str;
         while (p != str + max) if (!*p++) break;
     }
-    __EXCEPT_PAGE_FAULT
+    __EXCEPT( badptr_handler )
     {
         TRACE_(seh)("%p caused page fault during read\n", str);
         return TRUE;
@@ -226,13 +243,13 @@ BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
 {
     if (!str) return TRUE;
-    
+
     __TRY
     {
         volatile const WCHAR *p = str;
         while (p != str + max) if (!*p++) break;
     }
-    __EXCEPT_PAGE_FAULT
+    __EXCEPT( badptr_handler )
     {
         TRACE_(seh)("%p caused page fault during read\n", str);
         return TRUE;




More information about the wine-cvs mailing list