Title
Potential dangling reference returned from `transform_sender`
Status
new
Section
[exec.domain.default]
Submitter
Eric Niebler

Created on 2025-08-31.00:00:00 last changed 2 days ago

Messages

Date: 2025-09-15.14:55:46

Proposed resolution:

This wording is relative to N5014.

  1. Modify [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 `e` be the expression

    tag_of_t<Sndr>().transform_sender(std::forward<Sndr>(sndr), env...)
    

    if that expression is well-formed; otherwise, static_cast<Sndr>(std::forward<Sndr>(sndr)).

    -3- Returns: `e`.

    -4- Remarks: The exception specification is equivalent to `noexcept(e)`.

Date: 2025-08-31.00:00:00

The following has been reported by Trevor Gray to me:

There is a potential stack-use-after-scope in `execution::transform_sender` with `execution::default_domain::transform_sender`.

I'll give an example of the problem using `starts_on` with the `default_domain`.

`starts_on` defines a `transform_sender` so `execution::transform_sender` will expand to:

return transform_sender(
    dom,
    dom.transform_sender(std::forward<Sndr>(sndr), env...),
    env...);

where `dom` is the `default_domain` and `sndr` is `starts_on`.

Execution flow:

  • dom.transform_sender(std::forward<Sndr>(sndr), env...) uses `default_domain` to invoke `start_on`'s `transform_sender`. The return type is `T` (where `T` is a `let_value` sender)

  • transform_sender(dom, declval<T>(), env...) is then run which uses `default_domain` to just return std::forward<T>(t).

This means the value returned from the entire expression is T&& which a reference to a temporary variable in the frame of `transform_sender` which 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.

The fix is for the spec to follow suit and return prvalues when an xvalue would otherwise be returned.

History
Date User Action Args
2025-09-15 14:55:46adminsetmessages: + msg15053
2025-08-31 00:00:00admincreate