Commit 4dcb13bb authored by Rob Pike's avatar Rob Pike

cmd/gc: fix some overflows in the compiler

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