]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: fix some overflows in the compiler
authorRob Pike <r@golang.org>
Tue, 30 Apr 2013 05:44:40 +0000 (22:44 -0700)
committerRob Pike <r@golang.org>
Tue, 30 Apr 2013 05:44:40 +0000 (22:44 -0700)
Some 64-bit fields were run through 32-bit words, some counts were
not checked for overflow, and relocations must fit in 32 bits.
Tests to follow.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/9033043

19 files changed:
src/cmd/5g/cgen.c
src/cmd/5g/gsubr.c
src/cmd/6g/cgen.c
src/cmd/6g/ggen.c
src/cmd/6g/gobj.c
src/cmd/6g/gsubr.c
src/cmd/6g/reg.c
src/cmd/8g/cgen.c
src/cmd/8g/gsubr.c
src/cmd/gc/align.c
src/cmd/gc/closure.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
src/cmd/gc/pgen.c
src/cmd/gc/sinit.c
src/cmd/gc/subr.c
src/cmd/gc/swt.c
src/cmd/gc/typecheck.c
src/cmd/gc/unsafe.c

index 0844e180f65c4e9029ea924a758ea0226588fc25..1620f410ad3b1ca08d78281d54e0cd22e47cafde 100644 (file)
@@ -680,7 +680,9 @@ agen(Node *n, Node *res)
        case ODOT:
                agen(nl, res);
                // explicit check for nil if struct is large enough
-               // that we might derive too big a pointer.
+               // that we might derive too big a pointer.  If the left node
+               // was ODOT we have already done the nil check.
+               if(nl->op != ODOT)
                if(nl->type->width >= unmappedzero) {
                        regalloc(&n1, types[tptr], N);
                        gmove(res, &n1);
index d049ebe0524ef72c477f1bfd6e30959d8903f115..815d6fab23e25c6516d8348ef5285a83cc038f98 100644 (file)
@@ -1785,7 +1785,8 @@ sudoclean(void)
 int
 dotaddable(Node *n, Node *n1)
 {
-       int o, oary[10];
+       int o;
+       int64 oary[10];
        Node *nn;
 
        if(n->op != ODOT)
@@ -1816,7 +1817,7 @@ int
 sudoaddable(int as, Node *n, Addr *a, int *w)
 {
        int o, i;
-       int oary[10];
+       int64 oary[10];
        int64 v;
        Node n1, n2, n3, n4, *nn, *l, *r;
        Node *reg, *reg1;
index 32980a50b52c7eaf89fa9c41ca3911f44e48fbfc..2eae865f330f27aeaa356aec84a714dde2d05a12 100644 (file)
@@ -568,7 +568,7 @@ agenr(Node *n, Node *a, Node *res)
        Node n1, n2, n3, n4, n5, tmp, tmp2, nlen;
        Prog *p1;
        Type *t;
-       uint32 w;
+       uint64 w;
        uint64 v;
        int freelen;
 
@@ -883,7 +883,9 @@ agen(Node *n, Node *res)
        case ODOT:
                agen(nl, res);
                // explicit check for nil if struct is large enough
-               // that we might derive too big a pointer.
+               // that we might derive too big a pointer.  If the left node
+               // was ODOT we have already done the nil check.
+               if(nl->op != ODOT)
                if(nl->type->width >= unmappedzero) {
                        regalloc(&n1, types[tptr], res);
                        gmove(res, &n1);
@@ -1285,12 +1287,12 @@ ret:
  * or return value from function call.
  * return n's offset from SP.
  */
-int32
+int64
 stkof(Node *n)
 {
        Type *t;
        Iter flist;
-       int32 off;
+       int64 off;
 
        switch(n->op) {
        case OINDREG:
index 23bb5093f04988f133c6de44ad39917815b4a5f1..5e426753c57d278444d44be8e7bcbf575c2764a3 100644 (file)
@@ -942,7 +942,7 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 void
 clearfat(Node *nl)
 {
-       uint32 w, c, q;
+       int64 w, c, q;
        Node n1, oldn1, ax, oldax;
 
        /* clear a fat object */
index 508a3548ff5d608dfa7ee9b29c5a9b233d2dee7a..cdbbd5d9db0938eef4c529673efdefcff040aca9 100644 (file)
@@ -501,7 +501,8 @@ void
 genembedtramp(Type *rcvr, Type *method, Sym *newnam, int iface)
 {
        Sym *e;
-       int c, d, o, mov, add, loaded;
+       int c, d, mov, add, loaded;
+       int64 o;
        Prog *p;
        Type *f;
        
index 73998324682b51d2bd2cc1e92190623a2cfd26d4..55864c34edc9bdc43f5be350d7df03bfb5f95e3b 100644 (file)
@@ -1147,6 +1147,8 @@ naddr(Node *n, Addr *a, int canemitcode)
                a->type = n->val.u.reg+D_INDIR;
                a->sym = n->sym;
                a->offset = n->xoffset;
+               if(a->offset != (int32)a->offset)
+                       yyerror("offset %lld too large for OINDREG", a->offset);
                checkoffset(a, canemitcode);
                break;
 
@@ -1947,9 +1949,9 @@ sudoclean(void)
 int
 sudoaddable(int as, Node *n, Addr *a)
 {
-       int o, i, w;
-       int oary[10];
-       int64 v;
+       int o, i;
+       int64 oary[10];
+       int64 v, w;
        Node n1, n2, n3, n4, *nn, *l, *r;
        Node *reg, *reg1;
        Prog *p1;
index 7db6beab934494ccd9cb95fbe58db4e2eaaf5541..ab826d431f2b474a21e611544399939bf03bec66 100644 (file)
@@ -947,9 +947,9 @@ doregbits(int r)
 }
 
 static int
-overlap(int32 o1, int w1, int32 o2, int w2)
+overlap(int64 o1, int w1, int64 o2, int w2)
 {
-       int32 t1, t2;
+       int64 t1, t2;
 
        t1 = o1+w1;
        t2 = o2+w2;
@@ -967,7 +967,7 @@ mkvar(Reg *r, Adr *a)
        int i, t, n, et, z, flag;
        int64 w;
        uint32 regu;
-       int32 o;
+       int64 o;
        Bits bit;
        Node *node;
 
index b88ea401bb8c90ac672b8f0d3251604c79a37e3e..d54db7e62930e9550dcc20283eba25c1625afb98 100644 (file)
@@ -740,7 +740,9 @@ agen(Node *n, Node *res)
        case ODOT:
                agen(nl, res);
                // explicit check for nil if struct is large enough
-               // that we might derive too big a pointer.
+               // that we might derive too big a pointer.  If the left node
+               // was ODOT we have already done the nil check.
+               if(nl->op != ODOT)
                if(nl->type->width >= unmappedzero) {
                        regalloc(&n1, types[tptr], res);
                        gmove(res, &n1);
index 79348a42dcb163ac989d26f5e3b8b96abdd3267e..756bdd2039956b212768c7304d4e26471a501fa8 100644 (file)
@@ -2391,7 +2391,8 @@ naddr(Node *n, Addr *a, int canemitcode)
 int
 dotaddable(Node *n, Node *n1)
 {
-       int o, oary[10];
+       int o;
+       int64 oary[10];
        Node *nn;
 
        if(n->op != ODOT)
index be9f552f67e4221edf2386aeb6eeec7fb27ab2fc..80c65387b38104e6b2eb8c759e0c08068ad88979 100644 (file)
@@ -46,7 +46,8 @@ static vlong
 widstruct(Type *errtype, Type *t, vlong o, int flag)
 {
        Type *f;
-       int32 w, maxalign;
+       int64 w;
+       int32 maxalign;
        
        maxalign = flag;
        if(maxalign < 1)
@@ -643,7 +644,7 @@ argsize(Type *t)
 {
        Iter save;
        Type *fp;
-       int w, x;
+       int64 w, x;
 
        w = 0;
 
@@ -664,5 +665,7 @@ argsize(Type *t)
        }
 
        w = (w+widthptr-1) & ~(widthptr-1);
+       if((int)w != w)
+               fatal("argsize too big");
        return w;
 }
index 962b08845206fd0584e25c6b270121dc64d6664e..d81c5281ddf688e06978223d4c3f4492721ed804 100644 (file)
@@ -135,7 +135,7 @@ makeclosure(Node *func)
        NodeList *l, *body;
        static int closgen;
        char *p;
-       int offset;
+       vlong offset;
 
        /*
         * wrap body in external function
index b47a04bf052e3dacbab90280c6ff5e228f8499bf..955ec2c5bbb8b8bd689678019284949198faf8a4 100644 (file)
@@ -836,7 +836,7 @@ cgen_slice(Node *n, Node *res)
  * <0 is pointer to next field (+1)
  */
 int
-dotoffset(Node *n, int *oary, Node **nn)
+dotoffset(Node *n, int64 *oary, Node **nn)
 {
        int i;
 
index 1f5fb41aaa74840c0ed071114119ec1aecd8ce70..48bcf0233f13902f49a45a582871923e63643958 100644 (file)
@@ -156,9 +156,9 @@ struct      Type
        int             lineno;
 
        // TFUNC
-       uchar   thistuple;
-       uchar   outtuple;
-       uchar   intuple;
+       int     thistuple;
+       int     outtuple;
+       int     intuple;
        uchar   outnamed;
 
        Type*   method;
@@ -252,9 +252,7 @@ struct      Node
        uchar   embedded;       // ODCLFIELD embedded type
        uchar   colas;          // OAS resulting from :=
        uchar   diag;           // already printed error about this
-       uchar   esc;            // EscXXX
        uchar   noescape;       // func arguments do not escape
-       uchar   funcdepth;
        uchar   builtin;        // built-in name, like len or close
        uchar   walkdef;
        uchar   typecheck;
@@ -269,6 +267,8 @@ struct      Node
        uchar   dupok;  // duplicate definitions ok (for func)
        schar   likely; // likeliness of if statement
        uchar   hasbreak;       // has break statement
+       uint    esc;            // EscXXX
+       int     funcdepth;
 
        // most nodes
        Type*   type;
@@ -1103,7 +1103,7 @@ void      cgen_eface(Node* n, Node* res);
 void   cgen_slice(Node* n, Node* res);
 void   clearlabels(void);
 void   checklabels(void);
-int    dotoffset(Node *n, int *oary, Node **nn);
+int    dotoffset(Node *n, int64 *oary, Node **nn);
 void   gen(Node *n);
 void   genlist(NodeList *l);
 Node*  sysfunc(char *name);
index df8903bafeaebc737946e3dba82f46e42e960b13..82d8186b0d5292b0f394c7a88c0edfa9cbd45912 100644 (file)
@@ -177,8 +177,13 @@ cmpstackvar(Node *a, Node *b)
 {
        if (a->class != b->class)
                return (a->class == PAUTO) ? 1 : -1;
-       if (a->class != PAUTO)
-               return a->xoffset - b->xoffset;
+       if (a->class != PAUTO) {
+               if (a->xoffset < b->xoffset)
+                       return -1;
+               if (a->xoffset > b->xoffset)
+                       return 1;
+               return 0;
+       }
        if ((a->used == 0) != (b->used == 0))
                return b->used - a->used;
        return b->type->align - a->type->align;
@@ -240,6 +245,10 @@ allocauto(Prog* ptxt)
                stksize = rnd(stksize, n->type->align);
                if(thechar == '5')
                        stksize = rnd(stksize, widthptr);
+               if(stksize >= (1ULL<<31)) {
+                       setlineno(curfn);
+                       yyerror("stack frame too large (>2GB)");
+               }
                n->stkdelta = -stksize - n->xoffset;
        }
 
index 353fc00ceba200fe840103e12874cd5a25f5d573..f8c61828cfb49194421fbbd90b496854d9f29a05 100644 (file)
@@ -801,7 +801,8 @@ maplit(int ctxt, Node *n, Node *var, NodeList **init)
 {
        Node *r, *a;
        NodeList *l;
-       int nerr, b;
+       int nerr;
+       int64 b;
        Type *t, *tk, *tv, *t1;
        Node *vstat, *index, *value;
        Sym *syma, *symb;
@@ -1142,7 +1143,10 @@ stataddr(Node *nam, Node *n)
                l = getlit(n->right);
                if(l < 0)
                        break;
-               nam->xoffset += l*n->type->width;
+               // Check for overflow.
+               if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
+                       break;
+               nam->xoffset += l*n->type->width;
                nam->type = n->type;
                return 1;
        }
index bd78fb0246654f6e7b525fb7c2b014f9e10892f9..20a15bc7157c7340981cf6ebe2bbfda772a04c6e 100644 (file)
@@ -839,7 +839,7 @@ Type*
 aindex(Node *b, Type *t)
 {
        Type *r;
-       int bound;
+       int64 bound;
 
        bound = -1;     // open bound
        typecheck(&b, Erv);
@@ -1794,6 +1794,8 @@ ullmancalc(Node *n)
                ul = ur;
 
 out:
+       if(ul > 200)
+               ul = 200; // clamp to uchar with room to grow
        n->ullman = ul;
 }
 
@@ -2118,7 +2120,7 @@ localexpr(Node *n, Type *t, NodeList **init)
 void
 setmaxarg(Type *t)
 {
-       int32 w;
+       int64 w;
 
        dowidth(t);
        w = t->argwid;
@@ -3296,11 +3298,14 @@ liststmt(NodeList *l)
 int
 count(NodeList *l)
 {
-       int n;
+       vlong n;
 
        n = 0;
        for(; l; l=l->next)
                n++;
+       if((int)n != n) { // Overflow.
+               yyerror("too many elements in list");
+       }
        return n;
 }
 
index 5fba73140267973a7adf8f5973ff9ef38c5d7b84..3ad5f02a5f3944211f18d94c723be844ab7abc57 100644 (file)
@@ -358,6 +358,8 @@ mkcaselist(Node *sw, int arg)
                c = c1;
 
                ord++;
+               if((uint16)ord != ord)
+                       fatal("too many cases in switch");
                c->ordinal = ord;
                c->node = n;
 
index 938716e215d57a2acf42313759c2d272221d8347..40eecd337c1854b8af22ed3987d10ba35a5b85fa 100644 (file)
@@ -2350,7 +2350,8 @@ pushtype(Node *n, Type *t)
 static void
 typecheckcomplit(Node **np)
 {
-       int bad, i, len, nerr;
+       int bad, i, nerr;
+       int64 len;
        Node *l, *n, *norig, *r, **hash;
        NodeList *ll;
        Type *t, *f;
index 6b26cde2661d8ac499719e8ef3ec87fdc1da6776..ff08c0eef1d19c46be109ea30c3edc045da704b3 100644 (file)
@@ -19,7 +19,7 @@ unsafenmagic(Node *nn)
        Node *r, *n, *base, *r1;
        Sym *s;
        Type *t, *tr;
-       long v;
+       vlong v;
        Val val;
        Node *fn;
        NodeList *args;