Kaydet (Commit) 8313116f authored tarafından Mike Kaganski's avatar Mike Kaganski Kaydeden (comit) Stephan Bergmann

Don't use internal __CxxDetectRethrow: it has side effects

Since the __CxxDetectRethrow may increment __ProcessingThrow, which then
must be decremented in __CxxUnregisterExceptionObject, and the latter does
many other funny things with exception handling CRT machinery, we cannot
use those internal functions (neither alone, nor together), or we end up
breaking runtime's expectations: the runtime code checks __ProcessingThrow
left and right, expecting its non-0 value to indicate "we are unwinding...
possibly called from a dtor()". In this case, e.g., std::current_exception
returns nullptr inside catch block.

This creates our own copy of __CxxDetectRethrow, which does not mangle the
global state, and just performs the same checks. This is a dirty hack, and
it relies on current layout of the exception description layout - so must
be synchronized in the event of changes!

Change-Id: I2c475fbc2468073b796c7e9d0f4dfcd315896489
Reviewed-on: https://gerrit.libreoffice.org/58730
Tested-by: Jenkins
Reviewed-by: 's avatarStephan Bergmann <sbergman@redhat.com>
üst 7cb07a7a
......@@ -23,16 +23,16 @@
#include <typeinfo.h>
#include <signal.h>
#include "rtl/alloc.h"
#include "rtl/strbuf.hxx"
#include "rtl/ustrbuf.hxx"
#include <rtl/alloc.h>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <osl/mutex.hxx>
#include "com/sun/star/uno/Any.hxx"
#include <com/sun/star/uno/Any.hxx>
#include <unordered_map>
#include "msci.hxx"
#include "except.hxx"
#include <except.hxx>
#pragma pack(push, 8)
......@@ -468,6 +468,60 @@ void msci_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs );
}
namespace
{
// This function does the same check as __CxxDetectRethrow from msvcrt (see its
// crt/src/vcruntime/mgdframe.cpp). But it does not alter the global state, i.e. it does not
// increment __ProcessingThrow, and so does not break following exception handling. We rely on the
// definition of EHExceptionRecord, PER_IS_MSVC_EH and PER_PTHROW, that are current as of msvcrt
// 2017 (14.14.26428).
bool __DetectRethrow(void* ppExcept)
{
struct EHExceptionRecord
{
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD* ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
struct EHParameters
{
DWORD magicNumber;
PVOID pExceptionObject;
PVOID pThrowInfo;
} params;
};
constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) {
constexpr DWORD EH_EXCEPTION_NUMBER = ('msc' | 0xE0000000); // The NT Exception # that msvcrt uses
constexpr DWORD EH_MAGIC_NUMBER1 = 0x19930520; // latest magic # in thrown object
constexpr DWORD EH_MAGIC_NUMBER2 = 0x19930521; // latest magic # in func info for exception specs
constexpr DWORD EH_MAGIC_NUMBER3 = 0x19930522; // latest magic #
constexpr DWORD EH_EXCEPTION_PARAMETERS = 3; // Number of parameters in exception record for x86
return p->ExceptionCode == EH_EXCEPTION_NUMBER
&& p->NumberParameters == EH_EXCEPTION_PARAMETERS
&& (p->params.magicNumber == EH_MAGIC_NUMBER1
|| p->params.magicNumber == EH_MAGIC_NUMBER2
|| p->params.magicNumber == EH_MAGIC_NUMBER3);
};
constexpr auto PER_PTHROW = [](EHExceptionRecord* p) {
return p->params.pThrowInfo;
};
EHExceptionRecord* pExcept;
if (!ppExcept)
return false;
pExcept = *(EHExceptionRecord**)ppExcept;
if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr)
{
return true;
}
return false;
}
}
int msci_filterCppException(
EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
......@@ -478,7 +532,7 @@ int msci_filterCppException(
if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
return EXCEPTION_CONTINUE_SEARCH;
bool rethrow = __CxxDetectRethrow( &pRecord );
const bool rethrow = __DetectRethrow(&pRecord);
assert(pRecord == pPointers->ExceptionRecord);
if (rethrow && pRecord == pPointers->ExceptionRecord)
......
......@@ -782,6 +782,61 @@ void mscx_raiseException(
RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 4, arFilterArgs);
}
namespace
{
// This function does the same check as __CxxDetectRethrow from msvcrt (see its
// crt/src/vcruntime/mgdframe.cpp). But it does not alter the global state, i.e. it does not
// increment __ProcessingThrow, and so does not break following exception handling. We rely on the
// definition of EHExceptionRecord, PER_IS_MSVC_EH and PER_PTHROW, that are current as of msvcrt
// 2017 (14.14.26428).
bool __DetectRethrow(void* ppExcept)
{
struct EHExceptionRecord
{
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD* ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
struct alignas(8) EHParameters
{
DWORD magicNumber;
PVOID pExceptionObject;
PVOID pThrowInfo;
PVOID pThrowImageBase;
} params;
};
constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) {
constexpr DWORD EH_EXCEPTION_NUMBER = ('msc' | 0xE0000000); // The NT Exception # that msvcrt uses
constexpr DWORD EH_MAGIC_NUMBER1 = 0x19930520; // latest magic # in thrown object
constexpr DWORD EH_MAGIC_NUMBER2 = 0x19930521; // latest magic # in func info for exception specs
constexpr DWORD EH_MAGIC_NUMBER3 = 0x19930522; // latest magic #
constexpr DWORD EH_EXCEPTION_PARAMETERS = 4; // Number of parameters in exception record for AMD64
return p->ExceptionCode == EH_EXCEPTION_NUMBER
&& p->NumberParameters == EH_EXCEPTION_PARAMETERS
&& (p->params.magicNumber == EH_MAGIC_NUMBER1
|| p->params.magicNumber == EH_MAGIC_NUMBER2
|| p->params.magicNumber == EH_MAGIC_NUMBER3);
};
constexpr auto PER_PTHROW = [](EHExceptionRecord* p) {
return p->params.pThrowInfo;
};
EHExceptionRecord* pExcept;
if (!ppExcept)
return false;
pExcept = *(EHExceptionRecord**)ppExcept;
if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr)
{
return true;
}
return false;
}
}
int mscx_filterCppException(
EXCEPTION_POINTERS * pPointers,
uno_Any * pUnoExc,
......@@ -796,7 +851,7 @@ int mscx_filterCppException(
if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_ExceptionCode)
return EXCEPTION_CONTINUE_SEARCH;
bool rethrow = __CxxDetectRethrow( &pRecord );
const bool rethrow = __DetectRethrow(&pRecord);
assert(pRecord == pPointers->ExceptionRecord);
if (rethrow && pRecord == pPointers->ExceptionRecord)
......
......@@ -47,11 +47,5 @@ void mscx_raiseException(
}
//TODO: Work around missing __CxxDetectRethrow in clang-cl for now (predefined
// in cl, <www.geoffchappell.com/studies/msvc/language/predefined/index.html>):
#if defined __clang__
extern "C" int __cdecl __CxxDetectRethrow(void *);
#endif
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment