msvcrt: Destroy exception object when frame storing it is unwound.
Thrown object was incorrectly freed in following situation: try { throw obj; } catch(object &obj) { try { throw 1; } catch(...) {} //use object here } Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2d4b48a58d
commit
f085be3028
|
@ -131,6 +131,7 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame
|
||||||
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
|
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
|
||||||
const cxx_function_descr *descr,
|
const cxx_function_descr *descr,
|
||||||
EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel );
|
EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel );
|
||||||
|
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void*);
|
||||||
|
|
||||||
/* call a function with a given ebp */
|
/* call a function with a given ebp */
|
||||||
static inline void *call_ebp_func( void *func, void *ebp )
|
static inline void *call_ebp_func( void *func, void *ebp )
|
||||||
|
@ -361,9 +362,18 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
|
||||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||||
{
|
{
|
||||||
struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
|
struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
|
||||||
|
PEXCEPTION_RECORD prev_rec = nested_frame->rec;
|
||||||
|
|
||||||
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
|
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
|
||||||
{
|
{
|
||||||
|
if (prev_rec->ExceptionCode == CXX_EXCEPTION)
|
||||||
|
{
|
||||||
|
void *object = (void*)prev_rec->ExceptionInformation[1];
|
||||||
|
cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2];
|
||||||
|
if (info && info->destructor && _IsExceptionObjectToBeDestroyed(object))
|
||||||
|
call_dtor( info->destructor, object);
|
||||||
|
}
|
||||||
|
|
||||||
msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
|
msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
|
||||||
return ExceptionContinueSearch;
|
return ExceptionContinueSearch;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +382,6 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
|
||||||
|
|
||||||
if(rec->ExceptionCode == CXX_EXCEPTION)
|
if(rec->ExceptionCode == CXX_EXCEPTION)
|
||||||
{
|
{
|
||||||
PEXCEPTION_RECORD prev_rec = nested_frame->rec;
|
|
||||||
if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) ||
|
if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) ||
|
||||||
(prev_rec->ExceptionCode == CXX_EXCEPTION &&
|
(prev_rec->ExceptionCode == CXX_EXCEPTION &&
|
||||||
rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] &&
|
rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] &&
|
||||||
|
@ -388,22 +397,6 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
|
||||||
rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
|
rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (nested_frame->prev_rec && nested_frame->prev_rec->ExceptionCode == CXX_EXCEPTION &&
|
|
||||||
nested_frame->prev_rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] &&
|
|
||||||
nested_frame->prev_rec->ExceptionInformation[2] == prev_rec->ExceptionInformation[2])
|
|
||||||
{
|
|
||||||
TRACE("detect threw new exception in catch block - not owning old(obj: %lx type: %lx)\n",
|
|
||||||
prev_rec->ExceptionInformation[1], prev_rec->ExceptionInformation[2]);
|
|
||||||
}
|
|
||||||
else if (prev_rec->ExceptionCode == CXX_EXCEPTION) {
|
|
||||||
/* new exception in exception handler, destroy old */
|
|
||||||
void *object = (void*)prev_rec->ExceptionInformation[1];
|
|
||||||
cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2];
|
|
||||||
TRACE("detect threw new exception in catch block - destroy old(obj: %p type: %p)\n",
|
|
||||||
object, info);
|
|
||||||
if(info && info->destructor)
|
|
||||||
call_dtor( info->destructor, object );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE("detect threw new exception in catch block\n");
|
TRACE("detect threw new exception in catch block\n");
|
||||||
|
|
Loading…
Reference in New Issue