[PATCH v3 0/1] MR10068: msvcrt: Create copy of C++ exception object in std::rethrow_exception()
Fixes: https://bugs.winehq.org/show_bug.cgi?id=59329 Resolves whole lot of foobar2000 crashes after media indexing or playback errors (verified). Passes various C++ exception torture tests I quickly wrote. Notes about alloca() use- Size of C++ object is used, one that already existed elsewhere on stack, so it should not be an issue. MS runtime appears to do the same - copy the exception object on stack before rethrowing. -- v3: msvcrt: Create copy of C++ exception object in std::rethrow_exception(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10068
From: Piotr Pawłowski <p@perkele.cc> --- dlls/msvcp90/exception.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/dlls/msvcp90/exception.c b/dlls/msvcp90/exception.c index ab8de5de782..1df0c3caf95 100644 --- a/dlls/msvcp90/exception.c +++ b/dlls/msvcp90/exception.c @@ -18,6 +18,7 @@ #include <errno.h> #include <stdarg.h> +#include <malloc.h> #define COBJMACROS @@ -1077,6 +1078,9 @@ typedef struct LONG *ref; /* not binary compatible with native */ } exception_ptr; +static inline void copy_exception( void *object, void **dest, UINT catch_flags, + const cxx_type_info *type, uintptr_t base ); + static void exception_ptr_rethrow(const exception_ptr *ep) { TRACE("(%p)\n", ep); @@ -1090,6 +1094,20 @@ static void exception_ptr_rethrow(const exception_ptr *ep) _CxxThrowException(&e, &exception_exception_type); return; } + if (ep->rec->ExceptionCode == CXX_EXCEPTION) { + void *e; + void *obj = (void*)ep->rec->ExceptionInformation[1]; + const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; + uintptr_t base = cxx_rva_base( et ); + const cxx_type_info_table *table = cxx_rva( et->type_info_table, base ); + const cxx_type_info *ti = cxx_rva( table->info[0], base ); + + e = alloca(ti->size); + + copy_exception(obj, (void**)e, 0, ti, base); + _CxxThrowException(e, et); + return; + } RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & ~EXCEPTION_UNWINDING, ep->rec->NumberParameters, ep->rec->ExceptionInformation); @@ -1138,10 +1156,6 @@ void __cdecl _Throw_C_error(int code) _CxxThrowException(&se, &system_error_exception_type); } -#endif - -#if _MSVCP_VER >= 140 -void** CDECL __current_exception(void); /* compute the this pointer for a base class of a given type */ static inline void *get_this_pointer( const this_ptr_offsets *off, void *object ) @@ -1219,6 +1233,10 @@ static inline void copy_exception( void *object, void **dest, UINT catch_flags, } } +#endif + +#if _MSVCP_VER >= 140 + int __cdecl __uncaught_exceptions(void) { return *__processing_throw(); @@ -1302,6 +1320,8 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) exception_ptr_rethrow(ep); } +void** CDECL __current_exception(void); + /********************************************************************* * ?__ExceptionPtrCurrentException@@YAXPAX@Z * ?__ExceptionPtrCurrentException@@YAXPEAX@Z -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10068
Done, thanks for looking into it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10068#note_129729
participants (2)
-
Piotr Pawłowski -
Piotr Pawłowski (@DEATH)