summaryrefslogtreecommitdiffstats
path: root/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx')
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx57
1 files changed, 56 insertions, 1 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
index 86753103a751..c03716151bbc 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
@@ -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)