diff options
author | Abseil Team <absl-team@google.com> | 2023-06-30 17:32:13 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-06-30 17:32:57 (GMT) |
commit | 1f531be3a19055d1402ec6476c5cab80492d3c68 (patch) | |
tree | b17de07c9cd8210a74fb5d6a0a610d4f1efe8529 /googletest/src/gtest.cc | |
parent | 251e720391e92ab1aec845c7fd8ecdda35737f39 (diff) | |
download | googletest-1f531be3a19055d1402ec6476c5cab80492d3c68.zip googletest-1f531be3a19055d1402ec6476c5cab80492d3c68.tar.gz googletest-1f531be3a19055d1402ec6476c5cab80492d3c68.tar.bz2 |
Make GoogleTest handle SEH exceptions before stack unwinding rather than afterward
This ensure the erroring stack frame is visible and accessible when the handler is invoked.
Fixes #4298
PiperOrigin-RevId: 544692549
Change-Id: Ia165a8c293e8edc820da5f5ad4416546fffe2493
Diffstat (limited to 'googletest/src/gtest.cc')
-rw-r--r-- | googletest/src/gtest.cc | 67 |
1 files changed, 24 insertions, 43 deletions
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 704e1ac..30a5cc3 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -863,13 +863,18 @@ bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name, } #if GTEST_HAS_SEH -// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the -// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. -// This function is useful as an __except condition. -int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) { +static std::string FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << exception_code + << std::setbase(10) << " thrown in " << location << "."; + return message.GetString(); +} + +int UnitTestOptions::GTestProcessSEH(DWORD seh_code, const char* location) { // Google Test should handle a SEH exception if: // 1. the user wants it to, AND - // 2. this is not a breakpoint exception, AND + // 2. this is not a breakpoint exception or stack overflow, AND // 3. this is not a C++ exception (VC++ implements them via SEH, // apparently). // @@ -877,18 +882,20 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) { // (see http://support.microsoft.com/kb/185294 for more information). const DWORD kCxxExceptionCode = 0xe06d7363; - bool should_handle = true; + if (!GTEST_FLAG_GET(catch_exceptions) || seh_code == kCxxExceptionCode || + seh_code == EXCEPTION_BREAKPOINT || + seh_code == EXCEPTION_STACK_OVERFLOW) { + return EXCEPTION_CONTINUE_SEARCH; // Don't handle these exceptions + } - if (!GTEST_FLAG_GET(catch_exceptions)) - should_handle = false; - else if (seh_code == EXCEPTION_BREAKPOINT) - should_handle = false; - else if (seh_code == EXCEPTION_STACK_OVERFLOW) - should_handle = false; - else if (seh_code == kCxxExceptionCode) - should_handle = false; + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatSehExceptionMessage(seh_code, location) + + "\n" + "Stack trace:\n" + + ::testing::internal::GetCurrentOsStackTraceExceptTop(1)); - return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; + return EXCEPTION_EXECUTE_HANDLER; } #endif // GTEST_HAS_SEH @@ -2555,18 +2562,6 @@ bool Test::HasSameFixtureClass() { return true; } -#if GTEST_HAS_SEH - -static std::string FormatSehExceptionMessage(DWORD exception_code, - const char* location) { - Message message; - message << "SEH exception with code 0x" << std::setbase(16) << exception_code - << std::setbase(10) << " thrown in " << location << "."; - return message.GetString(); -} - -#endif // GTEST_HAS_SEH - namespace internal { #if GTEST_HAS_EXCEPTIONS @@ -2608,22 +2603,8 @@ Result HandleSehExceptionsInMethodIfSupported(T* object, Result (T::*method)(), #if GTEST_HAS_SEH __try { return (object->*method)(); - } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT - GetExceptionCode())) { - // We wrap an inner function because VC++ prohibits direct creation of - // objects with destructors on stack in functions using __try - // (see error C2712). - struct Wrapper { - static void ReportFailure(DWORD code, const char* location) { - return internal::ReportFailureInUnknownLocation( - TestPartResult::kFatalFailure, - FormatSehExceptionMessage(code, location) + - "\n" - "Stack trace:\n" + - ::testing::internal::GetCurrentOsStackTraceExceptTop(1)); - } - }; - Wrapper::ReportFailure(GetExceptionCode(), location); + } __except (internal::UnitTestOptions::GTestProcessSEH( // NOLINT + GetExceptionCode(), location)) { return static_cast<Result>(0); } #else |