October 04, 2020
https://issues.dlang.org/show_bug.cgi?id=21291

          Issue ID: 21291
           Summary: Array literal that escapes scope is allocated on stack
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: accepts-invalid, safe
          Severity: regression
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: dkorpel@live.nl

I got memory corruption in @safe code because an array literal that was
expected to be allocated by the Garbage Collector turned out to be put on the
stack, as shown by the following @nogc code (must be compiled with -dip1000):
```
@safe:
@nogc:
struct S {
    int[] arr;
    static S create(int[] arr) pure @nogc {
       return S(arr);
    }
}

S createS() {
    // This should be GC allocated, but the compiler allows this
    // in this @nogc function and puts it on the stack!
    return S.create([0xABCD, 0xBCDE]);
}

void stompStack() {
    // set stack memory to reveal dangling stack pointers
    ubyte[128] stackMemory = 0x77;
}

extern(C) void main() {
    auto s = createS();
    assert(s.arr[0] == 0xABCD); // likely still passes
    stompStack();
    assert(s.arr[0] == 0xABCD); // likely does not pass
}
```
It seems to be important that the array literal is in a pure static member
function, though it might be possible to reduce the example further.

This is introduced in DMD version 2.092 most likely because of https://github.com/dlang/dmd/pull/11039 though I don't think the wrong code is in that PR's code. I suspect that somewhere else in the compiler the 'return scope' flag is wrongfully inferred.

--