catchorg / catchorg/Catch2

Fixture's destructor called before retrieving uncaught exception's message

Open
#2,868 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
21.5k
Forks
3.5k
Avg merge
3d 16h
Merged PRs (30d)
2

Description

I have a unit test project in which exceptions rely on test fixture's state. This can lead to use-after-free situations, because uncaught exception objects can outlive fixture. Following code illustrates the problem:
```cpp
#include
#include
#include

struct Context
{
Context() { std::cout << "Context::Context\n"; }
~Context() { std::cout << "Context::~Context\n"; }
};

struct ErrorUsingContext : std::exception
{
ErrorUsingContext(Context&) { std::cout << "ErrorUsingContext::ErrorUsingContext\n"; }
~ErrorUsingContext() { std::cout << "ErrorUsingContext::~ErrorUsingContext\n"; }

const char* what() const noexcept override
{
std::cout << "ErrorUsingContext::what\n";
return "description allocated and managed by Context";
}
};

struct Test
{
Context ctx;
};

TEST_CASE_METHOD(Test, "Test")
{
throw ErrorUsingContext(ctx);
}
```
Godbolt: https://godbolt.org/z/xf3x65rhe

Output:
```
Context::Context
ErrorUsingContext::ErrorUsingContext
Context::~Context
ErrorUsingContext::what

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
output.s is a Catch v3.0.0-preview.3 host application.
Run with -? for options

-------------------------------------------------------------------------------
Test
-------------------------------------------------------------------------------
/app/example.cpp:32
...............................................................................

/app/example.cpp:32: FAILED:
due to unexpected exception with message:
description allocated and managed by Context

ErrorUsingContext::~ErrorUsingContext
===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed
```

`ErrorUsingContext::what` is called after `Context::~Context` which is a problem for me, because, in my case, memory of exception's description string is allocated and managed by the `Context` (strings use custom allocators).

I can work around it, but this could be avoided if uncaught exceptions' description were retrieved and saved by Catch2 before calling fixture's destructor.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the provided TEST_CASE_METHOD example and trace Catch2's fixture teardown and unexpected-exception reporting paths. Done means the exception message is retrieved before the fixture is destroyed, with a regression test covering an exception whose what() depends on fixture state.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.