Open PetarKirov opened 5 years ago
Nice catch, taking a look. Thanks for reporting!
So: using @trusted obviously opens a can of worms. But: why isn't return scope
enough for dmd to think it's safe to return a range with a pointer to this? It should track the lifetime of the returned range as being shorter than the vector that returned it (because of return scope
) then disallow assigning it to a global. Am I missing something that would make this an automem versus a dmd bug if @trusted
is removed?
I tried a couple of things with the current layout, but I couldn't figure out how to make it @safe
.
So far, I'm thinking that only a layout like this could be easily made @safe
:
struct Vector(T)
{
Impl* impl;
long start, end;
struct Impl
{
long refs;
long capacity;
T[0] data;
}
auto range(long start, long end) scope return
{
return Vector!T(impl, start, end);
}
}
(Disclaimer: untested, typing on the phone.)
It should track the lifetime of the returned range as being shorter than the vector that returned it (because of return scope) then disallow assigning it to a global.
Agreed, though at least dmd doesn't allow this code without the use of @trusted
. I think this a good candidate for a bug report.
Am I missing something that would make this an automem versus a dmd bug if @trusted is removed?
It's a deficiency of dmd that it doesn't support @safe
alternative for your use case.
Perhaps there's a way to make it work, I'll try to think more about that, without changing the object layout.
Weirdly enough, this fails to compile as expected with dip1000:
typeof(Container.range()) global;
void main() @safe {
auto c = Container();
global = c.range;
}
struct Container {
auto range() @safe return scope {
static struct Range {
Container *self;
}
return Range(&this);
}
}
$ dmd -preview=dip1000 bug.d
bug.d(5): Error: address of variable c assigned to global with longer lifetime
Found out why: it's the _elements
member variable. Add it to the example above and dmd goes "nope".
This
@trusted
block of code:https://github.com/atilaneves/automem/blob/98d7b1b3f0d03b29b61db43c9d9a2ccb20347c1f/source/automem/vector.d#L313-L316
allows a pointer to the vector to escape:
Stack corruption PoC: