]> Cypherpunks repositories - gostls13.git/commitdiff
gc: zero-width struct, zero-length array fixes
authorRuss Cox <rsc@golang.org>
Wed, 27 Jul 2011 20:47:45 +0000 (16:47 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 27 Jul 2011 20:47:45 +0000 (16:47 -0400)
Fixes #1774.
Fixes #2095.
Fixes #2097.

R=ken2
CC=golang-dev
https://golang.org/cl/4826046

src/cmd/5g/cgen.c
src/cmd/5g/galign.c
src/cmd/6g/cgen.c
src/cmd/6g/galign.c
src/cmd/8g/cgen.c
src/cmd/8g/galign.c
src/cmd/gc/align.c
src/cmd/gc/go.h
src/pkg/runtime/slice.c
test/fixedbugs/bug273.go
test/fixedbugs/bug352.go [new file with mode: 0644]

index 76e2707fa905af4c24d864d00fbfcb69d1399d17..6e2fbe20ff84c112a1c1756cc2260c2f5a99159e 100644 (file)
@@ -595,9 +595,6 @@ agen(Node *n, Node *res)
                // i is in &n1 (if not constant)
                // w is width
 
-               if(w == 0)
-                       fatal("index is zero width");
-
                // constant index
                if(isconst(nr, CTINT)) {
                        if(isconst(nl, CTSTR))
@@ -683,7 +680,9 @@ agen(Node *n, Node *res)
                        gmove(&n1, &n3);
                }
 
-               if(w == 1 || w == 2 || w == 4 || w == 8) {
+               if(w == 0) {
+                       // nothing to do
+               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
                        memset(&n4, 0, sizeof n4);
                        n4.op = OADDR;
                        n4.left = &n2;
index 0fece9a08ff27f9871c6b794e1679ddb0c06829f..12766102f1e1d5c8be1751d44ca249e3a8f05b87 100644 (file)
@@ -7,6 +7,7 @@
 int    thechar = '5';
 char*  thestring       = "arm";
 
+vlong MAXWIDTH = (1LL<<32) - 1;
 
 /*
  * go declares several platform-specific type aliases:
index fca4b64dd1c48f23e85a55a32ea9a2f1ada924ca..24f88a416ed33dfd389c0421dbce35756aa50158 100644 (file)
@@ -510,9 +510,6 @@ agen(Node *n, Node *res)
                        regfree(&n4);
                }
 
-               if(w == 0)
-                       fatal("index is zero width");
-
                // constant index
                if(isconst(nr, CTINT)) {
                        if(isconst(nl, CTSTR))
@@ -600,7 +597,9 @@ agen(Node *n, Node *res)
                        gmove(&n1, &n3);
                }
 
-               if(w == 1 || w == 2 || w == 4 || w == 8) {
+               if(w == 0) {
+                       // nothing to do
+               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
                        p1 = gins(ALEAQ, &n2, &n3);
                        p1->from.scale = w;
                        p1->from.index = p1->from.type;
@@ -608,7 +607,6 @@ agen(Node *n, Node *res)
                } else {
                        ginscon(optoas(OMUL, t), w, &n2);
                        gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       gmove(&n3, res);
                }
 
        indexdone:
index 97bfb58e8894d0ea4f3cefc38b5560b44c0b9814..e366362b30fe9f4e4cdbe13f7896216ccd1a1eaf 100644 (file)
@@ -7,6 +7,7 @@
 int    thechar = '6';
 char*  thestring       = "amd64";
 
+vlong MAXWIDTH = 1LL<<50;
 
 /*
  * go declares several platform-specific type aliases:
index 1614a2d77598d12ad1b1fe86708eb94eb0b70e93..b316e6e345a58641009d77f2d652bd795509f13e 100644 (file)
@@ -562,9 +562,6 @@ agen(Node *n, Node *res)
                        regfree(&n4);
                }
 
-               if(w == 0)
-                       fatal("index is zero width");
-
                // constant index
                if(isconst(nr, CTINT)) {
                        if(isconst(nl, CTSTR))
@@ -639,7 +636,9 @@ agen(Node *n, Node *res)
                        gmove(&n1, &n3);
                }
 
-               if(w == 1 || w == 2 || w == 4 || w == 8) {
+               if(w == 0) {
+                       // nothing to do
+               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
                        p1 = gins(ALEAL, &n2, &n3);
                        p1->from.scale = w;
                        p1->from.index = p1->from.type;
@@ -648,7 +647,6 @@ agen(Node *n, Node *res)
                        nodconst(&n1, types[TUINT32], w);
                        gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
                        gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       gmove(&n3, res);
                }
 
        indexdone:
index 48edfdf3cc124c1b45994285b460874230c21695..7734603c4b0044b462ec69843f4cc60671bb44da 100644 (file)
@@ -7,6 +7,7 @@
 int    thechar = '8';
 char*  thestring       = "386";
 
+vlong MAXWIDTH = (1LL<<32) - 1;
 
 /*
  * go declares several platform-specific type aliases:
index 6bb93ef1791c4e8364dc68cd30acc38ae8d8a437..14c1c4a8d2d852ba264a198c850d56597283782f 100644 (file)
@@ -30,14 +30,18 @@ offmod(Type *t)
        o = 0;
        for(f=t->type; f!=T; f=f->down) {
                if(f->etype != TFIELD)
-                       fatal("widstruct: not TFIELD: %lT", f);
+                       fatal("offmod: not TFIELD: %lT", f);
                f->width = o;
                o += widthptr;
+               if(o >= MAXWIDTH) {
+                       yyerror("interface too large");
+                       o = widthptr;
+               }
        }
 }
 
-static uint32
-widstruct(Type *t, uint32 o, int flag)
+static vlong
+widstruct(Type *errtype, Type *t, vlong o, int flag)
 {
        Type *f;
        int32 w, maxalign;
@@ -69,6 +73,10 @@ widstruct(Type *t, uint32 o, int flag)
                                f->nname->xoffset = o;
                }
                o += w;
+               if(o >= MAXWIDTH) {
+                       yyerror("type %lT too large", errtype);
+                       o = 8;  // small but nonzero
+               }
        }
        // final width is rounded
        if(flag)
@@ -226,10 +234,7 @@ dowidth(Type *t)
 
                        dowidth(t->type);
                        if(t->type->width != 0) {
-                               if(tptr == TPTR32)
-                                       cap = ((uint32)-1) / t->type->width;
-                               else
-                                       cap = ((uint64)-1) / t->type->width;
+                               cap = (MAXWIDTH-1) / t->type->width;
                                if(t->bound > cap)
                                        yyerror("type %lT larger than address space", t);
                        }
@@ -250,7 +255,7 @@ dowidth(Type *t)
        case TSTRUCT:
                if(t->funarg)
                        fatal("dowidth fn struct %T", t);
-               w = widstruct(t, 0, 1);
+               w = widstruct(t, t, 0, 1);
                break;
 
        case TFUNC:
@@ -268,9 +273,9 @@ dowidth(Type *t)
                // function is 3 cated structures;
                // compute their widths as side-effect.
                t1 = t->type;
-               w = widstruct(*getthis(t1), 0, 0);
-               w = widstruct(*getinarg(t1), w, widthptr);
-               w = widstruct(*getoutarg(t1), w, widthptr);
+               w = widstruct(t->type, *getthis(t1), 0, 0);
+               w = widstruct(t->type, *getinarg(t1), w, widthptr);
+               w = widstruct(t->type, *getoutarg(t1), w, widthptr);
                t1->argwid = w;
                if(w%widthptr)
                        warn("bad type %T %d\n", t1, w);
index dfc5887a5c59bb7a2d464e1e5c91a4cf2ef79a3f..604a1261b8240054e9af7510f1e2a8a14d5b5116 100644 (file)
@@ -43,9 +43,10 @@ enum
        AMEMWORD,
 
        BADWIDTH        = -1000000000,
-       MAXWIDTH        = 1<<30
 };
 
+extern vlong   MAXWIDTH;
+
 /*
  * note this is the representation
  * of the compilers string literals,
index 9146c177f2c2851ae662bb56d44c1e62674a0ba5..70534279b5a8c5b1465f0c9e809952e845d07f8f 100644 (file)
@@ -20,7 +20,7 @@ runtimeĀ·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
 {
        if(len < 0 || (int32)len != len)
                runtimeĀ·panicstring("makeslice: len out of range");
-       if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
+       if(cap < len || (int32)cap != cap || t->elem->size > 0 && cap > ((uintptr)-1) / t->elem->size)
                runtimeĀ·panicstring("makeslice: cap out of range");
 
        makeslice1(t, len, cap, &ret);
index 816f69e8f13a1c7e7b5ada9f24f56bca5e138c29..dd5aaa7b8af31ac57605aad1db6aeb3d88c82359 100644 (file)
@@ -47,15 +47,6 @@ func bigcap() {
        g1 = make([]int, 10, big)
 }
 
-const (
-       addrBits = 8*uint(unsafe.Sizeof((*byte)(nil)))
-       sh = addrBits/2 - 2
-)
-var g2 [][1<<sh][1<<sh]byte
-func overflow() {
-       g2 = make([][1<<sh][1<<sh]byte, 64)
-}
-
 var g3 map[int]int
 func badmapcap() {
        g3 = make(map[int]int, minus1)
@@ -74,6 +65,8 @@ func bigchancap() {
        g4 = make(chan int, big)
 }
 
+const addrBits = unsafe.Sizeof((*byte)(nil))
+
 var g5 chan [1<<15]byte
 func overflowchan() {
        if addrBits == 32 {
@@ -92,7 +85,6 @@ func main() {
        shouldfail(badcap, "badcap")
        shouldfail(badcap1, "badcap1")
        shouldfail(bigcap, "bigcap")
-       shouldfail(overflow, "overflow")
        shouldfail(badmapcap, "badmapcap")
        shouldfail(bigmapcap, "bigmapcap")
        shouldfail(badchancap, "badchancap")
diff --git a/test/fixedbugs/bug352.go b/test/fixedbugs/bug352.go
new file mode 100644 (file)
index 0000000..62fd006
--- /dev/null
@@ -0,0 +1,19 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug352
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var x [10][0]byte
+var y = make([]struct{}, 10)
+
+func main() {
+       if &x[1] != &x[2] {
+               println("BUG: bug352 [0]byte")
+       }
+       if &y[1] != &y[2] {
+               println("BUG: bug352 struct{}")
+       }
+}