mirror of
https://github.com/golang/go
synced 2024-11-21 21:54:40 -07:00
gc: more cleanup
* disallow surrogate pair runes. * diagnose impossible type assertions * eliminate another static buffer. * do not overflow lexbuf. * add -u flag to disable package unsafe. R=ken2 CC=golang-dev https://golang.org/cl/1619042
This commit is contained in:
parent
42a691b877
commit
a2a7d473f4
@ -659,6 +659,7 @@ EXTERN char* outfile;
|
|||||||
EXTERN Biobuf* bout;
|
EXTERN Biobuf* bout;
|
||||||
EXTERN int nerrors;
|
EXTERN int nerrors;
|
||||||
EXTERN int nsyntaxerrors;
|
EXTERN int nsyntaxerrors;
|
||||||
|
EXTERN int safemode;
|
||||||
EXTERN char namebuf[NSYMB];
|
EXTERN char namebuf[NSYMB];
|
||||||
EXTERN char lexbuf[NSYMB];
|
EXTERN char lexbuf[NSYMB];
|
||||||
EXTERN char debug[256];
|
EXTERN char debug[256];
|
||||||
|
@ -21,6 +21,26 @@ enum
|
|||||||
EOF = -1,
|
EOF = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
print("usage: %cg [flags] file.go...\n");
|
||||||
|
print("flags:\n");
|
||||||
|
// -A is allow use of "any" type, for bootstrapping
|
||||||
|
print(" -I DIR search for packages in DIR\n");
|
||||||
|
print(" -d print declarations\n");
|
||||||
|
print(" -e no limit on number of errors printed\n");
|
||||||
|
print(" -f print stack frame structure\n");
|
||||||
|
print(" -h panic on an error\n");
|
||||||
|
print(" -o file specify output file\n");
|
||||||
|
print(" -S print the assembly language\n");
|
||||||
|
print(" -V print the compiler version\n");
|
||||||
|
print(" -u disable package unsafe\n");
|
||||||
|
print(" -w print the parse tree after typing\n");
|
||||||
|
print(" -x print lex tokens\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -62,19 +82,24 @@ main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
outfile = ARGF();
|
outfile = EARGF(usage());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
addidir(ARGF());
|
addidir(EARGF(usage()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
safemode = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
print("%cg version %s\n", thechar, getgoversion());
|
print("%cg version %s\n", thechar, getgoversion());
|
||||||
errorexit();
|
exit(0);
|
||||||
} ARGEND
|
} ARGEND
|
||||||
|
|
||||||
if(argc < 1)
|
if(argc < 1)
|
||||||
goto usage;
|
usage();
|
||||||
|
|
||||||
// special flag to detect compilation of package runtime
|
// special flag to detect compilation of package runtime
|
||||||
compiling_runtime = debug['+'];
|
compiling_runtime = debug['+'];
|
||||||
@ -188,22 +213,6 @@ main(int argc, char *argv[])
|
|||||||
flusherrors();
|
flusherrors();
|
||||||
exit(0);
|
exit(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
usage:
|
|
||||||
print("flags:\n");
|
|
||||||
// -A is allow use of "any" type, for bootstrapping
|
|
||||||
print(" -I DIR search for packages in DIR\n");
|
|
||||||
print(" -d print declarations\n");
|
|
||||||
print(" -e no limit on number of errors printed\n");
|
|
||||||
print(" -f print stack frame structure\n");
|
|
||||||
print(" -h panic on an error\n");
|
|
||||||
print(" -o file specify output file\n");
|
|
||||||
print(" -S print the assembly language\n");
|
|
||||||
print(" -V print the compiler version\n");
|
|
||||||
print(" -w print the parse tree after typing\n");
|
|
||||||
print(" -x print lex tokens\n");
|
|
||||||
exit(0);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -336,6 +345,10 @@ importfile(Val *f, int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(f->u.sval->s, "unsafe") == 0) {
|
if(strcmp(f->u.sval->s, "unsafe") == 0) {
|
||||||
|
if(safemode) {
|
||||||
|
yyerror("cannot import package unsafe");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
importpkg = mkpkg(f->u.sval);
|
importpkg = mkpkg(f->u.sval);
|
||||||
cannedimports("unsafe.6", unsafeimport);
|
cannedimports("unsafe.6", unsafeimport);
|
||||||
return;
|
return;
|
||||||
@ -461,7 +474,7 @@ _yylex(void)
|
|||||||
{
|
{
|
||||||
int c, c1, clen, escflag, ncp;
|
int c, c1, clen, escflag, ncp;
|
||||||
vlong v;
|
vlong v;
|
||||||
char *cp;
|
char *cp, *ep;
|
||||||
Rune rune;
|
Rune rune;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
static Loophack *lstk;
|
static Loophack *lstk;
|
||||||
@ -485,11 +498,13 @@ l0:
|
|||||||
if(c >= Runeself) {
|
if(c >= Runeself) {
|
||||||
/* all multibyte runes are alpha */
|
/* all multibyte runes are alpha */
|
||||||
cp = lexbuf;
|
cp = lexbuf;
|
||||||
|
ep = lexbuf+sizeof lexbuf;
|
||||||
goto talph;
|
goto talph;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isalpha(c)) {
|
if(isalpha(c)) {
|
||||||
cp = lexbuf;
|
cp = lexbuf;
|
||||||
|
ep = lexbuf+sizeof lexbuf;
|
||||||
goto talph;
|
goto talph;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,12 +519,14 @@ l0:
|
|||||||
|
|
||||||
case '_':
|
case '_':
|
||||||
cp = lexbuf;
|
cp = lexbuf;
|
||||||
|
ep = lexbuf+sizeof lexbuf;
|
||||||
goto talph;
|
goto talph;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
c1 = getc();
|
c1 = getc();
|
||||||
if(isdigit(c1)) {
|
if(isdigit(c1)) {
|
||||||
cp = lexbuf;
|
cp = lexbuf;
|
||||||
|
ep = lexbuf+sizeof lexbuf;
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = c1;
|
c = c1;
|
||||||
c1 = 0;
|
c1 = 0;
|
||||||
@ -862,6 +879,10 @@ talph:
|
|||||||
* prefix has been stored
|
* prefix has been stored
|
||||||
*/
|
*/
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
if(c >= Runeself) {
|
if(c >= Runeself) {
|
||||||
ungetc(c);
|
ungetc(c);
|
||||||
rune = getr();
|
rune = getr();
|
||||||
@ -898,8 +919,13 @@ talph:
|
|||||||
tnum:
|
tnum:
|
||||||
c1 = 0;
|
c1 = 0;
|
||||||
cp = lexbuf;
|
cp = lexbuf;
|
||||||
|
ep = lexbuf+sizeof lexbuf;
|
||||||
if(c != '0') {
|
if(c != '0') {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = getc();
|
c = getc();
|
||||||
if(isdigit(c))
|
if(isdigit(c))
|
||||||
@ -911,6 +937,10 @@ tnum:
|
|||||||
c = getc();
|
c = getc();
|
||||||
if(c == 'x' || c == 'X') {
|
if(c == 'x' || c == 'X') {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = getc();
|
c = getc();
|
||||||
if(isdigit(c))
|
if(isdigit(c))
|
||||||
@ -930,6 +960,10 @@ tnum:
|
|||||||
|
|
||||||
c1 = 0;
|
c1 = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
if(!isdigit(c))
|
if(!isdigit(c))
|
||||||
break;
|
break;
|
||||||
if(c < '0' || c > '7')
|
if(c < '0' || c > '7')
|
||||||
@ -973,6 +1007,10 @@ ncu:
|
|||||||
|
|
||||||
casedot:
|
casedot:
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = getc();
|
c = getc();
|
||||||
if(!isdigit(c))
|
if(!isdigit(c))
|
||||||
@ -993,6 +1031,10 @@ casee:
|
|||||||
if(!isdigit(c))
|
if(!isdigit(c))
|
||||||
yyerror("malformed fp constant exponent");
|
yyerror("malformed fp constant exponent");
|
||||||
while(isdigit(c)) {
|
while(isdigit(c)) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = getc();
|
c = getc();
|
||||||
}
|
}
|
||||||
@ -1010,6 +1052,10 @@ casep:
|
|||||||
if(!isdigit(c))
|
if(!isdigit(c))
|
||||||
yyerror("malformed fp constant exponent");
|
yyerror("malformed fp constant exponent");
|
||||||
while(isdigit(c)) {
|
while(isdigit(c)) {
|
||||||
|
if(cp+10 >= ep) {
|
||||||
|
yyerror("identifier too long");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
c = getc();
|
c = getc();
|
||||||
}
|
}
|
||||||
@ -1254,7 +1300,7 @@ hex:
|
|||||||
ungetc(c);
|
ungetc(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(u && l > Runemax) {
|
if(u && (l > Runemax || (0xd800 <= l && l < 0xe000))) {
|
||||||
yyerror("invalid Unicode code point in escape sequence: %#llx", l);
|
yyerror("invalid Unicode code point in escape sequence: %#llx", l);
|
||||||
l = Runeerror;
|
l = Runeerror;
|
||||||
}
|
}
|
||||||
|
@ -877,7 +877,6 @@ Oconv(Fmt *fp)
|
|||||||
int
|
int
|
||||||
Lconv(Fmt *fp)
|
Lconv(Fmt *fp)
|
||||||
{
|
{
|
||||||
char str[STRINGSZ], s[STRINGSZ];
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Hist* incl; /* start of this include file */
|
Hist* incl; /* start of this include file */
|
||||||
@ -917,29 +916,25 @@ Lconv(Fmt *fp)
|
|||||||
if(n > HISTSZ)
|
if(n > HISTSZ)
|
||||||
n = HISTSZ;
|
n = HISTSZ;
|
||||||
|
|
||||||
str[0] = 0;
|
|
||||||
for(i=n-1; i>=0; i--) {
|
for(i=n-1; i>=0; i--) {
|
||||||
if(i != n-1) {
|
if(i != n-1) {
|
||||||
if(fp->flags & ~(FmtWidth|FmtPrec))
|
if(fp->flags & ~(FmtWidth|FmtPrec))
|
||||||
break;
|
break;
|
||||||
strcat(str, " ");
|
fmtprint(fp, " ");
|
||||||
}
|
}
|
||||||
if(a[i].line)
|
if(a[i].line)
|
||||||
snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
|
fmtprint(fp, "%s:%ld[%s:%ld]",
|
||||||
a[i].line->name, lno-a[i].ldel+1,
|
a[i].line->name, lno-a[i].ldel+1,
|
||||||
a[i].incl->name, lno-a[i].idel+1);
|
a[i].incl->name, lno-a[i].idel+1);
|
||||||
else
|
else
|
||||||
snprint(s, STRINGSZ, "%s:%ld",
|
fmtprint(fp, "%s:%ld",
|
||||||
a[i].incl->name, lno-a[i].idel+1);
|
a[i].incl->name, lno-a[i].idel+1);
|
||||||
if(strlen(s)+strlen(str) >= STRINGSZ-10)
|
|
||||||
break;
|
|
||||||
strcat(str, s);
|
|
||||||
lno = a[i].incl->line - 1; /* now print out start of this file */
|
lno = a[i].incl->line - 1; /* now print out start of this file */
|
||||||
}
|
}
|
||||||
if(n == 0)
|
if(n == 0)
|
||||||
strcat(str, "<epoch>");
|
fmtprint(fp, "<epoch>");
|
||||||
|
|
||||||
return fmtstrcpy(fp, str);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1135,10 +1130,10 @@ Tpretty(Fmt *fp, Type *t)
|
|||||||
Type *t1;
|
Type *t1;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
if(debug['U']) {
|
if(debug['r']) {
|
||||||
debug['U'] = 0;
|
debug['r'] = 0;
|
||||||
fmtprint(fp, "%T (orig=%T)", t, t->orig);
|
fmtprint(fp, "%T (orig=%T)", t, t->orig);
|
||||||
debug['U'] = 1;
|
debug['r'] = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,6 +1866,11 @@ assignop(Type *src, Type *dst, char **why)
|
|||||||
if(why != nil)
|
if(why != nil)
|
||||||
*why = "";
|
*why = "";
|
||||||
|
|
||||||
|
if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
|
||||||
|
yyerror("cannot use unsafe.Pointer");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
|
||||||
if(src == dst)
|
if(src == dst)
|
||||||
return OCONVNOP;
|
return OCONVNOP;
|
||||||
if(src == T || dst == T || src->etype == TFORW || dst->etype == TFORW || src->orig == T || dst->orig == T)
|
if(src == T || dst == T || src->etype == TFORW || dst->etype == TFORW || src->orig == T || dst->orig == T)
|
||||||
@ -1894,7 +1894,8 @@ assignop(Type *src, Type *dst, char **why)
|
|||||||
*why = smprint(": %T is pointer to interface, not interface", src);
|
*why = smprint(": %T is pointer to interface, not interface", src);
|
||||||
else if(have)
|
else if(have)
|
||||||
*why = smprint(": %T does not implement %T (wrong type for %S method)\n"
|
*why = smprint(": %T does not implement %T (wrong type for %S method)\n"
|
||||||
"\thave %T\n\twant %T", src, dst, missing->sym, have->type, missing->type);
|
"\thave %S%hhT\n\twant %S%hhT", src, dst, missing->sym,
|
||||||
|
have->sym, have->type, missing->sym, missing->type);
|
||||||
else
|
else
|
||||||
*why = smprint(": %T does not implement %T (missing %S method)",
|
*why = smprint(": %T does not implement %T (missing %S method)",
|
||||||
src, dst, missing->sym);
|
src, dst, missing->sym);
|
||||||
@ -2032,7 +2033,6 @@ convertop(Type *src, Type *dst, char **why)
|
|||||||
if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
|
if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
|
||||||
return OCONVNOP;
|
return OCONVNOP;
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ typecheck(Node **np, int top)
|
|||||||
Node *n, *l, *r;
|
Node *n, *l, *r;
|
||||||
NodeList *args;
|
NodeList *args;
|
||||||
int lno, ok, ntop;
|
int lno, ok, ntop;
|
||||||
Type *t;
|
Type *t, *missing, *have;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
Val v;
|
Val v;
|
||||||
char *why;
|
char *why;
|
||||||
@ -521,6 +521,18 @@ reswitch:
|
|||||||
if(n->type == T)
|
if(n->type == T)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if(n->type != T && n->type->etype != TINTER)
|
||||||
|
if(!implements(n->type, t, &missing, &have)) {
|
||||||
|
if(have)
|
||||||
|
yyerror("impossible type assertion: %+N cannot have dynamic type %T"
|
||||||
|
" (wrong type for %S method)\n\thave %S%hhT\n\twant %S%hhT",
|
||||||
|
l, n->type, missing->sym, have->sym, have->type,
|
||||||
|
missing->sym, missing->type);
|
||||||
|
else
|
||||||
|
yyerror("impossible type assertion: %+N cannot have dynamic type %T"
|
||||||
|
" (missing %S method)", l, n->type, missing->sym);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OINDEX:
|
case OINDEX:
|
||||||
@ -1179,6 +1191,8 @@ ret:
|
|||||||
checkwidth(t);
|
checkwidth(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(safemode && isptrto(t, TANY))
|
||||||
|
yyerror("cannot use unsafe.Pointer");
|
||||||
|
|
||||||
evconst(n);
|
evconst(n);
|
||||||
if(n->op == OTYPE && !(top & Etype)) {
|
if(n->op == OTYPE && !(top & Etype)) {
|
||||||
|
@ -19,7 +19,7 @@ unsafenmagic(Node *fn, NodeList *args)
|
|||||||
long v;
|
long v;
|
||||||
Val val;
|
Val val;
|
||||||
|
|
||||||
if(fn == N || fn->op != ONAME || (s = fn->sym) == S)
|
if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S)
|
||||||
goto no;
|
goto no;
|
||||||
if(s->pkg != unsafepkg)
|
if(s->pkg != unsafepkg)
|
||||||
goto no;
|
goto no;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// errchk $G $D/$F.go
|
// errchk $G -e $D/$F.go
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
@ -50,3 +50,22 @@ func main() {
|
|||||||
e = E(t) // ok
|
e = E(t) // ok
|
||||||
t = T(e) // ERROR "need explicit|need type assertion|incompatible"
|
t = T(e) // ERROR "need explicit|need type assertion|incompatible"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type M interface { M() }
|
||||||
|
var m M
|
||||||
|
|
||||||
|
var _ = m.(int) // ERROR "impossible type assertion"
|
||||||
|
|
||||||
|
type Int int
|
||||||
|
func (Int) M(float) {}
|
||||||
|
|
||||||
|
var _ = m.(Int) // ERROR "impossible type assertion"
|
||||||
|
|
||||||
|
var ii int
|
||||||
|
var jj Int
|
||||||
|
|
||||||
|
var m1 M = ii // ERROR "missing"
|
||||||
|
var m2 M = jj // ERROR "wrong type for M method"
|
||||||
|
|
||||||
|
var m3 = M(ii) // ERROR "missing"
|
||||||
|
var m4 = M(jj) // ERROR "wrong type for M method"
|
||||||
|
Loading…
Reference in New Issue
Block a user