Skip to content

Commit

Permalink
Merge pull request #5876 from WalterBright/fix15672
Browse files Browse the repository at this point in the history
fix Issue 15672 - Casting from void[] to T[] is erroneously considere…
  • Loading branch information
andralex committed Jun 27, 2016
2 parents 4341e9a + b232036 commit 5ca4b33
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
22 changes: 22 additions & 0 deletions src/expression.d
Expand Up @@ -11244,13 +11244,35 @@ extern (C++) final class CastExp : UnaExp
{
Type tobn = tob.nextOf().toBasetype();
Type t1bn = t1b.nextOf().toBasetype();

/* From void[] to anything mutable is unsafe because:
* int*[] api;
* void[] av = api;
* int[] ai = cast(int[]) av;
* ai[0] = 7;
* *api[0] crash!
*/
if (t1bn.ty == Tvoid && tobn.isMutable() && 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();

/* 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())
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;
Expand Down
38 changes: 38 additions & 0 deletions test/fail_compilation/test15672.d
@@ -0,0 +1,38 @@
/*
* TEST_OUTPUT:
---
fail_compilation/test15672.d(15): Error: cast from void[] to byte[] not allowed in safe code
fail_compilation/test15672.d(25): Error: cast from void* to byte* not allowed in safe code
---
*/
// https://issues.dlang.org/show_bug.cgi?id=15672

alias byte T;
alias const(byte) CT;

@safe T[] test1(void[] a)
{
return cast(T[])a;
}

@safe CT[] test2(void[] a)
{
return cast(CT[])a;
}

@safe T* test3(void* a)
{
return cast(T*)a;
}

@safe CT* test4(void* a)
{
return cast(CT*)a;
}

@safe T[] test5()
{
return cast(T[])[];
}


4 changes: 2 additions & 2 deletions test/runnable/testsafe.d
Expand Up @@ -12,7 +12,7 @@ void pointercast()
static assert(!__traits(compiles, cast(int*)b));
static assert(!__traits(compiles, cast(int*)b));
static assert(!__traits(compiles, cast(short*)b));
static assert( __traits(compiles, cast(byte*)b));
static assert(!__traits(compiles, cast(byte*)b));
static assert( __traits(compiles, cast(short*)a));
static assert( __traits(compiles, cast(byte*)a));
}
Expand Down Expand Up @@ -311,7 +311,7 @@ void arraycast()
int[] x;
void[] y = x;
static assert( __traits(compiles, cast(void[])x));
static assert( __traits(compiles, cast(int[])y));
static assert(!__traits(compiles, cast(int[])y));
static assert(!__traits(compiles, cast(int*[])y));
static assert(!__traits(compiles, cast(void[][])y));

Expand Down

0 comments on commit 5ca4b33

Please sign in to comment.