From 6ba264b10c02042157c1dc5acdc309a7087c8ebf Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Sat, 23 Jan 2021 12:58:20 -0800 Subject: [PATCH 1/5] Wrap all std::min and std::max calls in parentheses --- include/internal/benchmark/detail/catch_estimate_clock.hpp | 4 +++- include/internal/benchmark/detail/catch_stats.cpp | 4 ++-- include/internal/benchmark/detail/catch_stats.hpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/internal/benchmark/detail/catch_estimate_clock.hpp b/include/internal/benchmark/detail/catch_estimate_clock.hpp index 055c582500..391f5d24ce 100644 --- a/include/internal/benchmark/detail/catch_estimate_clock.hpp +++ b/include/internal/benchmark/detail/catch_estimate_clock.hpp @@ -68,7 +68,9 @@ namespace Catch { } template EnvironmentEstimate> estimate_clock_cost(FloatDuration resolution) { - auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration(clock_cost_estimation_time_limit)); + auto time_limit = (std::min)( + resolution * clock_cost_estimation_tick_limit, + FloatDuration(clock_cost_estimation_time_limit)); auto time_clock = [](int k) { return Detail::measure([k] { for (int i = 0; i < k; ++i) { diff --git a/include/internal/benchmark/detail/catch_stats.cpp b/include/internal/benchmark/detail/catch_stats.cpp index b85b740ea3..dcb51b15ea 100644 --- a/include/internal/benchmark/detail/catch_stats.cpp +++ b/include/internal/benchmark/detail/catch_stats.cpp @@ -152,7 +152,7 @@ namespace Catch { double sb = stddev.point; double mn = mean.point / n; double mg_min = mn / 2.; - double sg = std::min(mg_min / 4., sb / std::sqrt(n)); + double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); double sg2 = sg * sg; double sb2 = sb * sb; @@ -171,7 +171,7 @@ namespace Catch { return (nc / n) * (sb2 - nc * sg2); }; - return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; + return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2; } diff --git a/include/internal/benchmark/detail/catch_stats.hpp b/include/internal/benchmark/detail/catch_stats.hpp index 71a460d900..1bcbc259b9 100644 --- a/include/internal/benchmark/detail/catch_stats.hpp +++ b/include/internal/benchmark/detail/catch_stats.hpp @@ -138,8 +138,8 @@ namespace Catch { double b2 = bias - z1; double a1 = a(b1); double a2 = a(b2); - auto lo = std::max(cumn(a1), 0); - auto hi = std::min(cumn(a2), n - 1); + auto lo = (std::max)(cumn(a1), 0); + auto hi = (std::min)(cumn(a2), n - 1); return { point, resample[lo], resample[hi], confidence_level }; } From 2552ed064fc91c15b354595505c59e8d871ba427 Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Fri, 25 Nov 2022 13:44:01 -0800 Subject: [PATCH 2/5] Fix issue with Address Sanitizer on Windows. --- include/internal/catch_fatal_condition.cpp | 17 +++++------ projects/SelfTest/UsageTests/Misc.tests.cpp | 32 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index 873e2ed53a..3337a98db5 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -85,7 +85,7 @@ namespace Catch { { static_cast(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) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { reportFatal(def.name); @@ -99,7 +99,7 @@ namespace Catch { // Since we do not support multiple instantiations, we put these // into global variables and rely on cleaning them up in outlined // constructors/destructors - static PVOID exceptionHandlerHandle = nullptr; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr; // For MSVC, we reserve part of the stack memory for handling @@ -121,18 +121,15 @@ namespace Catch { void FatalConditionHandler::engage_platform() { - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - if (!exceptionHandlerHandle) { - CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); - } + // Register as a the top level exception filter. + previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter); } void FatalConditionHandler::disengage_platform() { - if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { - CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); + if (SetUnhandledExceptionFilter(reinterpret_cast(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) { + CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter"); } - exceptionHandlerHandle = nullptr; + previousTopLevelExceptionFilter = nullptr; } } // end namespace Catch diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp index dcd9fc8a8a..bfd217fec7 100644 --- a/projects/SelfTest/UsageTests/Misc.tests.cpp +++ b/projects/SelfTest/UsageTests/Misc.tests.cpp @@ -7,6 +7,7 @@ */ #include "catch.hpp" +#include #ifdef __clang__ # 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 + +#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 From 845c353bf86bb731a7873eab65be211e9fcd3f7c Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Fri, 25 Nov 2022 14:28:04 -0800 Subject: [PATCH 3/5] fix include statement --- projects/SelfTest/UsageTests/Misc.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp index bfd217fec7..0fe14d42cf 100644 --- a/projects/SelfTest/UsageTests/Misc.tests.cpp +++ b/projects/SelfTest/UsageTests/Misc.tests.cpp @@ -7,7 +7,7 @@ */ #include "catch.hpp" -#include +#include "internal/catch_windows_h_proxy.h" #ifdef __clang__ # pragma clang diagnostic ignored "-Wc++98-compat" From 5dc0474d8a2c30ab3bfa8636cbe0e82545e12cfb Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Mon, 12 Dec 2022 08:09:47 -0800 Subject: [PATCH 4/5] Update to match the latest devel (v3) branch. --- include/internal/catch_fatal_condition.cpp | 8 +++++--- projects/SelfTest/UsageTests/Misc.tests.cpp | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index 3337a98db5..a6663f7173 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -125,9 +125,11 @@ namespace Catch { previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter); } - void FatalConditionHandler::disengage_platform() { - if (SetUnhandledExceptionFilter(reinterpret_cast(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) { - CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter"); + void FatalConditionHandler::disengage_platform() noexcept { + if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) { + Catch::cerr() + << "Unexpected SEH unhandled exception filter on disengage." + << " The filter was restored, but might be rolled back unexpectedly."; } previousTopLevelExceptionFilter = nullptr; } diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp index 0fe14d42cf..8a6552260f 100644 --- a/projects/SelfTest/UsageTests/Misc.tests.cpp +++ b/projects/SelfTest/UsageTests/Misc.tests.cpp @@ -491,9 +491,8 @@ TEMPLATE_TEST_CASE_SIG("#1954 - 7 arg template test case sig compiles", "[regres SUCCEED(); } -}} // namespace MiscTests - -#if defined(CATCH_PLATFORM_WINDOWS) +// MinGW doesn't support __try, and Clang has only very partial support +#if defined(_MSC_VER) void throw_and_catch() { __try { @@ -522,4 +521,18 @@ TEST_CASE("Validate SEH behavior - unhandled", "[.approvals][FatalConditionHandl // Validate that Catch2 framework correctly handles tests raising and not handling SEH exceptions. throw_no_catch(); } -#endif + +static LONG CALLBACK dummyExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) { + return EXCEPTION_CONTINUE_SEARCH; +} + +TEST_CASE("Validate SEH behavior - no crash for stack unwinding", "[approvals][!throws][!shouldfail][FatalConditionHandler][CATCH_PLATFORM_WINDOWS]") +{ + // Trigger stack unwinding with SEH top-level filter changed and validate the test fails expectedly with no application crash + SetUnhandledExceptionFilter(dummyExceptionFilter); + throw 1; +} + +#endif // _MSC_VER + +}} // namespace MiscTests From ed3bcd3dd2ab520187246d3e7bcfb5010671d6fb Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Mon, 12 Dec 2022 08:59:37 -0800 Subject: [PATCH 5/5] Fix build errors. --- include/internal/catch_fatal_condition.cpp | 4 +--- include/internal/catch_fatal_condition.h | 2 +- projects/SelfTest/UsageTests/Misc.tests.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index a6663f7173..36e418ff5b 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -127,9 +127,7 @@ namespace Catch { void FatalConditionHandler::disengage_platform() noexcept { if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) { - Catch::cerr() - << "Unexpected SEH unhandled exception filter on disengage." - << " The filter was restored, but might be rolled back unexpectedly."; + CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter"); } previousTopLevelExceptionFilter = nullptr; } diff --git a/include/internal/catch_fatal_condition.h b/include/internal/catch_fatal_condition.h index b5744f8f21..1b6c5613bd 100644 --- a/include/internal/catch_fatal_condition.h +++ b/include/internal/catch_fatal_condition.h @@ -31,7 +31,7 @@ namespace Catch { // Should be if-defed to work on current platform, can assume // engage-disengage 1:1 pairing. void engage_platform(); - void disengage_platform(); + void disengage_platform() noexcept; public: // Should also have platform-specific implementations as needed FatalConditionHandler(); diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp index 8a6552260f..87670cd0e4 100644 --- a/projects/SelfTest/UsageTests/Misc.tests.cpp +++ b/projects/SelfTest/UsageTests/Misc.tests.cpp @@ -522,7 +522,7 @@ TEST_CASE("Validate SEH behavior - unhandled", "[.approvals][FatalConditionHandl throw_no_catch(); } -static LONG CALLBACK dummyExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) { +static LONG CALLBACK dummyExceptionFilter(PEXCEPTION_POINTERS /*ExceptionInfo*/) { return EXCEPTION_CONTINUE_SEARCH; }