Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ prevent access to a temporary

Tags:

c++

I am working on a class that acts like a std::variant, in that, it stores another object using a union along with an error code. Like std::variant, there is a get_if() function that can be used to access to the object in the class. So something like this

template<typename T>
class result final 
{
    ...
    [[nodiscard]] constexpr T const *
    get_if() const noexcept
    {
        if (details::result_type::contains_t == m_which) {
            return &m_t;
        }

        return nullptr;
    }
    ...
};

Now... suppose you have a function that returns an object using this class like this:

[[nodiscard]] static bsl::result<example_implementation>
make(bsl::int32 const answer) noexcept
{
    constexpr bsl::int32 valid_answer{42};

    if (answer == valid_answer) {
        return {bsl::in_place, valid_answer};
    }

    return {bsl::errc_failure, bsl::here()};
}

All of this works great. The problem that I cam concerned about is if the user does something like this:

if (auto const impl = example_implementation::make(valid_answer).get_if()) {
    example_bind_apis_type enforced_impl{*impl};

    if (enforced_impl.member_func_example(valid_answer)) {
        bsl::print("success\n");
    }

    if (!enforced_impl.member_func_example(invalid_answer)) {
        bsl::print("success\n");
    }
}
else {
    bsl::print("failure\n");
}

In the example above, the user is creating an example_implementation, and then using get_if() to get a pointer to the object wrapped by the result object. That pointer is then dereferenced and used. ASAN detects that the stack was used after destruction of an object, which is due to the fact that the "if" statement created a temporary result object, and then returned a pointer to something inside that temporary, which is deleted after the call to get_if(). This is similar to an issue with QString that I remember years ago, when people would get a pointer to the C style string inside the QString from a temporary.

Is there a way, in C++ to prevent the user from being able to call get_if() on a temporary like this? I tried reference qualifying get_if(), but that doesn't seem to work as the make function above returns an lvalue, not an rvalue (even though RVO will likely remove the copy). All I want to do is prevent the user from making this mistake accidentally.

Update: As stated in the comments, make() is returning an rvalue, not an lvalue as I stated above, so a ref qualifier should work.

like image 357
Rian Quinn Avatar asked Feb 02 '26 02:02

Rian Quinn


1 Answers

You might use reference qualifier to your method:

template<typename T>
class result final 
{
    // ...
    [[nodiscard]] constexpr T const* get_if() const & noexcept;

    constexpr void get_if() && noexcept = delete;

    // ...
};

Demo

like image 96
Jarod42 Avatar answered Feb 04 '26 15:02

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!