mirror of
https://github.com/golang/go
synced 2024-11-12 01:10:21 -07:00
nil pointer checks in 8g.
fix nil pointer check in 6g. was dereferencing after the ADD; dereference before instead. R=ken@golang.org CC=iant http://go/go-review/1016022
This commit is contained in:
parent
4d310f2434
commit
9dd2e1e30f
@ -403,7 +403,7 @@ void
|
||||
agen(Node *n, Node *res)
|
||||
{
|
||||
Node *nl, *nr;
|
||||
Node n1, n2, n3, tmp;
|
||||
Node n1, n2, n3, tmp, n4;
|
||||
Prog *p1;
|
||||
uint32 w;
|
||||
uint64 v;
|
||||
@ -484,6 +484,18 @@ agen(Node *n, Node *res)
|
||||
// i is in &n1 (if not constant)
|
||||
// w is width
|
||||
|
||||
// explicit check for nil if array is large enough
|
||||
// that we might derive too big a pointer.
|
||||
if(!isslice(nl->type) && nl->type->width >= unmappedzero) {
|
||||
regalloc(&n4, types[tptr], &n3);
|
||||
gmove(&n3, &n4);
|
||||
n4.op = OINDREG;
|
||||
n4.type = types[TUINT8];
|
||||
n4.xoffset = 0;
|
||||
gins(ATESTB, nodintconst(0), &n4);
|
||||
regfree(&n4);
|
||||
}
|
||||
|
||||
if(w == 0)
|
||||
fatal("index is zero width");
|
||||
|
||||
|
@ -1194,6 +1194,16 @@ slicearray:
|
||||
regfree(&n1);
|
||||
}
|
||||
|
||||
// if slice could be too big, dereference to
|
||||
// catch nil array pointer.
|
||||
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||
n2 = nodes[0];
|
||||
n2.xoffset = 0;
|
||||
n2.op = OINDREG;
|
||||
n2.type = types[TUINT8];
|
||||
gins(ATESTB, nodintconst(0), &n2);
|
||||
}
|
||||
|
||||
// ary = old[0] + (lb[2] * width[4]) (destroys old)
|
||||
n2 = *res;
|
||||
n2.xoffset += Array_array;
|
||||
@ -1215,16 +1225,6 @@ slicearray:
|
||||
}
|
||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
||||
|
||||
// if slice could be too big, dereference to
|
||||
// catch nil array pointer.
|
||||
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||
n2 = nodes[0];
|
||||
n2.xoffset = 0;
|
||||
n2.op = OINDREG;
|
||||
n2.type = types[TUINT8];
|
||||
gins(ATESTB, nodintconst(0), &n2);
|
||||
}
|
||||
|
||||
for(i=0; i<5; i++) {
|
||||
if(nodes[i].op == OREGISTER)
|
||||
regfree(&nodes[i]);
|
||||
|
@ -430,7 +430,7 @@ void
|
||||
agen(Node *n, Node *res)
|
||||
{
|
||||
Node *nl, *nr;
|
||||
Node n1, n2, n3, tmp;
|
||||
Node n1, n2, n3, n4, tmp;
|
||||
Type *t;
|
||||
uint32 w;
|
||||
uint64 v;
|
||||
@ -516,6 +516,18 @@ agen(Node *n, Node *res)
|
||||
// i is in &n1 (if not constant)
|
||||
// w is width
|
||||
|
||||
// explicit check for nil if array is large enough
|
||||
// that we might derive too big a pointer.
|
||||
if(!isslice(nl->type) && nl->type->width >= unmappedzero) {
|
||||
regalloc(&n4, types[tptr], &n3);
|
||||
gmove(&n3, &n4);
|
||||
n4.op = OINDREG;
|
||||
n4.type = types[TUINT8];
|
||||
n4.xoffset = 0;
|
||||
gins(ATESTB, nodintconst(0), &n4);
|
||||
regfree(&n4);
|
||||
}
|
||||
|
||||
if(w == 0)
|
||||
fatal("index is zero width");
|
||||
|
||||
@ -648,6 +660,17 @@ agen(Node *n, Node *res)
|
||||
fatal("agen: not ptr %N", n);
|
||||
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], res);
|
||||
gmove(res, &n1);
|
||||
n1.op = OINDREG;
|
||||
n1.type = types[TUINT8];
|
||||
n1.xoffset = 0;
|
||||
gins(ATESTB, nodintconst(0), &n1);
|
||||
regfree(&n1);
|
||||
}
|
||||
nodconst(&n1, types[tptr], n->xoffset);
|
||||
gins(optoas(OADD, types[tptr]), &n1, res);
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ EXTERN Node* deferreturn;
|
||||
EXTERN Node* throwindex;
|
||||
EXTERN Node* throwreturn;
|
||||
EXTERN int maxstksize;
|
||||
extern uint32 unmappedzero;
|
||||
|
||||
|
||||
/*
|
||||
* ggen.c
|
||||
@ -101,7 +103,7 @@ void sgen(Node*, Node*, int32);
|
||||
void gmove(Node*, Node*);
|
||||
Prog* gins(int, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void naddr(Node*, Addr*);
|
||||
void naddr(Node*, Addr*, int);
|
||||
void cgen_aret(Node*, Node*);
|
||||
Node* ncon(uint32);
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
// TODO(rsc): Can make this bigger if we move
|
||||
// the text segment up higher in 8l for all GOOS.
|
||||
uint32 unmappedzero = 4096;
|
||||
|
||||
#define CASE(a,b) (((a)<<16)|((b)<<0))
|
||||
|
||||
void
|
||||
@ -1629,6 +1633,7 @@ Prog*
|
||||
gins(int as, Node *f, Node *t)
|
||||
{
|
||||
Prog *p;
|
||||
Addr af, at;
|
||||
|
||||
if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER)
|
||||
fatal("gins MOVF reg, reg");
|
||||
@ -1641,22 +1646,46 @@ gins(int as, Node *f, Node *t)
|
||||
return nil;
|
||||
}
|
||||
|
||||
memset(&af, 0, sizeof af);
|
||||
memset(&at, 0, sizeof at);
|
||||
if(f != N)
|
||||
naddr(f, &af, 1);
|
||||
if(t != N)
|
||||
naddr(t, &at, 1);
|
||||
p = prog(as);
|
||||
if(f != N)
|
||||
naddr(f, &p->from);
|
||||
p->from = af;
|
||||
if(t != N)
|
||||
naddr(t, &p->to);
|
||||
p->to = at;
|
||||
if(debug['g'])
|
||||
print("%P\n", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
checkoffset(Addr *a, int canemitcode)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
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).
|
||||
p = gins(ATESTB, nodintconst(0), N);
|
||||
p->to = *a;
|
||||
p->to.offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* generate code to compute n;
|
||||
* make a refer to result.
|
||||
*/
|
||||
void
|
||||
naddr(Node *n, Addr *a)
|
||||
naddr(Node *n, Addr *a, int canemitcode)
|
||||
{
|
||||
a->scale = 0;
|
||||
a->index = D_NONE;
|
||||
@ -1758,7 +1787,7 @@ naddr(Node *n, Addr *a)
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
naddr(n->left, a);
|
||||
naddr(n->left, a, canemitcode);
|
||||
if(a->type >= D_INDIR) {
|
||||
a->type -= D_INDIR;
|
||||
break;
|
||||
@ -1774,24 +1803,28 @@ 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_nel < unmappedzero)
|
||||
checkoffset(a, canemitcode);
|
||||
break;
|
||||
|
||||
// case OADD:
|
||||
// if(n->right->op == OLITERAL) {
|
||||
// v = n->right->vconst;
|
||||
// naddr(n->left, a);
|
||||
// naddr(n->left, a, canemitcode);
|
||||
// } else
|
||||
// if(n->left->op == OLITERAL) {
|
||||
// v = n->left->vconst;
|
||||
// naddr(n->right, a);
|
||||
// naddr(n->right, a, canemitcode);
|
||||
// } else
|
||||
// goto bad;
|
||||
// a->offset += v;
|
||||
|
@ -126,7 +126,7 @@ pc: xxx
|
||||
|
||||
=========== nilptr/slicearray.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0xa
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user