[Issue 23440] New: closure over typesafe variadic or scope array passes safe though leads to stack corruption
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Oct 27 15:41:13 UTC 2022
https://issues.dlang.org/show_bug.cgi?id=23440
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 at puremagic.com
Reporter: destructionator at 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();
bar();
dg();
}
```
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.
--
More information about the Digitalmars-d-bugs
mailing list