https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121961
Bug ID: 121961 Summary: [coroutines] use-after-free when the awaitable's await_suspend destroys the just-suspended coroutine Product: gcc Version: 15.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: avi at scylladb dot com Target Milestone: --- The following, when compiled with -std=c++23 -fsanitize=address, detects a use-after-free. The example is a coroutine that is suspended and its await_suspend() destroys it. Since the coroutine is already suspended during entry to await_suspend, its state should not be touched. gcc 15.1 and clang 20.1 are not susceptible. --- begin reproducer --- #include <coroutine> struct a { }; struct my_coro { int* x = new int(0); struct promise_type { int* xptr = nullptr; void set(int x) { *xptr = x; } my_coro get_return_object() { auto c = my_coro(); xptr = c.x; return c; } bool await_ready() { return false; } void unhandled_exception() {} std::suspend_never initial_suspend() { return std::suspend_never(); } std::suspend_never final_suspend() noexcept { return std::suspend_never(); } }; }; struct awaitable { bool await_ready() { return false; } void await_suspend(std::coroutine_handle<my_coro::promise_type> h) { h.promise().set(7); h.destroy(); } void await_resume() {} }; awaitable operator co_await(a v) { return awaitable(); } my_coro f() { co_await a(); } int main() { auto c = f(); return *c.x; } --- end reproducer --- https://godbolt.org/z/b4oa56Pqv