aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2023-06-30 10:32:13 -0700
committerCopybara-Service <copybara-worker@google.com>2023-06-30 10:32:57 -0700
commit1f531be3a19055d1402ec6476c5cab80492d3c68 (patch)
treeb17de07c9cd8210a74fb5d6a0a610d4f1efe8529
parent251e720391e92ab1aec845c7fd8ecdda35737f39 (diff)
downloadgoogletest-1f531be3a19055d1402ec6476c5cab80492d3c68.tar.gz
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
-rw-r--r--googletest/src/gtest-internal-inl.h6
-rw-r--r--googletest/src/gtest.cc67
2 files changed, 27 insertions, 46 deletions
diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h
index be821662..1e9b5c26 100644
--- a/googletest/src/gtest-internal-inl.h
+++ b/googletest/src/gtest-internal-inl.h
@@ -387,10 +387,10 @@ class GTEST_API_ UnitTestOptions {
#ifdef GTEST_OS_WINDOWS
// Function for supporting the gtest_catch_exception flag.
- // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
- // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+ // Returns EXCEPTION_EXECUTE_HANDLER if given SEH exception was handled, or
+ // EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
- static int GTestShouldProcessSEH(DWORD exception_code);
+ static int GTestProcessSEH(DWORD seh_code, const char* location);
#endif // GTEST_OS_WINDOWS
// Returns true if "name" matches the ':' separated list of glob-style
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index 704e1aca..30a5cc3f 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