mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge DMD 1.057.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "rmem.h"
|
||||
#include "speller.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "dsymbol.h"
|
||||
@@ -347,6 +348,27 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Search for symbol with correct spelling.
|
||||
*/
|
||||
|
||||
void *symbol_search_fp(void *arg, const char *seed)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)arg;
|
||||
Identifier id(seed, 0);
|
||||
Module::clearCache();
|
||||
s = s->search(0, &id, 4|2);
|
||||
return s;
|
||||
}
|
||||
|
||||
Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||
{
|
||||
if (global.gag)
|
||||
return NULL; // don't do it for speculative compiles; too time consuming
|
||||
|
||||
return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, this, idchars);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Search for identifier id as a member of 'this'.
|
||||
* id may be a template instance.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -167,6 +167,7 @@ struct Dsymbol : Object
|
||||
virtual void semantic3(Scope *sc);
|
||||
virtual void inlineScan();
|
||||
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *search_correct(Identifier *id);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
|
||||
virtual int overloadInsert(Dsymbol *s);
|
||||
#ifdef _DH
|
||||
|
||||
@@ -55,6 +55,7 @@ int isnan(double);
|
||||
#include "hdrgen.h"
|
||||
#include "parse.h"
|
||||
|
||||
|
||||
Expression *expandVar(int result, VarDeclaration *v);
|
||||
|
||||
#define LOGSEMANTIC 0
|
||||
@@ -1059,13 +1060,10 @@ void Expression::error(const char *format, ...)
|
||||
|
||||
void Expression::warning(const char *format, ...)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void Expression::rvalue()
|
||||
@@ -1076,7 +1074,7 @@ void Expression::rvalue()
|
||||
dump(0);
|
||||
halt();
|
||||
#endif
|
||||
type = Type::tint32;
|
||||
type = Type::terror;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,6 +1136,9 @@ void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
void Expression::toMangleBuffer(OutBuffer *buf)
|
||||
{
|
||||
error("expression %s is not a valid template value argument", toChars());
|
||||
#ifdef DEBUG
|
||||
dump(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************
|
||||
@@ -1666,7 +1667,18 @@ void IntegerExp::toMangleBuffer(OutBuffer *buf)
|
||||
if ((sinteger_t)value < 0)
|
||||
buf->printf("N%jd", -value);
|
||||
else
|
||||
{
|
||||
/* This is an awful hack to maintain backwards compatibility.
|
||||
* There really always should be an 'i' before a number, but
|
||||
* there wasn't in earlier implementations, so to maintain
|
||||
* backwards compatibility it is only done if necessary to disambiguate.
|
||||
* See bugzilla 3029
|
||||
*/
|
||||
if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1]))
|
||||
buf->writeByte('i');
|
||||
|
||||
buf->printf("%jd", value);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************** ErrorExp **************************/
|
||||
@@ -2103,7 +2115,21 @@ Expression *IdentifierExp::semantic(Scope *sc)
|
||||
}
|
||||
return e->semantic(sc);
|
||||
}
|
||||
error("undefined identifier %s", ident->toChars());
|
||||
#if DMDV2
|
||||
if (ident == Id::ctfe)
|
||||
{ // Create the magic __ctfe bool variable
|
||||
VarDeclaration *vd = new VarDeclaration(loc, Type::tbool, Id::ctfe, NULL);
|
||||
Expression *e = new VarExp(loc, vd);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
|
||||
s = sc->search_correct(ident);
|
||||
if (s)
|
||||
error("undefined identifier %s, did you mean %s %s?", ident->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error("undefined identifier %s", ident->toChars());
|
||||
type = Type::terror;
|
||||
return this;
|
||||
}
|
||||
@@ -5275,14 +5301,14 @@ Expression *FileExp::semantic(Scope *sc)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (name != FileName::name(name))
|
||||
{ error("use -Jpath switch to provide path for filename %s", name);
|
||||
goto Lerror;
|
||||
}
|
||||
/* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
|
||||
* ('Path Traversal') attacks.
|
||||
* http://cwe.mitre.org/data/definitions/22.html
|
||||
*/
|
||||
|
||||
name = FileName::searchPath(global.filePath, name, 0);
|
||||
name = FileName::safeSearchPath(global.filePath, name);
|
||||
if (!name)
|
||||
{ error("file %s cannot be found, check -Jpath", se->toChars());
|
||||
{ error("file %s cannot be found or not in a path specified with -J", se->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
@@ -5820,6 +5846,14 @@ Expression *DotVarExp::semantic(Scope *sc)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
if (v->init)
|
||||
{ Expression *e = v->init->toExpression();
|
||||
if (e)
|
||||
{ e = e->copy();
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5941,11 +5975,15 @@ L1:
|
||||
e = e->semantic(sc);
|
||||
if (e->op == TOKdottd)
|
||||
{
|
||||
if (global.errors)
|
||||
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
|
||||
DotTemplateExp *dte = (DotTemplateExp *)e;
|
||||
TemplateDeclaration *td = dte->td;
|
||||
eleft = dte->e1;
|
||||
ti->tempdecl = td;
|
||||
ti->semantic(sc);
|
||||
if (!ti->inst) // if template failed to expand
|
||||
return new ErrorExp();
|
||||
Dsymbol *s = ti->inst->toAlias();
|
||||
Declaration *v = s->isDeclaration();
|
||||
if (v)
|
||||
@@ -7377,6 +7415,12 @@ Expression *CastExp::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!e1->type)
|
||||
{ error("cannot cast %s", e1->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
e = e1->castTo(sc, to);
|
||||
return e;
|
||||
}
|
||||
|
||||
24
dmd/func.c
24
dmd/func.c
@@ -640,15 +640,15 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
fdrequire = fd;
|
||||
}
|
||||
|
||||
if (!outId && f->nextOf()->toBasetype()->ty != Tvoid)
|
||||
outId = Id::result; // provide a default
|
||||
|
||||
if (fensure)
|
||||
{ /* out (result) { ... }
|
||||
* becomes:
|
||||
* tret __ensure(ref tret result) { ... }
|
||||
* __ensure(result);
|
||||
*/
|
||||
if (!outId && f->nextOf()->toBasetype()->ty != Tvoid)
|
||||
outId = Id::result; // provide a default
|
||||
|
||||
Loc loc = fensure->loc;
|
||||
Parameters *arguments = new Parameters();
|
||||
Parameter *a = NULL;
|
||||
@@ -772,14 +772,14 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (ad)
|
||||
{ VarDeclaration *v;
|
||||
|
||||
if (isFuncLiteralDeclaration() && isNested())
|
||||
if (isFuncLiteralDeclaration() && isNested() && !sc->intypeof)
|
||||
{
|
||||
error("literals cannot be class members");
|
||||
error("function literals cannot be class members");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!isNested()); // can't be both member and nested
|
||||
assert(!isNested() || sc->intypeof); // can't be both member and nested
|
||||
assert(ad->handle);
|
||||
v = new ThisDeclaration(loc, ad->handle);
|
||||
v->storage_class |= STCparameter | STCin;
|
||||
@@ -2628,15 +2628,9 @@ const char *FuncLiteralDeclaration::kind()
|
||||
|
||||
void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
static Identifier *idfunc;
|
||||
static Identifier *iddel;
|
||||
|
||||
if (!idfunc)
|
||||
idfunc = new Identifier("function", 0);
|
||||
if (!iddel)
|
||||
iddel = new Identifier("delegate", 0);
|
||||
|
||||
type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
|
||||
buf->writestring(kind());
|
||||
buf->writeByte(' ');
|
||||
type->toCBuffer(buf, NULL, hgs);
|
||||
bodyToCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -292,6 +292,11 @@ int BinExp::inlineCost(InlineCostState *ics)
|
||||
|
||||
int CallExp::inlineCost(InlineCostState *ics)
|
||||
{
|
||||
// Bugzilla 3500: super.func() calls must be devirtualized, and the inliner
|
||||
// can't handle that at present.
|
||||
if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper)
|
||||
return COST_MAX;
|
||||
|
||||
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,8 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
assert(tb->ty == Tfunction);
|
||||
TypeFunction *tf = (TypeFunction *)tb;
|
||||
Type *tret = tf->next->toBasetype();
|
||||
if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim)
|
||||
if (tf->varargs && arguments &&
|
||||
((parameters && arguments->dim != parameters->dim) || (!parameters && arguments->dim)))
|
||||
{ cantInterpret = 1;
|
||||
error("C-style variadic functions are not yet implemented in CTFE");
|
||||
return NULL;
|
||||
|
||||
42
dmd/mars.c
42
dmd/mars.c
@@ -61,9 +61,9 @@ Global::Global()
|
||||
obj_ext_alt = "obj";
|
||||
#endif
|
||||
|
||||
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
|
||||
copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.056";
|
||||
version = "v1.057";
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV_STR;
|
||||
global.structalign = 8;
|
||||
@@ -116,13 +116,10 @@ void error(Loc loc, const char *format, ...)
|
||||
|
||||
void warning(Loc loc, const char *format, ...)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void verror(Loc loc, const char *format, va_list ap)
|
||||
@@ -147,16 +144,26 @@ void vwarning(Loc loc, const char *format, va_list ap)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
char *p = loc.toChars();
|
||||
char *p = loc.toChars();
|
||||
|
||||
if (*p)
|
||||
fprintf(stdmsg, "%s: ", p);
|
||||
mem.free(p);
|
||||
if (*p)
|
||||
fprintf(stdmsg, "%s: ", p);
|
||||
mem.free(p);
|
||||
|
||||
fprintf(stdmsg, "Warning: ");
|
||||
vfprintf(stdmsg, format, ap);
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
fprintf(stdmsg, "Warning: ");
|
||||
#if _MSC_VER
|
||||
// MS doesn't recognize %zu format
|
||||
OutBuffer tmp;
|
||||
tmp.vprintf(format, ap);
|
||||
fprintf(stdmsg, "%s", tmp.toChars());
|
||||
#else
|
||||
vfprintf(stdmsg, format, ap);
|
||||
#endif
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
//halt();
|
||||
if (global.params.warnings == 1)
|
||||
global.warnings++; // warnings don't count if gagged
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +191,7 @@ void halt()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Parse and append contents of environment variable envvar
|
||||
* to argc and argv[].
|
||||
|
||||
@@ -94,6 +94,7 @@ the target object file format:
|
||||
#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer
|
||||
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
|
||||
#define SARRAYVALUE DMDV2 // static arrays are value types
|
||||
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
|
||||
|
||||
// Set if C++ mangling is done by the front end
|
||||
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS))
|
||||
@@ -182,6 +183,8 @@ struct Param
|
||||
bool useInline; // inline expand functions
|
||||
bool warnings; // enable warnings
|
||||
ubyte Dversion; // D version number
|
||||
// 1: warnings as errors
|
||||
// 2: informational warnings (no errors)
|
||||
char safe; // enforce safe memory model
|
||||
|
||||
char *argv0; // program name
|
||||
@@ -283,7 +286,8 @@ struct Global
|
||||
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
unsigned warnings; // number of warnings reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors & warnings
|
||||
|
||||
Global();
|
||||
};
|
||||
@@ -426,10 +430,9 @@ typedef uint64_t StorageClass;
|
||||
|
||||
|
||||
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
void vwarning(Loc loc, const char *format, va_list);
|
||||
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
void verror(Loc loc, const char *format, va_list);
|
||||
|
||||
void vwarning(Loc loc, const char *format, va_list);
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
@@ -905,6 +905,7 @@ void Module::gensymfile()
|
||||
|
||||
int Module::needModuleInfo()
|
||||
{
|
||||
//printf("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov);
|
||||
return needmoduleinfo;
|
||||
}
|
||||
|
||||
@@ -943,6 +944,13 @@ Dsymbol *Module::symtabInsert(Dsymbol *s)
|
||||
return Package::symtabInsert(s);
|
||||
}
|
||||
|
||||
void Module::clearCache()
|
||||
{
|
||||
for (int i = 0; i < amodules.dim; i++)
|
||||
{ Module *m = (Module *)amodules.data[i];
|
||||
m->searchCacheIdent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Can't run semantic on s now, try again later.
|
||||
|
||||
@@ -154,6 +154,7 @@ struct Module : Package
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
static void runDeferredSemantic();
|
||||
static void clearCache();
|
||||
int imports(Module *m);
|
||||
|
||||
// Back end
|
||||
|
||||
39
dmd/mtype.c
39
dmd/mtype.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -135,6 +135,10 @@ Type::Type(TY ty, Type *next)
|
||||
#if DMDV2
|
||||
this->cto = NULL;
|
||||
this->ito = NULL;
|
||||
this->sto = NULL;
|
||||
this->scto = NULL;
|
||||
this->wto = NULL;
|
||||
this->swto = NULL;
|
||||
#endif
|
||||
this->pto = NULL;
|
||||
this->rto = NULL;
|
||||
@@ -641,7 +645,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident)
|
||||
else if (ident == Id::size)
|
||||
{
|
||||
error(loc, ".size property should be replaced with .sizeof");
|
||||
e = new IntegerExp(loc, size(loc), Type::tsize_t);
|
||||
e = new ErrorExp();
|
||||
}
|
||||
else if (ident == Id::alignof)
|
||||
{
|
||||
@@ -679,8 +683,16 @@ Expression *Type::getProperty(Loc loc, Identifier *ident)
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
|
||||
e = new IntegerExp(loc, 1, Type::tint32);
|
||||
Dsymbol *s = NULL;
|
||||
if (ty == Tstruct || ty == Tclass || ty == Tenum || ty == Ttypedef)
|
||||
s = toDsymbol(NULL);
|
||||
if (s)
|
||||
s = s->search_correct(ident);
|
||||
if (s)
|
||||
error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars());
|
||||
else
|
||||
error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
|
||||
e = new ErrorExp();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
@@ -785,13 +797,10 @@ void Type::error(Loc loc, const char *format, ...)
|
||||
|
||||
void Type::warning(Loc loc, const char *format, ...)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
Identifier *Type::getTypeInfoIdent(int internal)
|
||||
@@ -4630,7 +4639,11 @@ L1:
|
||||
TemplateInstance *ti = s->isTemplateInstance();
|
||||
if (ti)
|
||||
{ if (!ti->semanticRun)
|
||||
{
|
||||
if (global.errors)
|
||||
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
|
||||
ti->semantic(sc);
|
||||
}
|
||||
s = ti->inst->toAlias();
|
||||
if (!s->isTemplateInstance())
|
||||
goto L1;
|
||||
@@ -5071,7 +5084,11 @@ L1:
|
||||
TemplateInstance *ti = s->isTemplateInstance();
|
||||
if (ti)
|
||||
{ if (!ti->semanticRun)
|
||||
{
|
||||
if (global.errors)
|
||||
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
|
||||
ti->semantic(sc);
|
||||
}
|
||||
s = ti->inst->toAlias();
|
||||
if (!s->isTemplateInstance())
|
||||
goto L1;
|
||||
|
||||
136
dmd/root/root.c
136
dmd/root/root.c
@@ -1,8 +1,8 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
@@ -819,6 +820,91 @@ char *FileName::searchPath(Array *path, const char *name, int cwd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Search Path for file in a safe manner.
|
||||
*
|
||||
* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
|
||||
* ('Path Traversal') attacks.
|
||||
* http://cwe.mitre.org/data/definitions/22.html
|
||||
* More info:
|
||||
* https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources
|
||||
* Returns:
|
||||
* NULL file not found
|
||||
* !=NULL mem.malloc'd file name
|
||||
*/
|
||||
|
||||
char *FileName::safeSearchPath(Array *path, const char *name)
|
||||
{
|
||||
#if _WIN32
|
||||
/* Disallow % / \ : and .. in name characters
|
||||
*/
|
||||
for (const char *p = name; *p; p++)
|
||||
{
|
||||
char c = *p;
|
||||
if (c == '\\' || c == '/' || c == ':' || c == '%' ||
|
||||
(c == '.' && p[1] == '.'))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return FileName::searchPath(path, name, 0);
|
||||
#elif POSIX
|
||||
/* Even with realpath(), we must check for // and disallow it
|
||||
*/
|
||||
for (const char *p = name; *p; p++)
|
||||
{
|
||||
char c = *p;
|
||||
if (c == '/' && p[1] == '/')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (path)
|
||||
{ unsigned i;
|
||||
|
||||
/* Each path is converted to a cannonical name and then a check is done to see
|
||||
* that the searched name is really a child one of the the paths searched.
|
||||
*/
|
||||
for (i = 0; i < path->dim; i++)
|
||||
{
|
||||
char *cname = NULL;
|
||||
char *cpath = canonicalName((char *)path->data[i]);
|
||||
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
||||
// name, (char *)path->data[i], cpath);
|
||||
if (cpath == NULL)
|
||||
goto cont;
|
||||
cname = canonicalName(combine(cpath, name));
|
||||
//printf("FileName::safeSearchPath(): cname=%s\n", cname);
|
||||
if (cname == NULL)
|
||||
goto cont;
|
||||
//printf("FileName::safeSearchPath(): exists=%i "
|
||||
// "strncmp(cpath, cname, %i)=%i\n", exists(cname),
|
||||
// strlen(cpath), strncmp(cpath, cname, strlen(cpath)));
|
||||
// exists and name is *really* a "child" of path
|
||||
if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0)
|
||||
{
|
||||
free(cpath);
|
||||
char *p = mem.strdup(cname);
|
||||
free(cname);
|
||||
return p;
|
||||
}
|
||||
cont:
|
||||
if (cpath)
|
||||
free(cpath);
|
||||
if (cname)
|
||||
free(cname);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int FileName::exists(const char *name)
|
||||
{
|
||||
#if POSIX
|
||||
@@ -886,6 +972,52 @@ void FileName::ensurePathExists(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
* Return canonical version of name in a malloc'd buffer.
|
||||
* This code is high risk.
|
||||
*/
|
||||
char *FileName::canonicalName(const char *name)
|
||||
{
|
||||
#if linux
|
||||
// Lovely glibc extension to do it for us
|
||||
return canonicalize_file_name(name);
|
||||
#elif POSIX
|
||||
#if _POSIX_VERSION >= 200809L || defined (linux)
|
||||
// NULL destination buffer is allowed and preferred
|
||||
return realpath(name, NULL);
|
||||
#else
|
||||
char *cname = NULL;
|
||||
#if PATH_MAX
|
||||
/* PATH_MAX must be defined as a constant in <limits.h>,
|
||||
* otherwise using it is unsafe due to TOCTOU
|
||||
*/
|
||||
size_t path_max = (size_t)PATH_MAX;
|
||||
if (path_max > 0)
|
||||
{
|
||||
/* Need to add one to PATH_MAX because of realpath() buffer overflow bug:
|
||||
* http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt
|
||||
*/
|
||||
cname = (char *)malloc(path_max + 1);
|
||||
if (cname == NULL)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return realpath(name, cname);
|
||||
#endif
|
||||
#elif _WIN32
|
||||
/* Apparently, there is no good way to do this on Windows.
|
||||
* GetFullPathName isn't it.
|
||||
*/
|
||||
assert(0);
|
||||
return NULL;
|
||||
#else
|
||||
assert(0);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/****************************** File ********************************/
|
||||
|
||||
File::File(FileName *n)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
@@ -156,8 +156,10 @@ struct FileName : String
|
||||
|
||||
void CopyTo(FileName *to);
|
||||
static char *searchPath(Array *path, const char *name, int cwd);
|
||||
static char *safeSearchPath(Array *path, const char *name);
|
||||
static int exists(const char *name);
|
||||
static void ensurePathExists(const char *path);
|
||||
static char *canonicalName(const char *name);
|
||||
};
|
||||
|
||||
struct File : Object
|
||||
|
||||
27
dmd/scope.c
27
dmd/scope.c
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2005 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "speller.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "init.h"
|
||||
@@ -361,3 +362,27 @@ void Scope::setNoFree()
|
||||
//assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* Given the failed search attempt, try to find
|
||||
* one with a close spelling.
|
||||
*/
|
||||
|
||||
void *scope_search_fp(void *arg, const char *seed)
|
||||
{
|
||||
//printf("scope_search_fp('%s')\n", seed);
|
||||
Scope *sc = (Scope *)arg;
|
||||
Identifier id(seed, 0);
|
||||
Module::clearCache();
|
||||
Dsymbol *s = sc->search(0, &id, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search_correct(Identifier *ident)
|
||||
{
|
||||
if (global.gag)
|
||||
return NULL; // don't do it for speculative compiles; too time consuming
|
||||
|
||||
return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ struct Scope
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *search_correct(Identifier *ident);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -101,13 +101,10 @@ void Statement::error(const char *format, ...)
|
||||
|
||||
void Statement::warning(const char *format, ...)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
int Statement::hasBreak()
|
||||
@@ -737,6 +734,7 @@ Statement *UnrolledLoopStatement::semantic(Scope *sc)
|
||||
Statement *s = (Statement *) statements->data[i];
|
||||
if (s)
|
||||
{
|
||||
//printf("[%d]: %s\n", i, s->toChars());
|
||||
s = s->semantic(scd);
|
||||
statements->data[i] = s;
|
||||
}
|
||||
@@ -798,6 +796,7 @@ int UnrolledLoopStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int UnrolledLoopStatement::comeFrom()
|
||||
{ int comefrom = FALSE;
|
||||
|
||||
@@ -3466,7 +3465,6 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
Statement *s = new ExpStatement(loc, exp);
|
||||
exp = NULL;
|
||||
s = s->semantic(sc);
|
||||
loc = 0;
|
||||
return new CompoundStatement(loc, s, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -3701,7 +3701,12 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
|
||||
id = name;
|
||||
s = sc->search(loc, id, &scopesym);
|
||||
if (!s)
|
||||
{ error("template '%s' is not defined", id->toChars());
|
||||
{
|
||||
s = sc->search_correct(id);
|
||||
if (s)
|
||||
error("template '%s' is not defined, did you mean %s?", id->toChars(), s->toChars());
|
||||
else
|
||||
error("template '%s' is not defined", id->toChars());
|
||||
return NULL;
|
||||
}
|
||||
#if LOG
|
||||
|
||||
Reference in New Issue
Block a user