Skip to content

Commit

Permalink
Issue 15702: prohibit implicit conversion to void[] in @safe code if …
Browse files Browse the repository at this point in the history
…array has indirections.
  • Loading branch information
H. S. Teoh committed Feb 21, 2016
1 parent eb8c2c7 commit ced053e
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ extern (C++) Expression implicitCastTo(Expression e, Scope* sc, Type t)
result.type = t;
return;
}
if (match == MATCHconvert && e.type.ty == Tarray && t.ty == Tarray && sc.func && !sc.intypeof)
{
/* Issue 15702: @safe code should not allow implicit
* conversion of T[] to void[] if T has indirections. */
auto et = e.type.nextOf();
auto tn = t.nextOf();
if (et.hasPointers() && tn.isMutable() && sc.func.setUnsafe())
{
e.error("cannot implicitly convert expression (%s) of type %s with indirections to %s in @safe code",
e.toChars(), e.type.toChars(), t.toChars());
result = new ErrorExp();
return;
}
}
result = e.castTo(sc, t);
return;
}
Expand Down
10 changes: 10 additions & 0 deletions src/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -10740,6 +10740,16 @@ public:
{
// Disallow unsafe casts

if (t1b.ty == Tarray && tob.ty == Tarray)
{
/* Issue 15702: @safe code should not allow casting of T[] to
* U[] if T has indirections and U is mutable. */
auto et = t1b.nextOf();
auto tn = tob.nextOf();
if (et != tn && et.hasPointers() && tn.isMutable() && sc.func.setUnsafe())
goto Lunsafe;
}

// Implicit conversions are always safe
if (t1b.implicitConvTo(tob))
goto Lsafe;
Expand Down
63 changes: 63 additions & 0 deletions test/fail_compilation/fail15702.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail15702.d(39): Error: cast from int*[] to void[] not allowed in safe code
fail_compilation/fail15702.d(40): Error: cast from Object[] to void[] not allowed in safe code
fail_compilation/fail15702.d(41): Error: cannot implicitly convert expression (ptrs) of type int*[] with indirections to void[] in @safe code
fail_compilation/fail15702.d(42): Error: cannot implicitly convert expression (objs) of type Object[] with indirections to void[] in @safe code
fail_compilation/fail15702.d(43): Error: cannot implicitly convert expression ([new Object]) of type Object[] with indirections to void[] in @safe code
fail_compilation/fail15702.d(44): Error: cast from Object[] to int[] not allowed in safe code
---
*/
void notTrustworthy(void[] buf) @trusted
{
auto bytes = cast(ubyte[]) buf;
bytes[0] = 123;
}
void trustworthy(const(void)[] buf) @trusted { }

int[] ints;
int*[] ptrs;
Object[] objs;

void safeFun() @safe
{
// should be allowed:
notTrustworthy(ints);
trustworthy(ints);
trustworthy(ptrs);
trustworthy(objs);
const(void)[] arrconst = ptrs;
const(void[]) constarr = ptrs;
auto a1 = cast(const(int)[]) objs;
auto a2 = cast(int*[]) ptrs;

// typeof should not emit errors
alias X = typeof(notTrustworthy(ptrs));

// should be prohibited:
notTrustworthy(cast(void[]) ptrs);
notTrustworthy(cast(void[]) objs);
notTrustworthy(ptrs);
notTrustworthy(objs);
void[] a3 = [ new Object() ];
auto a4 = cast(int[]) objs;
}

void unsafeFun() @system
{
// should be allowed:
notTrustworthy(ints);
trustworthy(ints);
trustworthy(ptrs);
trustworthy(objs);
const(void)[] arrconst = ptrs;
const(void[]) constarr = ptrs;

// should also be allowed:
notTrustworthy(cast(void[]) ptrs);
notTrustworthy(cast(void[]) objs);
notTrustworthy(ptrs);
notTrustworthy(objs);
void[] arr = [ new Object() ];
}

0 comments on commit ced053e

Please sign in to comment.