transform_senderSection: 33.9.5 [exec.domain.default] Status: New Submitter: Eric Niebler Opened: 2025-08-31 Last modified: 2025-09-15
Priority: Not Prioritized
View all other issues in [exec.domain.default].
View all issues with New status.
Discussion:
The following has been reported by Trevor Gray to me:
There is a potential stack-use-after-scope in
I'll give an example of the problem usingexecution::transform_senderwithexecution::default_domain::transform_sender.starts_onwith thedefault_domain.starts_ondefines atransform_sendersoexecution::transform_senderwill expand to:return transform_sender( dom, dom.transform_sender(std::forward<Sndr>(sndr), env...), env...);where
Execution flow:domis thedefault_domainandsndrisstarts_on.
dom.transform_sender(std::forward<Sndr>(sndr), env...)usesdefault_domainto invokestart_on'stransform_sender. The return type isT(whereTis alet_valuesender)
transform_sender(dom, declval<T>(), env...)is then run which usesdefault_domainto just returnstd::forward<T>(t).This means the value returned from the entire expression is
T&&which a reference to a temporary variable in the frame oftransform_senderwhich is no longer valid after the return.
In the reference implementation, this scenario does not create a dangling reference because
its implementation of default_domain::transform_sender does not conform to the spec. By default,
it returns an rvalue sender as a prvalue instead of an xvalue as the spec requires.
Proposed resolution:
This wording is relative to N5014.
Modify 33.9.5 [exec.domain.default] as indicated:
template<sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) constexpr sender decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) noexcept(see below);-2- Let
ebe the expressiontag_of_t<Sndr>().transform_sender(std::forward<Sndr>(sndr), env...)if that expression is well-formed; otherwise,
-3- Returns:static_cast<Sndr>(std::forward<Sndr>(sndr)).e. -4- Remarks: The exception specification is equivalent tonoexcept(e).