]> Cypherpunks repositories - gostls13.git/commitdiff
nil pointer checks in 8g.
authorRuss Cox <rsc@golang.org>
Mon, 2 Nov 2009 05:04:16 +0000 (21:04 -0800)
committerRuss Cox <rsc@golang.org>
Mon, 2 Nov 2009 05:04:16 +0000 (21:04 -0800)
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

src/cmd/6g/cgen.c
src/cmd/6g/ggen.c
src/cmd/8g/cgen.c
src/cmd/8g/gg.h
src/cmd/8g/gsubr.c
test/golden.out

index 1986e56065844bf550b31db759bb0988f3aa5fa0..2ee7934908e2d0586676bd2487ae823dcaa1ee29 100644 (file)
@@ -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");
 
index a920ae9f08d868de7bab2a911ce27c131d115be1..5c0a22114f89ff50fc529883c9daa87819e15255 100644 (file)
@@ -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]);
index a3e877621dfa9b3c56660b6cbf368e6d86fb3169..bf0b263b6182b167e6203332ae1881a981aa48df 100644 (file)
@@ -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);
                }
index a3f09000986a2894fa0f79411273ca4995d12ae7..447162c7bc48d13708aa0a2760f245b8669c3acf 100644 (file)
@@ -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);
 
index f051596641265d52e16fa12d5eb3390b8817d850..953b755c1a8b2ef62578077c6da9e461bcb83e2f 100755 (executable)
 
 #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;
index 8ace9fdfa0ac365dbba8eee0d1e945fdb9b5fb0d..d23369b6ef4dd2d1c4b82ca650f345099167f45b 100644 (file)
@@ -126,7 +126,7 @@ pc: xxx
 
 =========== nilptr/slicearray.go
 SIGSEGV: segmentation violation
-Faulting address: 0xa
+Faulting address: 0x0
 pc: xxx