www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 23440] New: closure over typesafe variadic or scope array


          Issue ID: 23440
           Summary: closure over typesafe variadic or scope array passes
                    safe though leads to stack corruption
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: destructionator gmail.com

Consider the following:

void delegate()  safe foo(int[] stuff...)  safe { // adding `scope` to `stuff`
makes no difference
        return () {
                assert(stuff == [1,2,3]);
                foreach(item; stuff) {}

void delegate()  safe helper()  safe {
        return foo(1, 2, 3);

void bar()  safe {
        int[2048] pwned; // just to smash the stack

void main()  safe {
        auto dg = helper();

Note how everything is ` safe`, though a dmd master build (from mid October),
including the -dip1000 switch, fails to catch the problem here.

The call to `foo` does a stack allocation, which makes enough sense, it
normally does for a typesafe variadic and that's fine. The receiving function
doesn't know the pedigree of the array. So it should assume `scope`. This PR
merged recently does this: https://github.com/dlang/dmd/pull/14324 which is
probably why adding the keyword here doesn't change anything; it is already
implicitly scope.

However, the delegate is able to capture it anyway, without any error being
reported. The `stuff` variable itself is captured on the heap closure, but the
`stuff.ptr` is not, which is why the assert is liable to fail.

In some cases, you do pass an infinite lifetime array to a typesafe variadic,
but the function just doesn't know, so it has to be more conservative. It
should prohibit capturing it and extending the lifetime - somehow - without the
programmer's intervention to pass the safe checks.

bugzilla suggested this: https://issues.dlang.org/show_bug.cgi?id=5212 as a
duplicate and they have a similar root cause but not quite the same, as my case
launders it through a closure instead of a direct assignment.

Oct 27 2022