Piotr Caban : msvcrt: Don' t call unwind handlers when unwinding nested catch blocks.

Alexandre Julliard julliard at winehq.org
Wed Apr 12 15:02:33 CDT 2017


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Apr 12 15:08:39 2017 +0200

msvcrt: Don't call unwind handlers when unwinding nested catch blocks.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/except_x86_64.c | 74 ++++++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 35 deletions(-)

diff --git a/dlls/msvcrt/except_x86_64.c b/dlls/msvcrt/except_x86_64.c
index 80780ae..d299608 100644
--- a/dlls/msvcrt/except_x86_64.c
+++ b/dlls/msvcrt/except_x86_64.c
@@ -334,7 +334,7 @@ static inline void* WINAPI call_catch_block(EXCEPTION_RECORD *rec)
 static inline void find_catch_block(EXCEPTION_RECORD *rec, ULONG64 frame,
                                     DISPATCHER_CONTEXT *dispatch,
                                     const cxx_function_descr *descr,
-                                    cxx_exception_type *info)
+                                    cxx_exception_type *info, ULONG64 orig_frame)
 {
     ULONG64 exc_base = (rec->NumberParameters == 4 ? rec->ExceptionInformation[3] : 0);
     int trylevel = ip_to_state(rva_to_ptr(descr->ipmap, dispatch->ImageBase),
@@ -343,38 +343,8 @@ static inline void find_catch_block(EXCEPTION_RECORD *rec, ULONG64 frame,
     EXCEPTION_RECORD catch_record;
     CONTEXT context;
     UINT i, j;
-    ULONG64 orig_frame = frame, throw_base;
-    DWORD throw_func_off;
-    void *throw_func;
     INT *unwind_help;
 
-    /* update orig_frame if it's a nested exception */
-    throw_func_off = RtlLookupFunctionEntry(dispatch->ControlPc, &throw_base, NULL)->BeginAddress;
-    throw_func = rva_to_ptr(throw_func_off, throw_base);
-    TRACE("reconstructed handler pointer: %p\n", throw_func);
-    for (i=descr->tryblock_count; i>0; i--)
-    {
-        const tryblock_info *tryblock = rva_to_ptr(descr->tryblock, dispatch->ImageBase);
-        tryblock = &tryblock[i-1];
-
-        if (trylevel>tryblock->end_level && trylevel<=tryblock->catch_level)
-        {
-            for (j=0; j<tryblock->catchblock_count; j++)
-            {
-                /* TODO: is it possible to have the same handler for multiple catch blocks? */
-                const catchblock_info *catchblock = rva_to_ptr(tryblock->catchblock, dispatch->ImageBase);
-                catchblock = &catchblock[j];
-
-                if (rva_to_ptr(catchblock->handler, dispatch->ImageBase) == throw_func)
-                {
-                    TRACE("nested exception detected\n");
-                    orig_frame = *(ULONG64*)rva_to_ptr(catchblock->frame, frame);
-                    TRACE("setting orig_frame to %lx\n", orig_frame);
-                }
-            }
-        }
-    }
-
     for (i=descr->tryblock_count; i>0; i--)
     {
         in_catch = rva_to_ptr(descr->tryblock, dispatch->ImageBase);
@@ -457,7 +427,14 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
                                CONTEXT *context, DISPATCHER_CONTEXT *dispatch,
                                const cxx_function_descr *descr)
 {
+    int trylevel = ip_to_state(rva_to_ptr(descr->ipmap, dispatch->ImageBase),
+            descr->ipmap_count, dispatch->ControlPc-dispatch->ImageBase);
     cxx_exception_type *exc_type;
+    ULONG64 orig_frame = frame;
+    ULONG64 throw_base;
+    DWORD throw_func_off;
+    void *throw_func;
+    UINT i, j;
 
     if (descr->magic<CXX_FRAME_MAGIC_VC6 || descr->magic>CXX_FRAME_MAGIC_VC8)
     {
@@ -465,6 +442,32 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
         return ExceptionContinueSearch;
     }
 
+    /* update orig_frame if it's a nested exception */
+    throw_func_off = RtlLookupFunctionEntry(dispatch->ControlPc, &throw_base, NULL)->BeginAddress;
+    throw_func = rva_to_ptr(throw_func_off, throw_base);
+    TRACE("reconstructed handler pointer: %p\n", throw_func);
+    for (i=descr->tryblock_count; i>0; i--)
+    {
+        const tryblock_info *tryblock = rva_to_ptr(descr->tryblock, dispatch->ImageBase);
+        tryblock = &tryblock[i-1];
+
+        if (trylevel>tryblock->end_level && trylevel<=tryblock->catch_level)
+        {
+            for (j=0; j<tryblock->catchblock_count; j++)
+            {
+                const catchblock_info *catchblock = rva_to_ptr(tryblock->catchblock, dispatch->ImageBase);
+                catchblock = &catchblock[j];
+
+                if (rva_to_ptr(catchblock->handler, dispatch->ImageBase) == throw_func)
+                {
+                    TRACE("nested exception detected\n");
+                    orig_frame = *(ULONG64*)rva_to_ptr(catchblock->frame, frame);
+                    TRACE("setting orig_frame to %lx\n", orig_frame);
+                }
+            }
+        }
+    }
+
     if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND))
     {
         if (rec->ExceptionCode==STATUS_UNWIND_CONSOLIDATE && rec->NumberParameters==6 &&
@@ -476,13 +479,13 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
 
             if (rec->ExceptionFlags & EH_TARGET_UNWIND)
             {
-                ULONG64 orig_frame = rec->ExceptionInformation[1];
                 const cxx_function_descr *orig_descr = (void*)rec->ExceptionInformation[2];
                 int end_level = rec->ExceptionInformation[3];
+                orig_frame = rec->ExceptionInformation[1];
 
                 cxx_local_unwind(orig_frame, dispatch, orig_descr, end_level);
             }
-            else
+            else if(frame == orig_frame)
                 cxx_local_unwind(frame, dispatch, descr, -1);
 
             /* FIXME: we should only unregister frames registered by call_catch_block here */
@@ -499,7 +502,8 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
             return ExceptionContinueSearch;
         }
 
-        cxx_local_unwind(frame, dispatch, descr, -1);
+        if (frame == orig_frame)
+            cxx_local_unwind(frame, dispatch, descr, -1);
         return ExceptionContinueSearch;
     }
     if (!descr->tryblock_count) return ExceptionContinueSearch;
@@ -545,7 +549,7 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
         }
     }
 
-    find_catch_block(rec, frame, dispatch, descr, exc_type);
+    find_catch_block(rec, frame, dispatch, descr, exc_type, orig_frame);
     return ExceptionContinueSearch;
 }
 




More information about the wine-cvs mailing list