Commit 9dd2e1e3 authored by Russ Cox's avatar Russ Cox

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
parent 4d310f24
...@@ -403,7 +403,7 @@ void ...@@ -403,7 +403,7 @@ void
agen(Node *n, Node *res) agen(Node *n, Node *res)
{ {
Node *nl, *nr; Node *nl, *nr;
Node n1, n2, n3, tmp; Node n1, n2, n3, tmp, n4;
Prog *p1; Prog *p1;
uint32 w; uint32 w;
uint64 v; uint64 v;
...@@ -484,6 +484,18 @@ agen(Node *n, Node *res) ...@@ -484,6 +484,18 @@ agen(Node *n, Node *res)
// i is in &n1 (if not constant) // i is in &n1 (if not constant)
// w is width // 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) if(w == 0)
fatal("index is zero width"); fatal("index is zero width");
......
...@@ -1194,6 +1194,16 @@ slicearray: ...@@ -1194,6 +1194,16 @@ slicearray:
regfree(&n1); 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) // ary = old[0] + (lb[2] * width[4]) (destroys old)
n2 = *res; n2 = *res;
n2.xoffset += Array_array; n2.xoffset += Array_array;
...@@ -1215,16 +1225,6 @@ slicearray: ...@@ -1215,16 +1225,6 @@ slicearray:
} }
gins(optoas(OAS, types[tptr]), &nodes[0], &n2); 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++) { for(i=0; i<5; i++) {
if(nodes[i].op == OREGISTER) if(nodes[i].op == OREGISTER)
regfree(&nodes[i]); regfree(&nodes[i]);
......
...@@ -430,7 +430,7 @@ void ...@@ -430,7 +430,7 @@ void
agen(Node *n, Node *res) agen(Node *n, Node *res)
{ {
Node *nl, *nr; Node *nl, *nr;
Node n1, n2, n3, tmp; Node n1, n2, n3, n4, tmp;
Type *t; Type *t;
uint32 w; uint32 w;
uint64 v; uint64 v;
...@@ -516,6 +516,18 @@ agen(Node *n, Node *res) ...@@ -516,6 +516,18 @@ agen(Node *n, Node *res)
// i is in &n1 (if not constant) // i is in &n1 (if not constant)
// w is width // 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) if(w == 0)
fatal("index is zero width"); fatal("index is zero width");
...@@ -648,6 +660,17 @@ agen(Node *n, Node *res) ...@@ -648,6 +660,17 @@ agen(Node *n, Node *res)
fatal("agen: not ptr %N", n); fatal("agen: not ptr %N", n);
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], 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); nodconst(&n1, types[tptr], n->xoffset);
gins(optoas(OADD, types[tptr]), &n1, res); gins(optoas(OADD, types[tptr]), &n1, res);
} }
......
...@@ -66,6 +66,8 @@ EXTERN Node* deferreturn; ...@@ -66,6 +66,8 @@ EXTERN Node* deferreturn;
EXTERN Node* throwindex; EXTERN Node* throwindex;
EXTERN Node* throwreturn; EXTERN Node* throwreturn;
EXTERN int maxstksize; EXTERN int maxstksize;
extern uint32 unmappedzero;
/* /*
* ggen.c * ggen.c
...@@ -101,7 +103,7 @@ void sgen(Node*, Node*, int32); ...@@ -101,7 +103,7 @@ void sgen(Node*, Node*, int32);
void gmove(Node*, Node*); void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*); Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*); int samaddr(Node*, Node*);
void naddr(Node*, Addr*); void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*); void cgen_aret(Node*, Node*);
Node* ncon(uint32); Node* ncon(uint32);
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include "gg.h" #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)) #define CASE(a,b) (((a)<<16)|((b)<<0))
void void
...@@ -1629,6 +1633,7 @@ Prog* ...@@ -1629,6 +1633,7 @@ Prog*
gins(int as, Node *f, Node *t) gins(int as, Node *f, Node *t)
{ {
Prog *p; Prog *p;
Addr af, at;
if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER) if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER)
fatal("gins MOVF reg, reg"); fatal("gins MOVF reg, reg");
...@@ -1641,22 +1646,46 @@ gins(int as, Node *f, Node *t) ...@@ -1641,22 +1646,46 @@ gins(int as, Node *f, Node *t)
return nil; 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); p = prog(as);
if(f != N) if(f != N)
naddr(f, &p->from); p->from = af;
if(t != N) if(t != N)
naddr(t, &p->to); p->to = at;
if(debug['g']) if(debug['g'])
print("%P\n", p); print("%P\n", p);
return 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; * 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->scale = 0; a->scale = 0;
a->index = D_NONE; a->index = D_NONE;
...@@ -1758,7 +1787,7 @@ naddr(Node *n, Addr *a) ...@@ -1758,7 +1787,7 @@ naddr(Node *n, Addr *a)
break; break;
case OADDR: case OADDR:
naddr(n->left, a); naddr(n->left, a, canemitcode);
if(a->type >= D_INDIR) { if(a->type >= D_INDIR) {
a->type -= D_INDIR; a->type -= D_INDIR;
break; break;
...@@ -1774,24 +1803,28 @@ naddr(Node *n, Addr *a) ...@@ -1774,24 +1803,28 @@ 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_nel < unmappedzero)
checkoffset(a, canemitcode);
break; break;
// case OADD: // case OADD:
// if(n->right->op == OLITERAL) { // if(n->right->op == OLITERAL) {
// v = n->right->vconst; // v = n->right->vconst;
// naddr(n->left, a); // naddr(n->left, a, canemitcode);
// } else // } else
// if(n->left->op == OLITERAL) { // if(n->left->op == OLITERAL) {
// v = n->left->vconst; // v = n->left->vconst;
// naddr(n->right, a); // naddr(n->right, a, canemitcode);
// } else // } else
// goto bad; // goto bad;
// a->offset += v; // a->offset += v;
......
...@@ -126,7 +126,7 @@ pc: xxx ...@@ -126,7 +126,7 @@ pc: xxx
=========== nilptr/slicearray.go =========== nilptr/slicearray.go
SIGSEGV: segmentation violation SIGSEGV: segmentation violation
Faulting address: 0xa Faulting address: 0x0
pc: xxx pc: xxx
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment