Bug 109991 - stack-use-after-scope
Summary: stack-use-after-scope
Status: RESOLVED DUPLICATE of bug 98675
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2023-05-26 14:43 UTC by igk
Modified: 2023-05-26 20:21 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-05-26 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description igk 2023-05-26 14:43:38 UTC
Hi,

I believe the below code should result in sanitizer complaining about stack-use-after-scope, but it does not. I've noted that clang catches this but not gcc. I've annotated where I've noted it seems to depend on whether or not constexpr is used. See  https://godbolt.org/z/Y3YKcfGda.

using T = int;

struct Wrap
{
    T const& v;
    
    // Shouldn't extend lifetime of temporary
    constexpr Wrap(T const& in) : v{in} {}
};

struct BadWrapUse final
{
    T i{};

    constexpr BadWrapUse()  // issue not caught with constexpr
    // BadWrapUse()  // issue caught without constexpr
    {
        Wrap w{T{}};  // temporary T's lifetime ends after this expression
        i = w.v;      // This should lead to stack-use-after-scope.
    }
};

int main()
{
    BadWrapUse c;
}
Comment 1 Andrew Pinski 2023-05-26 14:58:42 UTC
That is because with constexpr, the code should have been rejected ...

Take this C++20 GCC accepts it (incorrectly) but clang rejects it:
```
using T = int;
struct Wrap
{
    T const& v;
    constexpr Wrap(T const& in) : v{in} {}
};

struct BadWrapUse final
{
    T i{};
    consteval BadWrapUse()
    {
        Wrap w{T{}};  // temporary T's lifetime ends after this expression
        i = w.v;      // This should lead to stack-use-after-scope.
    }
};

int main()
{
    BadWrapUse c;
}
```

Note there might be a dup of it somewhere.
Basically in your original example, GCC is doing constexpr evulation but that is not valid for constant expression evulation ...
Comment 2 Andrew Pinski 2023-05-26 15:00:38 UTC
Dup of bug 98675.

*** This bug has been marked as a duplicate of bug 98675 ***
Comment 3 igk 2023-05-26 19:56:12 UTC
(In reply to Andrew Pinski from comment #2)
> Dup of bug 98675.
> 
> *** This bug has been marked as a duplicate of bug 98675 ***

Thanks for looking into this. I haven't quite understood though. 

I'm trying to see if I can find what you're saying that it should be rejected in the C++ 14 standard (the version I have). The closest things I can find are the following. Are they the relevant parts?

```
For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.
```
where (5.19) includes
```
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the
abstract machine (1.9), would evaluate one of the following expressions:
...
- an operation that would have undefined behavior,..
```

In my example, the function takes no arguments so there are no argument values "such that an invocation of the function or constructor could be an evaluated sub-expression of a core constant expression". This would make my program "ill-formed, no diagnostic required". I interpret this as saying the compiler isn't required to reject the code. Perhaps I'm on the wrong track, but I'm wondering, isn't such UB something sanitizer aims to catch?

Also, (not an issue with sanitizer) to me it seems odd that GCC would do constexpr evaluation when "BadWrapUse c;" is not declared as a constexpr variable, rather than not avoiding it because it is not valid.
Comment 4 Andrew Pinski 2023-05-26 19:59:32 UTC
(In reply to igk from comment #3)
> (In reply to Andrew Pinski from comment #2)
> > Dup of bug 98675.
> > 
> > *** This bug has been marked as a duplicate of bug 98675 ***
> 
> Thanks for looking into this. I haven't quite understood though. 

Let me reword of what is going on and why it is still is a dup. So the constexpr should be ignored because it is undefined code. But since GCC does not detect the undefineness yet (this is what PR 98675 is about), GCC decides that it is still a constexpr and evaluates it at compile time and removes the ability for the sanitizer to detect the undefinedness at runtime.
Comment 5 igk 2023-05-26 20:21:50 UTC
OK, becoming clearer, thanks. I'm just hoping for this to be diagnosed in some way. IIUC basically GCC doesn't diagnose the UB so it proceeds with constexpr eval just because it can, or so it thinks, and in the process makes it impossible for sanitizer to catch anything. Assuming that gets fixed some day, then GCC might as well diagnose the issue itself and hence no need for sanitizer to do anything.