From dfa0a5bfdbf45b4d49f032db7b9aa8a5b25669e1 Mon Sep 17 00:00:00 2001 From: Mikhail Labiuk Date: Tue, 13 Feb 2018 15:02:12 +0300 Subject: [PATCH 1/5] Prevent memory allocation in signal handler If the signal occurs when heap being inconsistent we should not use heap. We should call signal-safe functions only from signal handler. fix https://github.com/dotnet/coreclr/issues/16338 --- src/pal/src/exception/seh-unwind.cpp | 6 ++++-- src/pal/src/exception/signal.cpp | 2 +- src/pal/src/include/pal/seh.hpp | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index b15ac34c24b7..63cb880e0776 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -372,12 +372,14 @@ static volatile size_t s_allocatedContextsBitmap = 0; Parameters: exceptionRecord - output pointer to the allocated exception record contextRecord - output pointer to the allocated context record + allocationProhibited - input flag to avoid memory allocation in critical situations --*/ VOID -AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord) +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord, BOOL allocationProhibited) { ExceptionRecords* records; - if (posix_memalign((void**)&records, alignof(ExceptionRecords), sizeof(ExceptionRecords)) != 0) + if (allocationProhibited || + (posix_memalign((void**)&records, alignof(ExceptionRecords), sizeof(ExceptionRecords)) != 0) ) { size_t bitmap; size_t newBitmap; diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 012e32033846..d8891f8191f8 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -833,7 +833,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext ucontext = (native_context_t *)sigcontext; g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); - AllocateExceptionRecords(&exceptionRecord, &contextRecord); + AllocateExceptionRecords(&exceptionRecord, &contextRecord, true); exceptionRecord->ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); exceptionRecord->ExceptionFlags = EXCEPTION_IS_SIGNAL; diff --git a/src/pal/src/include/pal/seh.hpp b/src/pal/src/include/pal/seh.hpp index 3ac93d655a15..5edc2142a5ac 100644 --- a/src/pal/src/include/pal/seh.hpp +++ b/src/pal/src/include/pal/seh.hpp @@ -84,9 +84,10 @@ SEHProcessException(PAL_SEHException* exception); Parameters: exceptionRecord - output pointer to the allocated Windows exception record contextRecord - output pointer to the allocated Windows context record + allocationProhibited - input flag to avoid memory allocation in critical situations --*/ VOID -AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord); +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord, BOOL allocationProhibited=false); #if !HAVE_MACH_EXCEPTIONS // TODO: Implement for Mach exceptions. Not in CoreCLR surface area. From ee2648882aa0d010ebac294308a802a7b97e2db7 Mon Sep 17 00:00:00 2001 From: Mikhail Labiuk Date: Mon, 19 Feb 2018 19:08:50 +0300 Subject: [PATCH 2/5] Revert "Prevent memory allocation in signal handler" This reverts commit fa6087f0c2856215e7141259b56e75b46746f74d. --- src/pal/src/exception/seh-unwind.cpp | 6 ++---- src/pal/src/exception/signal.cpp | 2 +- src/pal/src/include/pal/seh.hpp | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index 63cb880e0776..b15ac34c24b7 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -372,14 +372,12 @@ static volatile size_t s_allocatedContextsBitmap = 0; Parameters: exceptionRecord - output pointer to the allocated exception record contextRecord - output pointer to the allocated context record - allocationProhibited - input flag to avoid memory allocation in critical situations --*/ VOID -AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord, BOOL allocationProhibited) +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord) { ExceptionRecords* records; - if (allocationProhibited || - (posix_memalign((void**)&records, alignof(ExceptionRecords), sizeof(ExceptionRecords)) != 0) ) + if (posix_memalign((void**)&records, alignof(ExceptionRecords), sizeof(ExceptionRecords)) != 0) { size_t bitmap; size_t newBitmap; diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index d8891f8191f8..012e32033846 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -833,7 +833,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext ucontext = (native_context_t *)sigcontext; g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); - AllocateExceptionRecords(&exceptionRecord, &contextRecord, true); + AllocateExceptionRecords(&exceptionRecord, &contextRecord); exceptionRecord->ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); exceptionRecord->ExceptionFlags = EXCEPTION_IS_SIGNAL; diff --git a/src/pal/src/include/pal/seh.hpp b/src/pal/src/include/pal/seh.hpp index 5edc2142a5ac..3ac93d655a15 100644 --- a/src/pal/src/include/pal/seh.hpp +++ b/src/pal/src/include/pal/seh.hpp @@ -84,10 +84,9 @@ SEHProcessException(PAL_SEHException* exception); Parameters: exceptionRecord - output pointer to the allocated Windows exception record contextRecord - output pointer to the allocated Windows context record - allocationProhibited - input flag to avoid memory allocation in critical situations --*/ VOID -AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord, BOOL allocationProhibited=false); +AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord); #if !HAVE_MACH_EXCEPTIONS // TODO: Implement for Mach exceptions. Not in CoreCLR surface area. From f8dafbb84eda8857b925a6d1cf3f8085f59ff56e Mon Sep 17 00:00:00 2001 From: Mikhail Labiuk Date: Mon, 19 Feb 2018 18:56:15 +0300 Subject: [PATCH 3/5] Do not allocate exception for signal from non managed code If the signal occurs in not managed code we cannot use heap. We should call signal-safe functions only from signal handler. Create exception object on stack for checking source of signal. If signal is from managed code we can use memory allocation to create persistent exception on heap as copy of volatile exception on stack. If signal from unmanaged code we do nothing and call base signal handler. fix https://github.com/dotnet/coreclr/issues/16338 --- src/pal/inc/pal.h | 5 ++++- src/pal/src/exception/seh.cpp | 23 +++++++++++++++++++++++ src/pal/src/exception/signal.cpp | 30 +++++++++++++++--------------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index aff205d7dd82..66232d7c0999 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -3762,6 +3762,8 @@ PAL_BindResources(IN LPCSTR lpDomain); #define EXCEPTION_IS_SIGNAL 0x100 +#define EXCEPTION_ON_STACK 0x400 + #define EXCEPTION_MAXIMUM_PARAMETERS 15 // Index in the ExceptionInformation array where we will keep the reference @@ -5683,7 +5685,8 @@ struct PAL_SEHException void FreeRecords() { - if (ExceptionPointers.ExceptionRecord != NULL) + if (ExceptionPointers.ExceptionRecord != NULL && + ! (ExceptionPointers.ExceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) ) { PAL_FreeExceptionRecords(ExceptionPointers.ExceptionRecord, ExceptionPointers.ContextRecord); ExceptionPointers.ExceptionRecord = NULL; diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 9f5f074f1820..61610864f64a 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -202,6 +202,23 @@ void ThrowExceptionHelper(PAL_SEHException* ex) throw std::move(*ex); } +static PAL_SEHException copyPAL_SEHException(PAL_SEHException* src) +{ + CONTEXT* contextRecord = src->GetContextRecord(); + EXCEPTION_RECORD* exceptionRecord = src->GetExceptionRecord(); + + CONTEXT* contextRecordCopy; + EXCEPTION_RECORD* exceptionRecordCopy; + AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); + + *exceptionRecordCopy = *exceptionRecord; + exceptionRecordCopy->ExceptionFlags &= ~EXCEPTION_ON_STACK; + *contextRecordCopy = *contextRecord; + return PAL_SEHException(exceptionRecordCopy, contextRecordCopy); +} + + + /*++ Function: SEHProcessException @@ -249,6 +266,9 @@ SEHProcessException(PAL_SEHException* exception) PROCAbort(); } } + + if(exceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) + *exception = copyPAL_SEHException(exception); if (g_hardwareExceptionHandler(exception)) { @@ -262,6 +282,9 @@ SEHProcessException(PAL_SEHException* exception) if (CatchHardwareExceptionHolder::IsEnabled()) { + if(exceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) + *exception = copyPAL_SEHException(exception); + PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception); } } diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 012e32033846..6ceef62cd9a2 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -826,32 +826,32 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext { sigset_t signal_set; CONTEXT signalContextRecord; - CONTEXT *contextRecord; - EXCEPTION_RECORD *exceptionRecord; + CONTEXT contextRecord; + EXCEPTION_RECORD exceptionRecord; native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); - AllocateExceptionRecords(&exceptionRecord, &contextRecord); + //AllocateExceptionRecords(&exceptionRecord, &contextRecord); - exceptionRecord->ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); - exceptionRecord->ExceptionFlags = EXCEPTION_IS_SIGNAL; - exceptionRecord->ExceptionRecord = NULL; - exceptionRecord->ExceptionAddress = GetNativeContextPC(ucontext); - exceptionRecord->NumberParameters = numParams; + exceptionRecord.ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); + exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL | EXCEPTION_ON_STACK; + exceptionRecord.ExceptionRecord = NULL; + exceptionRecord.ExceptionAddress = GetNativeContextPC(ucontext); + exceptionRecord.NumberParameters = numParams; va_list params; va_start(params, numParams); for (int i = 0; i < numParams; i++) { - exceptionRecord->ExceptionInformation[i] = va_arg(params, size_t); + exceptionRecord.ExceptionInformation[i] = va_arg(params, size_t); } // Pre-populate context with data from current frame, because ucontext doesn't have some data (e.g. SS register) // which is required for restoring context - RtlCaptureContext(contextRecord); + RtlCaptureContext(&contextRecord); ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT; @@ -862,7 +862,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext // Fill context record with required information. from pal.h: // On non-Win32 platforms, the CONTEXT pointer in the // PEXCEPTION_POINTERS will contain at least the CONTEXT_CONTROL registers. - CONTEXTFromNativeContext(ucontext, contextRecord, contextFlags); + CONTEXTFromNativeContext(ucontext, &contextRecord, contextFlags); /* Unmask signal so we can receive it again */ sigemptyset(&signal_set); @@ -873,17 +873,17 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet); } - contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + contextRecord.ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; - memcpy_s(&signalContextRecord, sizeof(CONTEXT), contextRecord, sizeof(CONTEXT)); + memcpy_s(&signalContextRecord, sizeof(CONTEXT), &contextRecord, sizeof(CONTEXT)); // The exception object takes ownership of the exceptionRecord and contextRecord - PAL_SEHException exception(exceptionRecord, contextRecord); + PAL_SEHException exception(&exceptionRecord, &contextRecord); if (SEHProcessException(&exception)) { // Exception handling may have modified the context, so update it. - CONTEXTToNativeContext(contextRecord, ucontext); + CONTEXTToNativeContext(&contextRecord, ucontext); return true; } From e7bf54ed933ff72dd715c3c79689555221fcfea4 Mon Sep 17 00:00:00 2001 From: Mikhail Labiuk Date: Tue, 20 Feb 2018 14:26:35 +0300 Subject: [PATCH 4/5] Move exception allocation to PAL_SEHException PAL_SEHException::EnsureExceptionRecordsOnHeap() moves exception record to heap if needed. fix https://github.com/dotnet/coreclr/issues/16338 --- src/pal/inc/pal.h | 35 +++++++++++++++++++++++++++----- src/pal/src/exception/seh.cpp | 25 ++--------------------- src/pal/src/exception/signal.cpp | 6 ++---- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 66232d7c0999..fea1a9332c3a 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -3762,8 +3762,6 @@ PAL_BindResources(IN LPCSTR lpDomain); #define EXCEPTION_IS_SIGNAL 0x100 -#define EXCEPTION_ON_STACK 0x400 - #define EXCEPTION_MAXIMUM_PARAMETERS 15 // Index in the ExceptionInformation array where we will keep the reference @@ -5665,6 +5663,11 @@ PAL_FreeExceptionRecords( IN EXCEPTION_RECORD *exceptionRecord, IN CONTEXT *contextRecord); +VOID +AllocateExceptionRecords( + EXCEPTION_RECORD** exceptionRecord, + CONTEXT** contextRecord); + #define EXCEPTION_CONTINUE_SEARCH 0 #define EXCEPTION_EXECUTE_HANDLER 1 #define EXCEPTION_CONTINUE_EXECUTION -1 @@ -5679,14 +5682,14 @@ struct PAL_SEHException ExceptionPointers.ExceptionRecord = ex.ExceptionPointers.ExceptionRecord; ExceptionPointers.ContextRecord = ex.ExceptionPointers.ContextRecord; TargetFrameSp = ex.TargetFrameSp; + RecordsOnStack = ex.RecordsOnStack; ex.Clear(); } void FreeRecords() { - if (ExceptionPointers.ExceptionRecord != NULL && - ! (ExceptionPointers.ExceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) ) + if (ExceptionPointers.ExceptionRecord != NULL && !RecordsOnStack ) { PAL_FreeExceptionRecords(ExceptionPointers.ExceptionRecord, ExceptionPointers.ContextRecord); ExceptionPointers.ExceptionRecord = NULL; @@ -5698,12 +5701,14 @@ struct PAL_SEHException EXCEPTION_POINTERS ExceptionPointers; // Target frame stack pointer set before the 2nd pass. SIZE_T TargetFrameSp; + bool RecordsOnStack; - PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord) + PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord, bool onStack = false) { ExceptionPointers.ExceptionRecord = pExceptionRecord; ExceptionPointers.ContextRecord = pContextRecord; TargetFrameSp = NoTargetFrameSp; + RecordsOnStack = onStack; } PAL_SEHException() @@ -5739,6 +5744,26 @@ struct PAL_SEHException ExceptionPointers.ExceptionRecord = NULL; ExceptionPointers.ContextRecord = NULL; TargetFrameSp = NoTargetFrameSp; + RecordsOnStack = false; + } + + void EnsureExceptionRecordsOnHeap() + { + if( !RecordsOnStack || ExceptionPointers.ExceptionRecord == NULL) + { + return; + } + + CONTEXT* contextRecordCopy; + EXCEPTION_RECORD* exceptionRecordCopy; + AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); + + *exceptionRecordCopy = *ExceptionPointers.ExceptionRecord; + ExceptionPointers.ExceptionRecord = exceptionRecordCopy; + *contextRecordCopy = *ExceptionPointers.ContextRecord; + ExceptionPointers.ContextRecord = contextRecordCopy; + + RecordsOnStack = false; } CONTEXT* GetContextRecord() diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 61610864f64a..876e53ea6e41 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -202,23 +202,6 @@ void ThrowExceptionHelper(PAL_SEHException* ex) throw std::move(*ex); } -static PAL_SEHException copyPAL_SEHException(PAL_SEHException* src) -{ - CONTEXT* contextRecord = src->GetContextRecord(); - EXCEPTION_RECORD* exceptionRecord = src->GetExceptionRecord(); - - CONTEXT* contextRecordCopy; - EXCEPTION_RECORD* exceptionRecordCopy; - AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); - - *exceptionRecordCopy = *exceptionRecord; - exceptionRecordCopy->ExceptionFlags &= ~EXCEPTION_ON_STACK; - *contextRecordCopy = *contextRecord; - return PAL_SEHException(exceptionRecordCopy, contextRecordCopy); -} - - - /*++ Function: SEHProcessException @@ -266,10 +249,8 @@ SEHProcessException(PAL_SEHException* exception) PROCAbort(); } } - - if(exceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) - *exception = copyPAL_SEHException(exception); + exception->EnsureExceptionRecordsOnHeap(); if (g_hardwareExceptionHandler(exception)) { // The exception happened in managed code and the execution should continue. @@ -282,9 +263,7 @@ SEHProcessException(PAL_SEHException* exception) if (CatchHardwareExceptionHolder::IsEnabled()) { - if(exceptionRecord->ExceptionFlags | EXCEPTION_ON_STACK) - *exception = copyPAL_SEHException(exception); - + exception->EnsureExceptionRecordsOnHeap(); PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception); } } diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 6ceef62cd9a2..3c2319f19dd8 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -833,10 +833,8 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext ucontext = (native_context_t *)sigcontext; g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); - //AllocateExceptionRecords(&exceptionRecord, &contextRecord); - exceptionRecord.ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext); - exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL | EXCEPTION_ON_STACK; + exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; exceptionRecord.ExceptionRecord = NULL; exceptionRecord.ExceptionAddress = GetNativeContextPC(ucontext); exceptionRecord.NumberParameters = numParams; @@ -878,7 +876,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext memcpy_s(&signalContextRecord, sizeof(CONTEXT), &contextRecord, sizeof(CONTEXT)); // The exception object takes ownership of the exceptionRecord and contextRecord - PAL_SEHException exception(&exceptionRecord, &contextRecord); + PAL_SEHException exception(&exceptionRecord, &contextRecord, true); if (SEHProcessException(&exception)) { From 5966e0ed01f1b4f10f9aca3add24545c591b75d0 Mon Sep 17 00:00:00 2001 From: Mikhail Labiuk Date: Tue, 20 Feb 2018 16:59:27 +0300 Subject: [PATCH 5/5] Remove exception records allocation from pal.h --- src/pal/inc/pal.h | 24 ----------------------- src/pal/src/exception/seh.cpp | 36 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index fea1a9332c3a..f89cb4fa121c 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -5663,11 +5663,6 @@ PAL_FreeExceptionRecords( IN EXCEPTION_RECORD *exceptionRecord, IN CONTEXT *contextRecord); -VOID -AllocateExceptionRecords( - EXCEPTION_RECORD** exceptionRecord, - CONTEXT** contextRecord); - #define EXCEPTION_CONTINUE_SEARCH 0 #define EXCEPTION_EXECUTE_HANDLER 1 #define EXCEPTION_CONTINUE_EXECUTION -1 @@ -5747,25 +5742,6 @@ struct PAL_SEHException RecordsOnStack = false; } - void EnsureExceptionRecordsOnHeap() - { - if( !RecordsOnStack || ExceptionPointers.ExceptionRecord == NULL) - { - return; - } - - CONTEXT* contextRecordCopy; - EXCEPTION_RECORD* exceptionRecordCopy; - AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); - - *exceptionRecordCopy = *ExceptionPointers.ExceptionRecord; - ExceptionPointers.ExceptionRecord = exceptionRecordCopy; - *contextRecordCopy = *ExceptionPointers.ContextRecord; - ExceptionPointers.ContextRecord = contextRecordCopy; - - RecordsOnStack = false; - } - CONTEXT* GetContextRecord() { return ExceptionPointers.ContextRecord; diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 876e53ea6e41..31842c33b349 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -202,6 +202,38 @@ void ThrowExceptionHelper(PAL_SEHException* ex) throw std::move(*ex); } +/*++ +Function: + EnsureExceptionRecordsOnHeap + + Helper function to move records from stack to heap. + +Parameters: + PAL_SEHException* exception +--*/ +static void EnsureExceptionRecordsOnHeap(PAL_SEHException* exception) +{ + if( !exception->RecordsOnStack || + exception->ExceptionPointers.ExceptionRecord == NULL ) + { + return; + } + + CONTEXT* contextRecord = exception->ExceptionPointers.ContextRecord; + EXCEPTION_RECORD* exceptionRecord = exception->ExceptionPointers.ExceptionRecord; + + CONTEXT* contextRecordCopy; + EXCEPTION_RECORD* exceptionRecordCopy; + AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy); + + *exceptionRecordCopy = *exceptionRecord; + *contextRecordCopy = *contextRecord; + + exception->ExceptionPointers.ExceptionRecord = exceptionRecordCopy; + exception->ExceptionPointers.ContextRecord = contextRecordCopy; + exception->RecordsOnStack = false; +} + /*++ Function: SEHProcessException @@ -250,7 +282,7 @@ SEHProcessException(PAL_SEHException* exception) } } - exception->EnsureExceptionRecordsOnHeap(); + EnsureExceptionRecordsOnHeap(exception); if (g_hardwareExceptionHandler(exception)) { // The exception happened in managed code and the execution should continue. @@ -263,7 +295,7 @@ SEHProcessException(PAL_SEHException* exception) if (CatchHardwareExceptionHolder::IsEnabled()) { - exception->EnsureExceptionRecordsOnHeap(); + EnsureExceptionRecordsOnHeap(exception); PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception); } }