Signed-off-by: Daniel Lehman dlehman25@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;