]> Cypherpunks repositories - gostls13.git/commitdiff
gc: more cleanup
authorRuss Cox <rsc@golang.org>
Wed, 9 Jun 2010 18:00:55 +0000 (11:00 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 9 Jun 2010 18:00:55 +0000 (11:00 -0700)
 * 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

src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/subr.c
src/cmd/gc/typecheck.c
src/cmd/gc/unsafe.c
test/interface/explicit.go

index 18e87f0cadf460a44396a86d7664b29d97dd35d6..2cf408e760025aedb49427810259d7c4c79c21cc 100644 (file)
@@ -659,6 +659,7 @@ EXTERN      char*   outfile;
 EXTERN Biobuf* bout;
 EXTERN int     nerrors;
 EXTERN int     nsyntaxerrors;
+EXTERN int     safemode;
 EXTERN char    namebuf[NSYMB];
 EXTERN char    lexbuf[NSYMB];
 EXTERN char    debug[256];
index 7f85271749a7532e78d4f169968cd6409f0e7a7a..5dc6d78cfe6381030086c6ca8d72ee661907b749 100644 (file)
@@ -21,6 +21,26 @@ enum
        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
 main(int argc, char *argv[])
 {
@@ -62,19 +82,24 @@ main(int argc, char *argv[])
                break;
 
        case 'o':
-               outfile = ARGF();
+               outfile = EARGF(usage());
                break;
 
        case 'I':
-               addidir(ARGF());
+               addidir(EARGF(usage()));
+               break;
+       
+       case 'u':
+               safemode = 1;
                break;
+
        case 'V':
                print("%cg version %s\n", thechar, getgoversion());
-               errorexit();
+               exit(0);
        } ARGEND
 
        if(argc < 1)
-               goto usage;
+               usage();
 
        // special flag to detect compilation of package runtime
        compiling_runtime = debug['+'];
@@ -188,22 +213,6 @@ main(int argc, char *argv[])
        flusherrors();
        exit(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
@@ -336,6 +345,10 @@ importfile(Val *f, int line)
        }
 
        if(strcmp(f->u.sval->s, "unsafe") == 0) {
+               if(safemode) {
+                       yyerror("cannot import package unsafe");
+                       errorexit();
+               }
                importpkg = mkpkg(f->u.sval);
                cannedimports("unsafe.6", unsafeimport);
                return;
@@ -461,7 +474,7 @@ _yylex(void)
 {
        int c, c1, clen, escflag, ncp;
        vlong v;
-       char *cp;
+       char *cp, *ep;
        Rune rune;
        Sym *s;
        static Loophack *lstk;
@@ -485,11 +498,13 @@ l0:
        if(c >= Runeself) {
                /* all multibyte runes are alpha */
                cp = lexbuf;
+               ep = lexbuf+sizeof lexbuf;
                goto talph;
        }
 
        if(isalpha(c)) {
                cp = lexbuf;
+               ep = lexbuf+sizeof lexbuf;
                goto talph;
        }
 
@@ -504,12 +519,14 @@ l0:
 
        case '_':
                cp = lexbuf;
+               ep = lexbuf+sizeof lexbuf;
                goto talph;
 
        case '.':
                c1 = getc();
                if(isdigit(c1)) {
                        cp = lexbuf;
+                       ep = lexbuf+sizeof lexbuf;
                        *cp++ = c;
                        c = c1;
                        c1 = 0;
@@ -862,6 +879,10 @@ talph:
         * prefix has been stored
         */
        for(;;) {
+               if(cp+10 >= ep) {
+                       yyerror("identifier too long");
+                       errorexit();
+               }
                if(c >= Runeself) {
                        ungetc(c);
                        rune = getr();
@@ -898,8 +919,13 @@ talph:
 tnum:
        c1 = 0;
        cp = lexbuf;
+       ep = lexbuf+sizeof lexbuf;
        if(c != '0') {
                for(;;) {
+                       if(cp+10 >= ep) {
+                               yyerror("identifier too long");
+                               errorexit();
+                       }
                        *cp++ = c;
                        c = getc();
                        if(isdigit(c))
@@ -911,6 +937,10 @@ tnum:
        c = getc();
        if(c == 'x' || c == 'X') {
                for(;;) {
+                       if(cp+10 >= ep) {
+                               yyerror("identifier too long");
+                               errorexit();
+                       }
                        *cp++ = c;
                        c = getc();
                        if(isdigit(c))
@@ -930,6 +960,10 @@ tnum:
 
        c1 = 0;
        for(;;) {
+               if(cp+10 >= ep) {
+                       yyerror("identifier too long");
+                       errorexit();
+               }
                if(!isdigit(c))
                        break;
                if(c < '0' || c > '7')
@@ -973,6 +1007,10 @@ ncu:
 
 casedot:
        for(;;) {
+               if(cp+10 >= ep) {
+                       yyerror("identifier too long");
+                       errorexit();
+               }
                *cp++ = c;
                c = getc();
                if(!isdigit(c))
@@ -993,6 +1031,10 @@ casee:
        if(!isdigit(c))
                yyerror("malformed fp constant exponent");
        while(isdigit(c)) {
+               if(cp+10 >= ep) {
+                       yyerror("identifier too long");
+                       errorexit();
+               }
                *cp++ = c;
                c = getc();
        }
@@ -1010,6 +1052,10 @@ casep:
        if(!isdigit(c))
                yyerror("malformed fp constant exponent");
        while(isdigit(c)) {
+               if(cp+10 >= ep) {
+                       yyerror("identifier too long");
+                       errorexit();
+               }
                *cp++ = c;
                c = getc();
        }
@@ -1254,7 +1300,7 @@ hex:
                ungetc(c);
                break;
        }
-       if(u && l > Runemax) {
+       if(u && (l > Runemax || (0xd800 <= l && l < 0xe000))) {
                yyerror("invalid Unicode code point in escape sequence: %#llx", l);
                l = Runeerror;
        }
index 96d03617ceac2f7abe9a689d5932a327733da11a..649b8f542819c5eaaf917d2b80c3e48e83bd8f78 100644 (file)
@@ -877,7 +877,6 @@ Oconv(Fmt *fp)
 int
 Lconv(Fmt *fp)
 {
-       char str[STRINGSZ], s[STRINGSZ];
        struct
        {
                Hist*   incl;   /* start of this include file */
@@ -917,29 +916,25 @@ Lconv(Fmt *fp)
        if(n > HISTSZ)
                n = HISTSZ;
 
-       str[0] = 0;
        for(i=n-1; i>=0; i--) {
                if(i != n-1) {
                        if(fp->flags & ~(FmtWidth|FmtPrec))
                                break;
-                       strcat(str, " ");
+                       fmtprint(fp, " ");
                }
                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].incl->name, lno-a[i].idel+1);
                else
-                       snprint(s, STRINGSZ, "%s:%ld",
+                       fmtprint(fp, "%s:%ld",
                                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 */
        }
        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;
        Sym *s;
        
-       if(debug['U']) {
-               debug['U'] = 0;
+       if(debug['r']) {
+               debug['r'] = 0;
                fmtprint(fp, "%T (orig=%T)", t, t->orig);
-               debug['U'] = 1;
+               debug['r'] = 1;
                return 0;
        }
 
@@ -1871,6 +1866,11 @@ assignop(Type *src, Type *dst, char **why)
        if(why != nil)
                *why = "";
 
+       if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
+               yyerror("cannot use unsafe.Pointer");
+               errorexit();
+       }
+
        if(src == dst)
                return OCONVNOP;
        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);
                        else if(have)
                                *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
                                *why = smprint(": %T does not implement %T (missing %S method)",
                                        src, dst, missing->sym);
@@ -2031,7 +2032,6 @@ convertop(Type *src, Type *dst, char **why)
        // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
        if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
                return OCONVNOP;
-               
 
        return 0;
 }
index d285ad0a766ef73d2a333f81b278e0081170d540..592166c885e2effd63476efbfb9e055a63141001 100644 (file)
@@ -52,7 +52,7 @@ typecheck(Node **np, int top)
        Node *n, *l, *r;
        NodeList *args;
        int lno, ok, ntop;
-       Type *t;
+       Type *t, *missing, *have;
        Sym *sym;
        Val v;
        char *why;
@@ -521,6 +521,18 @@ reswitch:
                        if(n->type == T)
                                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;
 
        case OINDEX:
@@ -1179,6 +1191,8 @@ ret:
                        checkwidth(t);
                }
        }
+       if(safemode && isptrto(t, TANY))
+               yyerror("cannot use unsafe.Pointer");
 
        evconst(n);
        if(n->op == OTYPE && !(top & Etype)) {
index 423fc08c6ef64b36f2d52efc096bde4c702fb48b..dbf6f708a8bf35ad457bf9a2eaafd83eafc0387c 100644 (file)
@@ -19,7 +19,7 @@ unsafenmagic(Node *fn, NodeList *args)
        long v;
        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;
        if(s->pkg != unsafepkg)
                goto no;
index 797cec80e4ed483051d019c59b6959ebd917c513..120135cb68444368096ccc65d9355de16a254d5b 100644 (file)
@@ -1,4 +1,4 @@
-// errchk $G $D/$F.go
+// errchk $G -e $D/$F.go
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -50,3 +50,22 @@ func main() {
        e = E(t) // ok
        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"