[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