Fix issue with Address Sanitizer on Windows.

This commit is contained in:
Scott Hutchinson 2022-11-25 13:44:01 -08:00
parent 428a30ebd0
commit 2552ed064f
2 changed files with 39 additions and 10 deletions

View File

@ -85,7 +85,7 @@ namespace Catch {
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
}; };
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
reportFatal(def.name); reportFatal(def.name);
@ -99,7 +99,7 @@ namespace Catch {
// Since we do not support multiple instantiations, we put these // Since we do not support multiple instantiations, we put these
// into global variables and rely on cleaning them up in outlined // into global variables and rely on cleaning them up in outlined
// constructors/destructors // constructors/destructors
static PVOID exceptionHandlerHandle = nullptr; static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
// For MSVC, we reserve part of the stack memory for handling // For MSVC, we reserve part of the stack memory for handling
@ -121,18 +121,15 @@ namespace Catch {
void FatalConditionHandler::engage_platform() { void FatalConditionHandler::engage_platform() {
// Register as first handler in current chain // Register as a the top level exception filter.
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
if (!exceptionHandlerHandle) {
CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
}
} }
void FatalConditionHandler::disengage_platform() { void FatalConditionHandler::disengage_platform() {
if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { if (SetUnhandledExceptionFilter(reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) {
CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter");
} }
exceptionHandlerHandle = nullptr; previousTopLevelExceptionFilter = nullptr;
} }
} // end namespace Catch } // end namespace Catch

View File

@ -7,6 +7,7 @@
*/ */
#include "catch.hpp" #include "catch.hpp"
#include <catch2/internal/catch_windows_h_proxy.hpp>
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat"
@ -491,3 +492,34 @@ TEMPLATE_TEST_CASE_SIG("#1954 - 7 arg template test case sig compiles", "[regres
} }
}} // namespace MiscTests }} // namespace MiscTests
#if defined(CATCH_PLATFORM_WINDOWS)
void throw_and_catch()
{
__try {
RaiseException(0xC0000005, 0, 0, NULL);
}
__except (1)
{
}
}
TEST_CASE("Validate SEH behavior - handled", "[approvals][FatalConditionHandler][CATCH_PLATFORM_WINDOWS]")
{
// Validate that Catch2 framework correctly handles tests raising and handling SEH exceptions.
throw_and_catch();
}
void throw_no_catch()
{
RaiseException(0xC0000005, 0, 0, NULL);
}
TEST_CASE("Validate SEH behavior - unhandled", "[.approvals][FatalConditionHandler][CATCH_PLATFORM_WINDOWS]")
{
// Validate that Catch2 framework correctly handles tests raising and not handling SEH exceptions.
throw_no_catch();
}
#endif