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:
parent
ae3c9992ae
commit
1228112b50
@ -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);
|
||||||
|
@ -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*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user