On Wednesday, 25 May 2016 at 19:47:06 UTC, Nick Treleaven wrote:
On 24/05/2016 14:48, Nick Treleaven wrote:
What about:

@safe unittest
{
     RCArray!int arr;
+      arr.length = 1;
     ref r = arr[0];
arr.destroy; // refcount drops to zero, arr.impl memory freed
     r++; // writes to unallocated memory
}

Here I think local refs must be prevented from initialization by return ref (-dip25). The @rc DIP and RCArray would use return ref. It would be OK to initialize a local ref with a ref function result that is not return ref. Naturally, this would be @safe:

auto slice = [7];
ref r = slice[0];
slice.destroy;
r++; // slice memory still allocated

To elaborate: neither `scope` nor reference counting can ever protect you against explicit premature destruction of a still-referenced owner. But there is a slightly different problematic scenario:

RCArray!int arr = [7];
ref r = arr[0];
arr = [9];        // this releases the old array
r++;              // use after free

But this issue exists even without locale `ref`s:

void foo() {
    RCArray!int arr = [7];
    bar(arr, arr[0]);
}

void bar(ref RCArray!int arr, ref int r) {
    arr = [9];    // this releases the old array
    r++;          // use after free
}

It can be solved in one of two ways: Either by making the owner (`arr`) non-mutable during the existence of the references, thereby forbidding the call to `bar()` (I would prefer this one, as it's cleaner and can be used for many more things, e.g. the byLine problem), or by making the owner live longer by inserting the appropriate AddRef/Release pairs whenever such a situation arises.

Reply via email to