Skip to content

Commit

Permalink
Merge pull request #3204 from 9rnsr/fix11824
Browse files Browse the repository at this point in the history
[REG2.065a] Issue 11824 - A stack variable escaping problem in CTFE Phobos code
  • Loading branch information
WalterBright committed Feb 7, 2014
2 parents 231e27f + dc828cc commit cbc100a
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 5 deletions.
24 changes: 19 additions & 5 deletions src/interpret.c
Original file line number Diff line number Diff line change
Expand Up @@ -1184,15 +1184,29 @@ bool stopPointersEscaping(Loc loc, Expression *e)
{
if (!e->type->hasPointers())
return true;
if ( isPointer(e->type) )
if (isPointer(e->type))
{
Expression *x = e;
if (e->op == TOKaddress)
x = ((AddrExp *)e)->e1;
if (x->op == TOKvar && ((VarExp *)x)->var->isVarDeclaration() &&
ctfeStack.isInCurrentFrame( ((VarExp *)x)->var->isVarDeclaration() ) )
{ error(loc, "returning a pointer to a local stack variable");
return false;
VarDeclaration *v;
while (x->op == TOKvar &&
(v = ((VarExp *)x)->var->isVarDeclaration()) != NULL)
{
if (v->storage_class & STCref)
{
x = v->getValue();
if (e->op == TOKaddress)
((AddrExp *)e)->e1 = x;
continue;
}
if (ctfeStack.isInCurrentFrame(v))
{
error(loc, "returning a pointer to a local stack variable");
return false;
}
else
break;
}
// TODO: If it is a TOKdotvar or TOKindex, we should check that it is not
// pointing to a local struct or static array.
Expand Down
17 changes: 17 additions & 0 deletions test/compilable/interpret3.d
Original file line number Diff line number Diff line change
Expand Up @@ -3935,6 +3935,23 @@ static assert(!is(typeof(compiles!(test7876(0)))));
static assert( is(typeof(compiles!(test7876(11)))));
static assert(!is(typeof(compiles!(test7876(10)))));

/**************************************************
11824
**************************************************/

int f11824(T)()
{
T[] arr = new T[](1);
T* getAddr(ref T a)
{
return &a;
}
getAddr(arr[0]);
return 1;
}
static assert(f11824!int()); // OK
static assert(f11824!(int[])()); // OK <- NG

/**************************************************
6817 if converted to &&, only with -inline
**************************************************/
Expand Down
72 changes: 72 additions & 0 deletions test/compilable/test11824.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// REQUIRED_ARGS: -o-
// PERMUTE_ARGS:

struct Take(R)
{
public R source;
private size_t _maxAvailable;

alias R Source;

@property bool empty()
{
return _maxAvailable == 0 || source.empty;
}

@property auto ref front()
{
return source.front;
}

void popFront()
{
source.popFront();
--_maxAvailable;
}

@property size_t length() const
{
return _maxAvailable;
}
}

struct Repeat(T)
{
private T _value;

enum bool empty = false;
@property inout(T) front() inout { return _value; }
void popFront() {}
}

Take!(Repeat!T) repeat(T)(T value, size_t n)
{
return typeof(return)(Repeat!T(value), n);
}

auto array(Range)(Range r)
{
alias E = typeof(r.front);
//static if (hasLength!Range)
{
if (r.length == 0)
return null;

auto result = new E[](r.length);

size_t i;
static auto trustedGetAddr(T)(ref T t) @trusted nothrow pure
{
return &t;
}
foreach (e; r)
{
*trustedGetAddr(result[i]) = e;
++i;
}
return cast(E[])result;
}
}

enum r = [1].repeat(1).array;
static assert(r == [[1]]);

0 comments on commit cbc100a

Please sign in to comment.