Skip to content

Commit

Permalink
fix Issue 15399 - unaligned pointers are not @safe
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Jun 17, 2016
1 parent f49a6ef commit a294c6e
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 2 deletions.
63 changes: 63 additions & 0 deletions src/expression.d
Expand Up @@ -112,6 +112,42 @@ bool checkOverlappedPointer(Scope* sc, Expression e, string msg)
return false;
}

/*************************************************************
* Check if e is a DotVarExp representing a misaligned pointer.
* Print error if misaligned pointer and in @safe.
* Params:
* sc = scope
* e = expression to check
* msg = error message string
* Returns:
* true if error
*/

bool checkMisalignedPointer(Scope* sc, Expression e, string msg)
{
if (e.op != TOKdotvar)
return false;
DotVarExp dve = cast(DotVarExp)e;
if (VarDeclaration v = dve.var.isVarDeclaration())
{
if (v.isField() && !sc.intypeof && sc.func &&
(v.type.hasPointers() && v.type.toBasetype().ty != Tstruct))
{
if (auto ad = v.toParent2().isAggregateDeclaration())
{
if ((ad.type.alignment() < Target.ptrsize ||
(v.offset & (Target.ptrsize - 1))) &&
sc.func.setUnsafe())
{
e.error(msg.ptr, ad.toChars(), v.toChars());
return true;
}
}
}
}
return false;
}

/*************************************************************
* Given var, we need to get the
* right 'this' pointer if var is in an outer class, but our
Expand Down Expand Up @@ -1686,6 +1722,10 @@ extern (C++) bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type t
if (p.storageClass & STCref)
{
arg = arg.toLvalue(sc, arg);

// Look for mutable misaligned pointer in @safe mode
if (arg.type.isMutable())
err |= checkMisalignedPointer(sc, arg, "'ref' of misaligned pointer in field %s.%s is not @safe");
}
else if (p.storageClass & STCout)
{
Expand All @@ -1696,7 +1736,11 @@ extern (C++) bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type t
err = true;
}
else
{
// Look for misaligned pointer in @safe mode
err |= checkMisalignedPointer(sc, arg, "'out' of misaligned pointer in field %s.%s is not @safe");
err |= checkDefCtor(arg.loc, t); // t must be default constructible
}
arg = arg.toLvalue(sc, arg);
}
else if (p.storageClass & STClazy)
Expand Down Expand Up @@ -9058,6 +9102,11 @@ extern (C++) final class DotVarExp : UnaExp
printf("e1->type = %s\n", e1.type.toChars());
printf("var->type = %s\n", var.type.toChars());
}

// Look for misaligned pointer in @safe mode
if (checkMisalignedPointer(sc, this, "writing to misaligned pointer in field %s.%s is not @safe"))
return new ErrorExp();

return Expression.modifiableLvalue(sc, e);
}

Expand Down Expand Up @@ -10548,6 +10597,10 @@ extern (C++) final class AddrExp : UnaExp
e = e.semantic(sc);
return e;
}

// Look for misaligned pointer in @safe mode
if (checkMisalignedPointer(sc, dve, "taking address of misaligned pointer in field %s.%s is not @safe"))
return new ErrorExp();
}
else if (e1.op == TOKvar)
{
Expand Down Expand Up @@ -11945,6 +11998,16 @@ extern (C++) final class IntervalExp : Expression
return this;
}

override Expression modifiableLvalue(Scope* sc, Expression e)
{
if (sc.func.setUnsafe())
{
error("cannot modify delegate pointer in @safe code %s", toChars());
return new ErrorExp();
}
return Expression.modifiableLvalue(sc, e);
}

override void accept(Visitor v)
{
v.visit(this);
Expand Down
46 changes: 46 additions & 0 deletions test/fail_compilation/test15399.d
@@ -0,0 +1,46 @@
/* https://issues.dlang.org/show_bug.cgi?id=15399
---
fail_compilation/test15399.d(31): Error: writing to misaligned pointer in field S1.ptr is not @safe
fail_compilation/test15399.d(32): Error: writing to misaligned pointer in field S2.ptr is not @safe
fail_compilation/test15399.d(33): Error: taking address of misaligned pointer in field S1.ptr is not @safe
fail_compilation/test15399.d(34): Error: taking address of misaligned pointer in field S2.ptr is not @safe
fail_compilation/test15399.d(35): Error: 'ref' of misaligned pointer in field S1.ptr is not @safe
fail_compilation/test15399.d(36): Error: 'ref' of misaligned pointer in field S2.ptr is not @safe
fail_compilation/test15399.d(37): Error: 'out' of misaligned pointer in field S1.ptr is not @safe
fail_compilation/test15399.d(38): Error: 'out' of misaligned pointer in field S2.ptr is not @safe
---
*/

struct S1
{
char c;
align (1)
int* ptr;
}

align (1)
struct S2
{
int* ptr;
}

@safe void test(S1* s1, S2* s2)
{
int* p = s1.ptr;
p = s2.ptr;
s1.ptr = null;
s2.ptr = null;
int** pp = &s1.ptr;
pp = &s2.ptr;
bar(s1.ptr);
bar(s2.ptr);
sinister(s1.ptr);
sinister(s2.ptr);
cbar(s1.ptr);
cbar(s2.ptr);
}

@safe void bar(ref int*);
@safe void cbar(ref const int*);
@safe void sinister(out int*);

4 changes: 2 additions & 2 deletions test/runnable/testsafe.d
Expand Up @@ -156,9 +156,9 @@ void safeunions() // improved for issue 11510
su1.a = 7, su1.b = 8, su1.c = null;
su2.a = 7, su2.b = 8, su2.c = 9;
uu1.a = 7, uu1.c = null;
uu2.a = 7; uu2.b = 8, uu2.c = null;
uu2.a = 7; uu2.b = 8, //uu2.c = null;
uu3.a = 7; uu3.c = null;
uu4.a = 7; uu4.b = 8, uu4.c = null;
uu4.a = 7; uu4.b = 8, //uu4.c = null;
uu5.x.a = 7; uu5.x.b = 8, uu5.x.c = 9;
uud.a.a.a.a = null, uud.a.a.a.b = null;

Expand Down

0 comments on commit a294c6e

Please sign in to comment.