Sebastian Lackner : ntdll: Avoid recursive exception handler calls when handling guard pages.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Oct 13 11:18:10 CDT 2014


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

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Wed Oct  8 21:11:55 2014 +0200

ntdll: Avoid recursive exception handler calls when handling guard pages.

The ATL check leads to problems when a page is protected with guard page protection.
raise_segv_exception is called with EXCEPTION_EXECUTE_FAULT. The ATL check tries to
read the memory, and triggers another exception handler. This time the virtual_handle_fault
check is executed, and removes the guard page protection. Afterwards, when the ATL
check returns, the exception is _not_ catched by virtual_handle_fault, but instead
passed to the application.

---

 dlls/kernel32/tests/virtual.c |  2 --
 dlls/ntdll/signal_i386.c      | 10 ++++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 501934d..4d8277d 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -1818,7 +1818,6 @@ static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR
     if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
     {
 
-        todo_wine
         ok( rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ||
             broken(!(flags & MEM_EXECUTE_OPTION_DISABLE) && rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT), /* Windows 2000 */
             "ExceptionInformation[0] is %d instead of %d\n", (DWORD)rec->ExceptionInformation[0], EXCEPTION_EXECUTE_FAULT );
@@ -1971,7 +1970,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
     if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
         ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
     else
-        todo_wine
         ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
 
     ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 12aa5a4..b9b45a8 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1821,17 +1821,19 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
     case EXCEPTION_ACCESS_VIOLATION:
         if (rec->NumberParameters == 2)
         {
-            if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT && check_atl_thunk( rec, context ))
-                goto done;
             if (rec->ExceptionInformation[1] == 0xffffffff && check_invalid_gs( context ))
                 goto done;
             if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
                                                              rec->ExceptionInformation[0] )))
                 goto done;
-            /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
-            if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
+            if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
+                rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
             {
                 ULONG flags;
+                if (check_atl_thunk( rec, context ))
+                    goto done;
+
+                /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
                 NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
                                            &flags, sizeof(flags), NULL );
                 if (!(flags & MEM_EXECUTE_OPTION_DISABLE))




More information about the wine-cvs mailing list