diff options
author | Abseil Team <absl-team@google.com> | 2023-06-28 18:44:27 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-06-28 18:45:07 (GMT) |
commit | 687c589949eaf8734484491a6882a7fc56aebc12 (patch) | |
tree | 88a924b570ab28023f83f034ff8bb5419b616b54 | |
parent | 2acd53824402affcf473b2355d7323047e660e86 (diff) | |
download | googletest-687c589949eaf8734484491a6882a7fc56aebc12.zip googletest-687c589949eaf8734484491a6882a7fc56aebc12.tar.gz googletest-687c589949eaf8734484491a6882a7fc56aebc12.tar.bz2 |
Print stack traces on SEH exceptions on Windows
Also tidies up a couple of things:
- Prevent handling of stack overflows, which cannot be done safely
- `exception_code` is a macro, so we rename it
- The `std::string` heap allocation was unnecessary
Fixes #4298
PiperOrigin-RevId: 544117790
Change-Id: I8ba61f87119d5fbdb1f653700d9867ca6f8c28ce
-rw-r--r-- | googletest/src/gtest.cc | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index d1eddf1..704e1ac 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -866,7 +866,7 @@ bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name, // 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 exception_code) { +int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) { // Google Test should handle a SEH exception if: // 1. the user wants it to, AND // 2. this is not a breakpoint exception, AND @@ -881,9 +881,11 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { if (!GTEST_FLAG_GET(catch_exceptions)) should_handle = false; - else if (exception_code == EXCEPTION_BREAKPOINT) + else if (seh_code == EXCEPTION_BREAKPOINT) should_handle = false; - else if (exception_code == kCxxExceptionCode) + else if (seh_code == EXCEPTION_STACK_OVERFLOW) + should_handle = false; + else if (seh_code == kCxxExceptionCode) should_handle = false; return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; @@ -2555,17 +2557,12 @@ bool Test::HasSameFixtureClass() { #if GTEST_HAS_SEH -// Adds an "exception thrown" fatal failure to the current test. This -// function returns its result via an output parameter pointer because VC++ -// prohibits creation of objects with destructors on stack in functions -// using __try (see error C2712). -static std::string* FormatSehExceptionMessage(DWORD exception_code, - const char* location) { +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 new std::string(message.GetString()); + return message.GetString(); } #endif // GTEST_HAS_SEH @@ -2613,14 +2610,20 @@ Result HandleSehExceptionsInMethodIfSupported(T* object, Result (T::*method)(), return (object->*method)(); } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT GetExceptionCode())) { - // We create the exception message on the heap because VC++ prohibits - // creation of objects with destructors on stack in functions using __try + // We wrap an inner function because VC++ prohibits direct creation of + // objects with destructors on stack in functions using __try // (see error C2712). - std::string* exception_message = - FormatSehExceptionMessage(GetExceptionCode(), location); - internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, - *exception_message); - delete exception_message; + 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); return static_cast<Result>(0); } #else |