1
0
mirror of https://github.com/golang/go synced 2024-11-22 06:14:39 -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:
cgen(nl, res);
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);
regalloc(&n2, n1.type, N);
regalloc(&n3, types[tptr], N);

View File

@ -62,6 +62,7 @@ EXTERN Node* deferproc;
EXTERN Node* deferreturn;
EXTERN Node* throwindex;
EXTERN Node* throwreturn;
EXTERN long unmappedzero;
EXTERN int maxstksize;
/*
@ -99,7 +100,7 @@ void raddr(Node *n, Prog *p);
Prog* gcmp(int, Node*, Node*);
Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, 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*);
/*

View File

@ -30,6 +30,10 @@
#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
clearp(Prog *p)
{
@ -863,6 +867,7 @@ gins(int as, Node *f, Node *t)
// Node nod;
// int32 v;
Prog *p;
Addr af, at;
if(f != N && f->op == OINDEX) {
fatal("gins OINDEX not implemented");
@ -883,11 +888,16 @@ gins(int as, Node *f, Node *t)
// regfree(&nod);
}
p = prog(as);
memset(&af, 0, sizeof af);
memset(&at, 0, sizeof at);
if(f != N)
naddr(f, &p->from);
naddr(f, &af, 1);
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'])
print("%P\n", p);
return p;
@ -901,7 +911,7 @@ raddr(Node *n, Prog *p)
{
Addr a;
naddr(n, &a);
naddr(n, &a, 1);
if(a.type != D_REG && a.type != D_FREG) {
if(n)
fatal("bad in raddr: %O", n->op);
@ -958,13 +968,33 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
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;
* make a refer to result.
*/
void
naddr(Node *n, Addr *a)
naddr(Node *n, Addr *a, int canemitcode)
{
a->type = D_NONE;
a->name = D_NONE;
@ -1014,6 +1044,7 @@ naddr(Node *n, Addr *a)
a->reg = n->val.u.reg;
a->sym = n->sym;
a->offset = n->xoffset;
checkoffset(a, canemitcode);
break;
case OPARAM:
@ -1099,18 +1130,22 @@ naddr(Node *n, Addr *a)
case OLEN:
// len of string or slice
naddr(n->left, a);
naddr(n->left, a, canemitcode);
a->offset += Array_nel;
if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
checkoffset(a, canemitcode);
break;
case OCAP:
// cap of string or slice
naddr(n->left, a);
naddr(n->left, a, canemitcode);
a->offset += Array_cap;
if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
checkoffset(a, canemitcode);
break;
case OADDR:
naddr(n->left, a);
naddr(n->left, a, canemitcode);
switch(a->type) {
case D_OREG:
a->type = D_CONST;
@ -1558,7 +1593,7 @@ lit:
reg1 = &clean[cleani-2];
reg->op = OEMPTY;
reg1->op = OEMPTY;
naddr(n, a);
naddr(n, a, 1);
goto yes;
odot:
@ -1571,7 +1606,7 @@ odot:
n1 = *nn;
n1.type = n->type;
n1.xoffset += oary[0];
naddr(&n1, a);
naddr(&n1, a, 1);
goto yes;
}
@ -1595,7 +1630,7 @@ odot:
a->type = D_NONE;
a->name = D_NONE;
naddr(&n1, a);
naddr(&n1, a, 1);
goto yes;
oindex:
@ -1669,6 +1704,17 @@ oindex:
n2.type = types[tptr];
n2.xoffset = Array_nel;
} 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);
if(o & OPtrto)
nodconst(&n2, types[TUINT32], l->type->type->bound);
@ -1699,7 +1745,7 @@ oindex:
else if(*w == 8)
gshift(AADD, reg1, SHIFT_LL, 3, reg);
naddr(reg1, a);
naddr(reg1, a, 1);
a->type = D_OREG;
a->reg = reg->val.u.reg;
a->offset = 0;
@ -1763,7 +1809,7 @@ oindex_const:
n2.xoffset = v * (*w);
a->type = D_NONE;
a->name = D_NONE;
naddr(&n2, a);
naddr(&n2, a, 1);
goto yes;
yes: