[PATCH v2] vcruntime140_1: Terminate on noexcept function trying to propagate exception.

Daniel Lehman dlehman25 at gmail.com
Wed Sep 30 21:14:56 CDT 2020


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>

---
v2: handle nested case

this should print 0x42:
wine64 tosend.exe

these should terminate():
wine64 tosend.exe 1
wine64 tosend.exe 1 1
wine64 tosend.exe 1 1 1

/* cl /EHsc /MD noexcept.cpp */

void do_throw(void) { throw int(0x42); }

void crash_without_tries(void) noexcept { do_throw(); }

void crash_with_tries(void) noexcept
{
    try { do_throw(); } catch (float e) { /* bogus */ }
}

void crash_nested(void) noexcept
{
    try {
         try { throw 1; }
         catch (int e) { throw; }
    }
    catch (float f) {  /* bogus */ }
}

void works(void) noexcept
{
    try { do_throw(); } catch (int e) { printf("0x%x\n", e); }
}

void works_nested(void) noexcept
{
    try {
         try { throw 1; }
         catch (int e) { throw; }
    }
    catch (...) {
    }
}

void works_nested2(void) noexcept
{
    try {
        try {
             try { throw 1; }
             catch (int e) { throw; }
        }
        catch (int e) { throw; }
    }
    catch (...) {
    }
}

int main(int argc, char **argv)
{
    try
    {
        switch (argc)
        {
            case 4: crash_nested(); break;
            case 3: crash_without_tries(); break;
            case 2: crash_with_tries(); break;
            default:
                works();
                works_nested();
                works_nested2();
                break;
        }
    }
    catch (...)
    {
        printf("%s: should not be printed\n", __FUNCTION__);
    }
    return 0;
}
---
 dlls/vcruntime140_1/except_x86_64.c | 90 ++++++++++++++++-------------
 1 file changed, 49 insertions(+), 41 deletions(-)

diff --git a/dlls/vcruntime140_1/except_x86_64.c b/dlls/vcruntime140_1/except_x86_64.c
index f66ae43721f..341f26a20c2 100644
--- a/dlls/vcruntime140_1/except_x86_64.c
+++ b/dlls/vcruntime140_1/except_x86_64.c
@@ -683,56 +683,64 @@ static DWORD cxx_frame_handler4(EXCEPTION_RECORD *rec, ULONG64 frame,
         cxx_local_unwind4(orig_frame, dispatch, descr, trylevel, last_level);
         return ExceptionContinueSearch;
     }
-    if (!descr->tryblock_map) return ExceptionContinueSearch;
-
-    if (rec->ExceptionCode == CXX_EXCEPTION)
+    if (descr->tryblock_map)
     {
-        if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
-        {
-            TRACE("rethrow detected.\n");
-            *rec = *(EXCEPTION_RECORD*)*__current_exception();
-        }
-
-        exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
-
-        if (TRACE_ON(seh))
+        if (rec->ExceptionCode == CXX_EXCEPTION)
         {
-            TRACE("handling C++ exception rec %p frame %lx descr %p\n", rec, frame,  descr);
-            dump_exception_type(exc_type, rec->ExceptionInformation[3]);
-        }
-    }
-    else
-    {
-        _se_translator_function se_translator = get_se_translator();
-
-        exc_type = NULL;
-        TRACE("handling C exception code %x rec %p frame %lx descr %p\n",
-                rec->ExceptionCode, rec, frame, descr);
+            if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
+            {
+                TRACE("rethrow detected.\n");
+                *rec = *(EXCEPTION_RECORD*)*__current_exception();
+            }
 
-        if (se_translator) {
-            EXCEPTION_POINTERS except_ptrs;
-            se_translator_ctx ctx;
+            exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
 
-            ctx.dest_frame = frame;
-            ctx.orig_frame = orig_frame;
-            ctx.seh_rec    = rec;
-            ctx.dispatch   = dispatch;
-            ctx.descr      = descr;
-            ctx.trylevel   = trylevel;
-            __TRY
+            if (TRACE_ON(seh))
             {
-                except_ptrs.ExceptionRecord = rec;
-                except_ptrs.ContextRecord = context;
-                se_translator(rec->ExceptionCode, &except_ptrs);
+                TRACE("handling C++ exception rec %p frame %lx descr %p\n", rec, frame,  descr);
+                dump_exception_type(exc_type, rec->ExceptionInformation[3]);
             }
-            __EXCEPT_CTX(se_translation_filter, &ctx)
-            {
+        }
+        else
+        {
+            _se_translator_function se_translator = get_se_translator();
+
+            exc_type = NULL;
+            TRACE("handling C exception code %x rec %p frame %lx descr %p\n",
+                    rec->ExceptionCode, rec, frame, descr);
+
+            if (se_translator) {
+                EXCEPTION_POINTERS except_ptrs;
+                se_translator_ctx ctx;
+
+                ctx.dest_frame = frame;
+                ctx.orig_frame = orig_frame;
+                ctx.seh_rec    = rec;
+                ctx.dispatch   = dispatch;
+                ctx.descr      = descr;
+                ctx.trylevel   = trylevel;
+                __TRY
+                {
+                    except_ptrs.ExceptionRecord = rec;
+                    except_ptrs.ContextRecord = context;
+                    se_translator(rec->ExceptionCode, &except_ptrs);
+                }
+                __EXCEPT_CTX(se_translation_filter, &ctx)
+                {
+                }
+                __ENDTRY
             }
-            __ENDTRY
         }
+
+        find_catch_block4(rec, context, NULL, frame, dispatch, descr, exc_type, orig_frame, trylevel);
     }
 
-    find_catch_block4(rec, context, NULL, frame, dispatch, descr, exc_type, orig_frame, trylevel);
+    if ((descr->header & FUNC_DESCR_NO_EXCEPT) &&
+        !(descr->header & FUNC_DESCR_IS_CATCH))
+    {
+        ERR("noexcept function propagating exception\n");
+        terminate();
+    }
     return ExceptionContinueSearch;
 }
 
@@ -759,7 +767,7 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
         return ExceptionContinueSearch;  /* handle only c++ exceptions */
 
     if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_UNWIND_MAP |
-                FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS))
+                FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS | FUNC_DESCR_NO_EXCEPT))
     {
         FIXME("unsupported flags: %x\n", descr.header);
         return ExceptionContinueSearch;
-- 
2.25.1




More information about the wine-devel mailing list