Skip to content

Commit a3791fd

Browse files
nebkatclaude
andcommitted
fix(read_env): advertise inline_completion only for the tags it sends
`read_env`'s `__attrs::query` was a member template, so it returned `inline_completion` for every completion tag - even `set_stopped_t`, which read_env never sends. That made `let_value` mistakenly classify chains like read_env(q) | let_value([](auto v) { return some_async_sender; }) as inline-completing. The check `__never_sends || behavior == inline_completion` passed for every tag because read_env claimed inline across the board. `__as_awaitable` then picked the inline `__sender_awaiter`, which holds the operation state as a local in `await_suspend` and destroys it at the closing brace. For any inner sender that hadn't actually completed by then, this is a use-after-free. Bind the query to the tags read_env actually completes with: always `set_value_t`, and `set_error_t(exception_ptr)` when evaluating the query throws - both complete inline within `start()`. `set_stopped_t` now falls through to `__unknown`, so the inline check correctly fails and the non-inline awaiter gets selected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 02d671d commit a3791fd

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

include/stdexec/__detail/__read_env.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,14 @@ namespace STDEXEC
8080
template <class _Query>
8181
struct __attrs
8282
{
83-
template <class _SetTag>
8483
STDEXEC_ATTRIBUTE(nodiscard)
85-
constexpr auto query(__get_completion_behavior_t<_SetTag>) const noexcept
84+
constexpr auto query(__get_completion_behavior_t<set_value_t>) const noexcept
85+
{
86+
return __completion_behavior::__inline_completion;
87+
}
88+
89+
STDEXEC_ATTRIBUTE(nodiscard)
90+
constexpr auto query(__get_completion_behavior_t<set_error_t>) const noexcept
8691
{
8792
return __completion_behavior::__inline_completion;
8893
}

0 commit comments

Comments
 (0)