mirror of
https://github.com/golang/go
synced 2024-11-20 01:44:42 -07:00
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
This commit is contained in:
parent
e4c4edf681
commit
4dcb13bb44
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ makeclosure(Node *func)
|
||||
NodeList *l, *body;
|
||||
static int closgen;
|
||||
char *p;
|
||||
int offset;
|
||||
vlong offset;
|
||||
|
||||
/*
|
||||
* wrap body in external function
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,6 +1143,9 @@ stataddr(Node *nam, Node *n)
|
||||
l = getlit(n->right);
|
||||
if(l < 0)
|
||||
break;
|
||||
// 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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user