Skip to content

Commit

Permalink
Merge pull request #3683 from WalterBright/fix12485
Browse files Browse the repository at this point in the history
fix Issue 12485 - [REG2.065] DMD crashes when recursive template expansion
  • Loading branch information
yebblies committed Jul 4, 2014
2 parents 0188bd4 + d99d496 commit 1cccc74
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 15 deletions.
28 changes: 23 additions & 5 deletions src/mangle.c
Expand Up @@ -26,6 +26,7 @@
#include "module.h"

char *toCppMangle(Dsymbol *s);
void toBuffer(OutBuffer *buf, const char *id, Dsymbol *s);

void mangleFunc(OutBuffer *buf, FuncDeclaration *fd, bool inParent)
{
Expand Down Expand Up @@ -77,7 +78,7 @@ void mangleParent(OutBuffer *buf, Dsymbol *s)
if (p->getIdent())
{
const char *id = p->ident->toChars();
buf->printf("%llu%s", (ulonglong)strlen(id), id);
toBuffer(buf, id, s);

if (FuncDeclaration *f = p->isFuncDeclaration())
mangleFunc(buf, f, true);
Expand All @@ -93,7 +94,7 @@ void mangleDecl(OutBuffer *buf, Declaration *sthis)

assert(sthis->ident);
const char *id = sthis->ident->toChars();
buf->printf("%llu%s", (ulonglong)strlen(id), id);
toBuffer(buf, id, sthis);

if (FuncDeclaration *fd = sthis->isFuncDeclaration())
{
Expand Down Expand Up @@ -228,7 +229,7 @@ class Mangler : public Visitor
visit((Dsymbol *)od);
return;
}

if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration())
{
if (!od->hasOverloads || fd->isUnique())
Expand Down Expand Up @@ -337,7 +338,7 @@ class Mangler : public Visitor

ti->getIdent();
const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
buf.printf("%llu%s", (ulonglong)strlen(id), id);
toBuffer(&buf, id, ti);
id = buf.extractString();

//printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
Expand All @@ -357,7 +358,7 @@ class Mangler : public Visitor
mangleParent(&buf, s);

char *id = s->ident ? s->ident->toChars() : s->toChars();
buf.printf("%llu%s", (ulonglong)strlen(id), id);
toBuffer(&buf, id, s);
id = buf.extractString();

//printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
Expand All @@ -381,3 +382,20 @@ const char *mangleExact(FuncDeclaration *fd)
v.mangleExact(fd);
return v.result;
}


/************************************************************
* Write length prefixed string to buf.
*/

void toBuffer(OutBuffer *buf, const char *id, Dsymbol *s)
{
size_t len = strlen(id);
if (len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
s->error("excessive length %llu for symbol, possible recursive expansion?", len);
else
{
buf->printf("%llu", (ulonglong)len);
buf->write(id, len);
}
}
18 changes: 8 additions & 10 deletions src/root/outbuffer.c
Expand Up @@ -310,17 +310,16 @@ void OutBuffer::align(size_t size)

void OutBuffer::vprintf(const char *format, va_list args)
{
char buffer[128];
char *p;
unsigned psize;
int count;

p = buffer;
psize = sizeof(buffer);
if (doindent)
write(NULL, 0); // perform indent
unsigned psize = 128;
for (;;)
{
reserve(psize);
#if _WIN32
count = _vsnprintf(p,psize,format,args);
count = _vsnprintf((char *)data + offset,psize,format,args);
if (count != -1)
break;
psize *= 2;
Expand All @@ -336,7 +335,7 @@ void OutBuffer::vprintf(const char *format, va_list args)
of ap is undefined after the call. The application should call
va_end(ap) itself afterwards.
*/
count = vsnprintf(p,psize,format,va);
count = vsnprintf((char *)data + offset,psize,format,va);
va_end(va);
if (count == -1)
psize *= 2;
Expand All @@ -345,11 +344,10 @@ void OutBuffer::vprintf(const char *format, va_list args)
else
break;
#else
assert(0);
assert(0);
#endif
p = (char *) alloca(psize); // buffer too small, try again with larger size
}
write(p,count);
offset += count;
}

void OutBuffer::printf(const char *format, ...)
Expand Down
2 changes: 2 additions & 0 deletions src/template.c
Expand Up @@ -5951,13 +5951,15 @@ void TemplateInstance::tryExpandMembers(Scope *sc2)
}

expandMembers(sc2);

nest--;
}

void TemplateInstance::trySemantic3(Scope *sc2)
{
// extracted to a function to allow windows SEH to work without destructors in the same function
static int nest;
//printf("%d\n", nest);
if (++nest > 300)
{
global.gag = 0; // ensure error message gets printed
Expand Down
11 changes: 11 additions & 0 deletions test/fail_compilation/fail12485.d
@@ -0,0 +1,11 @@
void dorecursive()
{
recursive([0]);
}

void recursive(R)(R r)
{
import std.algorithm;
recursive( r.filter!(e=>true) );
}

0 comments on commit 1cccc74

Please sign in to comment.