Skip to content

Commit

Permalink
fix Issue 15703 - @safe code should not allow certain types of array …
Browse files Browse the repository at this point in the history
…casts
  • Loading branch information
WalterBright committed Aug 26, 2016
1 parent 627e96b commit 811ddf9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
38 changes: 17 additions & 21 deletions src/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -11329,7 +11329,9 @@ extern (C++) final class CastExp : UnaExp

if (tob.ty == Tarray && t1b.ty == Tsarray) // Bugzilla 12502
t1b = t1b.nextOf().arrayOf();
if (tob.ty == Tarray && t1b.ty == Tarray)

if (tob.ty == Tarray && t1b.ty == Tarray ||
tob.ty == Tpointer && t1b.ty == Tpointer)
{
Type tobn = tob.nextOf().toBasetype();
Type t1bn = t1b.nextOf().toBasetype();
Expand All @@ -11341,31 +11343,25 @@ extern (C++) final class CastExp : UnaExp
* ai[0] = 7;
* *api[0] crash!
*/
if (t1bn.ty == Tvoid && tobn.isMutable() && ex.op != TOKarrayliteral)
if (t1bn.ty == Tvoid && tobn.isMutable() &&
!(tob.ty == Tarray && ex.op == TOKarrayliteral))
goto Lunsafe;

if (!tobn.hasPointers() && MODimplicitConv(t1bn.mod, tobn.mod))
goto Lsafe;
}
if (tob.ty == Tpointer && t1b.ty == Tpointer)
{
Type tobn = tob.nextOf().toBasetype();
Type t1bn = t1b.nextOf().toBasetype();
// If the struct is opaque we don't know about the struct members then the cast becomes unsafe
if (tobn.ty == Tstruct && !(cast(TypeStruct)tobn).sym.members ||
t1bn.ty == Tstruct && !(cast(TypeStruct)t1bn).sym.members)
goto Lunsafe;

/* From void* to anything mutable is unsafe because:
* int** ppi;
* void* pv = ppi;
* int* pi = cast(int*) pv;
* *pi = 7;
* **ppi crash!
*/
if (t1bn.ty == Tvoid && tobn.isMutable())
const t1pointers = t1bn.hasPointers();
const topointers = tobn.hasPointers();

if (t1pointers && !topointers && tobn.isMutable())
goto Lunsafe;

if (!t1pointers && topointers)
goto Lunsafe;

// If the struct is opaque we don't know about the struct members and the cast becomes unsafe
bool sfwrd = tobn.ty == Tstruct && !(cast(TypeStruct)tobn).sym.members ||
t1bn.ty == Tstruct && !(cast(TypeStruct)t1bn).sym.members;
if (!sfwrd && !tobn.hasPointers() &&
if (!topointers &&
tobn.ty != Tfunction && t1bn.ty != Tfunction &&
tobn.size() <= t1bn.size() &&
MODimplicitConv(t1bn.mod, tobn.mod))
Expand Down
23 changes: 23 additions & 0 deletions test/fail_compilation/test15703.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
REQUIRED_ARGS: -m32
PERMUTE_ARGS:
TEST_OUTPUT:
---
fail_compilation/test15703.d(17): Error: cast from Object[] to uint[] not allowed in safe code
fail_compilation/test15703.d(19): Error: cast from object.Object to const(uint)* not allowed in safe code
fail_compilation/test15703.d(22): Error: cast from uint[] to Object[] not allowed in safe code
---
*/

// https://issues.dlang.org/show_bug.cgi?id=15703

void test() @safe
{
auto objs = [ new Object() ];
auto longs = cast(size_t[]) objs; // error
auto longc = cast(const(size_t)[]) objs; // ok
auto longp = cast(const(size_t)*) objs[0]; // error

size_t[] al;
objs = cast(Object[]) al; // error
}

0 comments on commit 811ddf9

Please sign in to comment.