[cfe-dev] Miscompilation: heap-use-after-free in C++ coroutines

Adrian Vogelsgesang via cfe-dev cfe-dev at lists.llvm.org
Wed Feb 3 12:21:09 PST 2021


Dear Clang community,

I think I stumbled across a front-end bug in clang’s coroutine implementation.

Having an awaitable with

```
template<typename PROMISE> std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle<PROMISE> coro) noexcept {
      coro.destroy();
     return std::experimental::noop_coroutine();
}
```

destroys the function’s own coroutine frame. This is valid, as long as no-one afterwards resumes the coroutine anymore. However, address-sanitizer reports a heap-use-after-free error (see https://godbolt.org/z/eq6eoc )

Afaict, this is because clang stores the return value of `await_suspend` in the coroutine frame. Instead, clang should probably store this return value on the stack. Storing on the stack should be valid, as it is guaranteed that this return value will never live across a suspension point.

You can find a minimal repro in https://godbolt.org/z/eq6eoc and a more complex end-to-end version in https://godbolt.org/z/8Yadv1 . See https://stackoverflow.com/questions/65991264/c-coroutines-is-it-valid-to-call-handle-destroy-from-the-final-suspend-poin (in particular the comments to David Haim’s reply) for more context.

Cheers,
Adrian

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20210203/d50b6e37/attachment.html>


More information about the cfe-dev mailing list