[Issue 24757] New: Escaping with typesafe variadic functions is not detected, making @safe code potentially unsafe
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Mon Sep 9 22:40:53 UTC 2024
https://issues.dlang.org/show_bug.cgi?id=24757
Issue ID: 24757
Summary: Escaping with typesafe variadic functions is not
detected, making @safe code potentially unsafe
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: issues.dlang at jmdavisProg.com
This code compiles and runs, but the assertion fails
---
void main() @safe
{
auto arr = bar();
assert(arr == [1, 2, 3]);
}
int[] foo(int[] args...) @safe
{
auto saved = args;
return saved;
}
int[] bar() @safe
{
return foo(1, 2, 3);
}
---
If you have
---
void main() @safe
{
auto arr = foo(1, 2, 3);
assert(arr == [1, 2, 3]);
}
int[] foo(int[] args...) @safe
{
auto saved = args;
return saved;
}
---
it works - presumably because the array ends up sitting on the stack in main in
that case - but it's still not actually memory safe.
If you have
---
void main() @safe
{
auto arr = foo(1, 2, 3);
assert(arr == [1, 2, 3]);
}
int[] foo(int[] args...) @safe
{
return args;
}
---
then the compiler catches it with
---
q.d(9): Error: returning `args` escapes a reference to variadic parameter
`args`
---
but once you slice the array, it can no longer catch the problem, making it so
that @safe code is not actually memory safe.
The issue is pretty similar to what happens with slicing static arrays -
https://issues.dlang.org/show_bug.cgi?id=24750 - in that DIP 1000 does solve
the problem, but without it, we have a hole in @safe. Also, just like with
static arrays, slicing the array is caught when returning it directly but isn't
otherwise (without DIP 1000).
If we want to close the hole without needing DIP 1000, it seems to me that we
either need to make it so that typesafe variadic functions are not considered
@safe, or we need the compiler to flag anywhere that slices the variadic array
as @system (even if it's implicit like when passing it to a function or using
auto to slice the entire array). Making it @system to slice the variadic array
would likely be the better choice, because then more code can be @safe, though
I expect that a large percentage of such functions will ultimately have to be
@trusted anyway, since in most cases, you're probably going to want to slice
the array rather than simply access its elements.
Also, special attention may have to be take with foreach, since depending on
how that's implemented, it could be slicing the array, but if it is, it's
guaranteed that the slice isn't escaping, because the compiler is doing it in a
way that it can't escape. But it could be that that's simply lowered to using
for with an index, in which case, no slicing actually happens, and it's a
non-issue. I just bring it up, since it occurs to me that it might be, and it
should not be flagged as @system.
But regardless of how we want to solve it, as things stand, without DIP 1000,
it's very possible to escape a variadic array from an @safe function.
--
More information about the Digitalmars-d-bugs
mailing list