1
0
mirror of https://github.com/golang/go synced 2024-11-25 12:07:56 -07:00

bug162, large indices on nil references

R=rsc
http://go/go-review/1013016
This commit is contained in:
Kai Backman 2009-10-26 21:49:32 -07:00
parent ae3c9992ae
commit 1228112b50
3 changed files with 71 additions and 14 deletions

View File

@ -702,6 +702,16 @@ agen(Node *n, Node *res)
case ODOTPTR: case ODOTPTR:
cgen(nl, res); cgen(nl, res);
if(n->xoffset != 0) { if(n->xoffset != 0) {
// explicit check for nil if struct is large enough
// that we might derive too big a pointer.
if(nl->type->type->width >= unmappedzero) {
regalloc(&n1, types[tptr], N);
gmove(res, &n1);
p1 = gins(AMOVW, &n1, &n1);
p1->from.type = D_OREG;
p1->from.offset = 0;
regfree(&n1);
}
nodconst(&n1, types[TINT32], n->xoffset); nodconst(&n1, types[TINT32], n->xoffset);
regalloc(&n2, n1.type, N); regalloc(&n2, n1.type, N);
regalloc(&n3, types[tptr], N); regalloc(&n3, types[tptr], N);

View File

@ -62,6 +62,7 @@ EXTERN Node* deferproc;
EXTERN Node* deferreturn; EXTERN Node* deferreturn;
EXTERN Node* throwindex; EXTERN Node* throwindex;
EXTERN Node* throwreturn; EXTERN Node* throwreturn;
EXTERN long unmappedzero;
EXTERN int maxstksize; EXTERN int maxstksize;
/* /*
@ -99,7 +100,7 @@ void raddr(Node *n, Prog *p);
Prog* gcmp(int, Node*, Node*); Prog* gcmp(int, Node*, Node*);
Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs); Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs);
Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs); Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
void naddr(Node*, Addr*); void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*); void cgen_aret(Node*, Node*);
/* /*

View File

@ -30,6 +30,10 @@
#include "gg.h" #include "gg.h"
// TODO(kaib): Can make this bigger if we move
// the text segment up higher in 5l for all GOOS.
long unmappedzero = 4096;
void void
clearp(Prog *p) clearp(Prog *p)
{ {
@ -863,6 +867,7 @@ gins(int as, Node *f, Node *t)
// Node nod; // Node nod;
// int32 v; // int32 v;
Prog *p; Prog *p;
Addr af, at;
if(f != N && f->op == OINDEX) { if(f != N && f->op == OINDEX) {
fatal("gins OINDEX not implemented"); fatal("gins OINDEX not implemented");
@ -883,11 +888,16 @@ gins(int as, Node *f, Node *t)
// regfree(&nod); // regfree(&nod);
} }
p = prog(as); memset(&af, 0, sizeof af);
memset(&at, 0, sizeof at);
if(f != N) if(f != N)
naddr(f, &p->from); naddr(f, &af, 1);
if(t != N) if(t != N)
naddr(t, &p->to); naddr(t, &at, 1); p = prog(as);
if(f != N)
p->from = af;
if(t != N)
p->to = at;
if(debug['g']) if(debug['g'])
print("%P\n", p); print("%P\n", p);
return p; return p;
@ -901,7 +911,7 @@ raddr(Node *n, Prog *p)
{ {
Addr a; Addr a;
naddr(n, &a); naddr(n, &a, 1);
if(a.type != D_REG && a.type != D_FREG) { if(a.type != D_REG && a.type != D_FREG) {
if(n) if(n)
fatal("bad in raddr: %O", n->op); fatal("bad in raddr: %O", n->op);
@ -958,13 +968,33 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
return p; return p;
} }
static void
checkoffset(Addr *a, int canemitcode)
{
Prog *p;
Node n1;
if(a->offset < unmappedzero)
return;
if(!canemitcode)
fatal("checkoffset %#llx, cannot emit code", a->offset);
// cannot rely on unmapped nil page at 0 to catch
// reference with large offset. instead, emit explicit
// test of 0(reg).
regalloc(&n1, types[TUINTPTR], N);
p = gins(AMOVW, N, &n1);
p->from = *a;
p->from.offset = 0;
regfree(&n1);
}
/* /*
* generate code to compute n; * generate code to compute n;
* make a refer to result. * make a refer to result.
*/ */
void void
naddr(Node *n, Addr *a) naddr(Node *n, Addr *a, int canemitcode)
{ {
a->type = D_NONE; a->type = D_NONE;
a->name = D_NONE; a->name = D_NONE;
@ -1014,6 +1044,7 @@ naddr(Node *n, Addr *a)
a->reg = n->val.u.reg; a->reg = n->val.u.reg;
a->sym = n->sym; a->sym = n->sym;
a->offset = n->xoffset; a->offset = n->xoffset;
checkoffset(a, canemitcode);
break; break;
case OPARAM: case OPARAM:
@ -1099,18 +1130,22 @@ naddr(Node *n, Addr *a)
case OLEN: case OLEN:
// len of string or slice // len of string or slice
naddr(n->left, a); naddr(n->left, a, canemitcode);
a->offset += Array_nel; a->offset += Array_nel;
if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
checkoffset(a, canemitcode);
break; break;
case OCAP: case OCAP:
// cap of string or slice // cap of string or slice
naddr(n->left, a); naddr(n->left, a, canemitcode);
a->offset += Array_cap; a->offset += Array_cap;
if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
checkoffset(a, canemitcode);
break; break;
case OADDR: case OADDR:
naddr(n->left, a); naddr(n->left, a, canemitcode);
switch(a->type) { switch(a->type) {
case D_OREG: case D_OREG:
a->type = D_CONST; a->type = D_CONST;
@ -1558,7 +1593,7 @@ lit:
reg1 = &clean[cleani-2]; reg1 = &clean[cleani-2];
reg->op = OEMPTY; reg->op = OEMPTY;
reg1->op = OEMPTY; reg1->op = OEMPTY;
naddr(n, a); naddr(n, a, 1);
goto yes; goto yes;
odot: odot:
@ -1571,7 +1606,7 @@ odot:
n1 = *nn; n1 = *nn;
n1.type = n->type; n1.type = n->type;
n1.xoffset += oary[0]; n1.xoffset += oary[0];
naddr(&n1, a); naddr(&n1, a, 1);
goto yes; goto yes;
} }
@ -1595,7 +1630,7 @@ odot:
a->type = D_NONE; a->type = D_NONE;
a->name = D_NONE; a->name = D_NONE;
naddr(&n1, a); naddr(&n1, a, 1);
goto yes; goto yes;
oindex: oindex:
@ -1669,6 +1704,17 @@ oindex:
n2.type = types[tptr]; n2.type = types[tptr];
n2.xoffset = Array_nel; n2.xoffset = Array_nel;
} else { } else {
if(l->type->width >= unmappedzero && l->op == OIND) {
// cannot rely on page protections to
// catch array ptr == 0, so dereference.
n2 = *reg;
n2.op = OINDREG;
n2.type = types[TUINTPTR];
n2.xoffset = 0;
regalloc(&n3, n2.type, N);
gins(AMOVW, &n2, &n3);
regfree(&n3);
}
nodconst(&n2, types[TUINT32], l->type->bound); nodconst(&n2, types[TUINT32], l->type->bound);
if(o & OPtrto) if(o & OPtrto)
nodconst(&n2, types[TUINT32], l->type->type->bound); nodconst(&n2, types[TUINT32], l->type->type->bound);
@ -1699,7 +1745,7 @@ oindex:
else if(*w == 8) else if(*w == 8)
gshift(AADD, reg1, SHIFT_LL, 3, reg); gshift(AADD, reg1, SHIFT_LL, 3, reg);
naddr(reg1, a); naddr(reg1, a, 1);
a->type = D_OREG; a->type = D_OREG;
a->reg = reg->val.u.reg; a->reg = reg->val.u.reg;
a->offset = 0; a->offset = 0;
@ -1763,7 +1809,7 @@ oindex_const:
n2.xoffset = v * (*w); n2.xoffset = v * (*w);
a->type = D_NONE; a->type = D_NONE;
a->name = D_NONE; a->name = D_NONE;
naddr(&n2, a); naddr(&n2, a, 1);
goto yes; goto yes;
yes: yes: