Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
fix issue 17108 Associative array byKeyValue is unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
somzzz committed Nov 2, 2017
1 parent 3092711 commit 51003a3
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 26 deletions.
88 changes: 66 additions & 22 deletions src/object.d
Expand Up @@ -1935,11 +1935,11 @@ extern (C)
// int _aaApply2(void* aa, size_t keysize, _dg2_t dg);

private struct AARange { void* impl; size_t idx; }
AARange _aaRange(void* aa) pure nothrow @nogc;
bool _aaRangeEmpty(AARange r) pure nothrow @nogc;
void* _aaRangeFrontKey(AARange r) pure nothrow @nogc;
void* _aaRangeFrontValue(AARange r) pure nothrow @nogc;
void _aaRangePopFront(ref AARange r) pure nothrow @nogc;
AARange _aaRange(void* aa) pure nothrow @nogc @safe;
bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe;
void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe;
void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe;
void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe;

int _aaEqual(in TypeInfo tiRaw, in void* e1, in void* e2);
hash_t _aaGetHash(in void* aa, in TypeInfo tiRaw) nothrow;
Expand Down Expand Up @@ -2035,7 +2035,7 @@ V[K] dup(T : V[K], K, V)(T* aa)
return (*aa).dup;
}

auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc
auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
{
import core.internal.traits : substInout;

Expand All @@ -2044,21 +2044,25 @@ auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc
AARange r;

pure nothrow @nogc:
@property bool empty() { return _aaRangeEmpty(r); }
@property ref front() { return *cast(substInout!K*)_aaRangeFrontKey(r); }
void popFront() { _aaRangePopFront(r); }
@property bool empty() @safe { return _aaRangeEmpty(r); }
@property ref front()
{
auto p = (() @trusted => cast(substInout!K*) _aaRangeFrontKey(r)) ();
return *p;
}
void popFront() @safe { _aaRangePopFront(r); }
@property Result save() { return this; }
}

return Result(_aaRange(cast(void*)aa));
return Result(_aaRange(() @trusted { return cast(void*)aa; } ()));
}

auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
{
return (*aa).byKey();
}

auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc
auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
{
import core.internal.traits : substInout;

Expand All @@ -2067,21 +2071,25 @@ auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc
AARange r;

pure nothrow @nogc:
@property bool empty() { return _aaRangeEmpty(r); }
@property ref front() { return *cast(substInout!V*)_aaRangeFrontValue(r); }
void popFront() { _aaRangePopFront(r); }
@property bool empty() @safe { return _aaRangeEmpty(r); }
@property ref front()
{
auto p = (() @trusted => cast(substInout!V*) _aaRangeFrontValue(r)) ();
return *p;
}
void popFront() @safe { _aaRangePopFront(r); }
@property Result save() { return this; }
}

return Result(_aaRange(cast(void*)aa));
return Result(_aaRange((() @trusted => cast(void*) aa) ()));
}

auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
{
return (*aa).byValue();
}

auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc
auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
{
import core.internal.traits : substInout;

Expand All @@ -2090,8 +2098,8 @@ auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc
AARange r;

pure nothrow @nogc:
@property bool empty() { return _aaRangeEmpty(r); }
@property auto front() @trusted
@property bool empty() @safe { return _aaRangeEmpty(r); }
@property auto front()
{
static struct Pair
{
Expand All @@ -2100,17 +2108,25 @@ auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc
private void* keyp;
private void* valp;

@property ref key() inout { return *cast(substInout!K*)keyp; }
@property ref value() inout { return *cast(substInout!V*)valp; }
@property ref key() inout
{
auto p = (() @trusted => cast(substInout!K*) keyp) ();
return *p;
};
@property ref value() inout
{
auto p = (() @trusted => cast(substInout!V*) valp) ();
return *p;
};
}
return Pair(_aaRangeFrontKey(r),
_aaRangeFrontValue(r));
}
void popFront() { _aaRangePopFront(r); }
void popFront() @safe { return _aaRangePopFront(r); }
@property Result save() { return this; }
}

return Result(_aaRange(cast(void*)aa));
return Result(_aaRange((() @trusted => cast(void*) aa) ()));
}

auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
Expand Down Expand Up @@ -2182,6 +2198,34 @@ inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
return (*aa).get(key, defaultValue);
}

@safe unittest
{
int[string] aa;
int a;
foreach (val; aa.byKeyValue)
{
++aa[val.key];
a = val.value;
}
}

unittest
{
static assert(!__traits(compiles,
() @safe {
struct BadValue
{
int x;
this(this) @safe { *(cast(ubyte*)(null) + 100000) = 5; } // not @safe
alias x this;
}

BadValue[int] aa;
() @safe { auto x = aa.byKey.front; } ();
}
));
}

pure nothrow unittest
{
int[int] a;
Expand Down
17 changes: 13 additions & 4 deletions src/rt/aaA.d
Expand Up @@ -88,7 +88,7 @@ private:
return used - deleted;
}

@property size_t dim() const pure nothrow @nogc
@property size_t dim() const pure nothrow @nogc @safe
{
return buckets.length;
}
Expand Down Expand Up @@ -183,7 +183,7 @@ private pure nothrow @nogc:
return hash == HASH_DELETED;
}

@property bool filled() const
@property bool filled() const @safe
{
return cast(ptrdiff_t) hash < 0;
}
Expand Down Expand Up @@ -677,7 +677,7 @@ struct Range
alias impl this;
}

extern (C) pure nothrow @nogc
extern (C) pure nothrow @nogc @safe
{
Range _aaRange(AA aa)
{
Expand All @@ -699,16 +699,25 @@ extern (C) pure nothrow @nogc

void* _aaRangeFrontKey(Range r)
{
if (r.idx >= r.dim)
return null;
return r.buckets[r.idx].entry;
}

void* _aaRangeFrontValue(Range r)
{
return r.buckets[r.idx].entry + r.valoff;
if (r.idx >= r.dim)
return null;

auto entry = r.buckets[r.idx].entry;
return entry is null ?
null :
(() @trusted { return entry + r.valoff; } ());
}

void _aaRangePopFront(ref Range r)
{
if (r.idx >= r.dim) return;
for (++r.idx; r.idx < r.dim; ++r.idx)
{
if (r.buckets[r.idx].filled)
Expand Down

0 comments on commit 51003a3

Please sign in to comment.