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

Reply via email to