]> Cypherpunks repositories - gostls13.git/commitdiff
gc: be pickier about slice, chan, array, and map sizes
authorRuss Cox <rsc@golang.org>
Sat, 1 May 2010 20:15:42 +0000 (13:15 -0700)
committerRuss Cox <rsc@golang.org>
Sat, 1 May 2010 20:15:42 +0000 (13:15 -0700)
Fixes #589.

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

src/cmd/gc/align.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/runtime.go
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c
src/pkg/runtime/chan.c
src/pkg/runtime/hashmap.c
src/pkg/runtime/runtime.h
src/pkg/runtime/slice.c
test/fixedbugs/bug273.go [new file with mode: 0644]

index c4facf1be01e0aeeab20f090be62a428bdc4408e..460358df18ad3ecb360f276e87660e4a81d53bf3 100644 (file)
@@ -96,7 +96,7 @@ void
 dowidth(Type *t)
 {
        int32 et;
-       uint32 w;
+       int64 w;
        int lno;
        Type *t1;
 
@@ -222,7 +222,15 @@ dowidth(Type *t)
                if(t->type == T)
                        break;
                if(t->bound >= 0) {
+                       uint64 cap;
+
                        dowidth(t->type);
+                       if(tptr == TPTR32)
+                               cap = ((uint32)-1) / t->type->width;
+                       else
+                               cap = ((uint64)-1) / t->type->width;
+                       if(t->bound > cap)
+                               yyerror("type %lT larger than address space", t);
                        w = t->bound * t->type->width;
                        if(w == 0)
                                w = maxround;
index 94efa412bf4c4f5bc3e054d4a159d64dadacca91..1e7a14947b6f3ba1961ae866dddf780faf752356 100644 (file)
@@ -33,47 +33,47 @@ char *runtimeimport =
        "func \"\".stringiter (? string, ? int) int\n"
        "func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
        "func \"\".slicecopy (to any, fr any, wid uint32) int\n"
-       "func \"\".ifaceI2E (iface any) (ret any)\n"
-       "func \"\".ifaceE2I (typ *uint8, iface any) (ret any)\n"
-       "func \"\".ifaceT2E (typ *uint8, elem any) (ret any)\n"
-       "func \"\".ifaceE2T (typ *uint8, elem any) (ret any)\n"
+       "func \"\".ifaceI2E (iface any) any\n"
+       "func \"\".ifaceE2I (typ *uint8, iface any) any\n"
+       "func \"\".ifaceT2E (typ *uint8, elem any) any\n"
+       "func \"\".ifaceE2T (typ *uint8, elem any) any\n"
        "func \"\".ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
        "func \"\".ifaceE2T2 (typ *uint8, elem any) (ret any, ok bool)\n"
-       "func \"\".ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) (ret any)\n"
-       "func \"\".ifaceI2T (typ *uint8, iface any) (ret any)\n"
+       "func \"\".ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) any\n"
+       "func \"\".ifaceI2T (typ *uint8, iface any) any\n"
        "func \"\".ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
-       "func \"\".ifaceI2I (typ *uint8, iface any) (ret any)\n"
-       "func \"\".ifaceI2Ix (typ *uint8, iface any) (ret any)\n"
+       "func \"\".ifaceI2I (typ *uint8, iface any) any\n"
+       "func \"\".ifaceI2Ix (typ *uint8, iface any) any\n"
        "func \"\".ifaceI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
-       "func \"\".ifaceeq (i1 any, i2 any) (ret bool)\n"
-       "func \"\".efaceeq (i1 any, i2 any) (ret bool)\n"
-       "func \"\".ifacethash (i1 any) (ret uint32)\n"
-       "func \"\".efacethash (i1 any) (ret uint32)\n"
-       "func \"\".makemap (key *uint8, val *uint8, hint int) (hmap map[any] any)\n"
-       "func \"\".mapaccess1 (hmap map[any] any, key any) (val any)\n"
+       "func \"\".ifaceeq (i1 any, i2 any) bool\n"
+       "func \"\".efaceeq (i1 any, i2 any) bool\n"
+       "func \"\".ifacethash (i1 any) uint32\n"
+       "func \"\".efacethash (i1 any) uint32\n"
+       "func \"\".makemap (key *uint8, val *uint8, hint int64) map[any] any\n"
+       "func \"\".mapaccess1 (hmap map[any] any, key any) any\n"
        "func \"\".mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n"
        "func \"\".mapassign1 (hmap map[any] any, key any, val any)\n"
        "func \"\".mapassign2 (hmap map[any] any, key any, val any, pres bool)\n"
        "func \"\".mapiterinit (hmap map[any] any, hiter *any)\n"
        "func \"\".mapiternext (hiter *any)\n"
-       "func \"\".mapiter1 (hiter *any) (key any)\n"
+       "func \"\".mapiter1 (hiter *any) any\n"
        "func \"\".mapiter2 (hiter *any) (key any, val any)\n"
-       "func \"\".makechan (elem *uint8, hint int) (hchan chan any)\n"
-       "func \"\".chanrecv1 (hchan <-chan any) (elem any)\n"
+       "func \"\".makechan (elem *uint8, hint int64) chan any\n"
+       "func \"\".chanrecv1 (hchan <-chan any) any\n"
        "func \"\".chanrecv2 (hchan <-chan any) (elem any, pres bool)\n"
        "func \"\".chansend1 (hchan chan<- any, elem any)\n"
-       "func \"\".chansend2 (hchan chan<- any, elem any) (pres bool)\n"
+       "func \"\".chansend2 (hchan chan<- any, elem any) bool\n"
        "func \"\".closechan (hchan any)\n"
        "func \"\".closedchan (hchan any) bool\n"
-       "func \"\".newselect (size int) (sel *uint8)\n"
-       "func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) (selected bool)\n"
-       "func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) (selected bool)\n"
-       "func \"\".selectdefault (sel *uint8) (selected bool)\n"
+       "func \"\".newselect (size int) *uint8\n"
+       "func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) bool\n"
+       "func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
+       "func \"\".selectdefault (sel *uint8) bool\n"
        "func \"\".selectgo (sel *uint8)\n"
-       "func \"\".makeslice (typ *uint8, nel int, cap int) (ary []any)\n"
-       "func \"\".sliceslice1 (old []any, lb int, width int) (ary []any)\n"
-       "func \"\".sliceslice (old []any, lb int, hb int, width int) (ary []any)\n"
-       "func \"\".slicearray (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
+       "func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
+       "func \"\".sliceslice1 (old []any, lb int, width int) []any\n"
+       "func \"\".sliceslice (old []any, lb int, hb int, width int) []any\n"
+       "func \"\".slicearray (old *any, nel int, lb int, hb int, width int) []any\n"
        "func \"\".closure ()\n"
        "func \"\".int64div (? int64, ? int64) int64\n"
        "func \"\".uint64div (? uint64, ? uint64) uint64\n"
@@ -81,7 +81,7 @@ char *runtimeimport =
        "func \"\".uint64mod (? uint64, ? uint64) uint64\n"
        "func \"\".float64toint64 (? float64) int64\n"
        "func \"\".int64tofloat64 (? int64) float64\n"
-       "func \"\".complex128div (num complex128, den complex128) (quo complex128)\n"
+       "func \"\".complex128div (num complex128, den complex128) complex128\n"
        "\n"
        "$$\n";
 char *unsafeimport =
@@ -90,9 +90,9 @@ char *unsafeimport =
        "func \"\".Offsetof (? any) int\n"
        "func \"\".Sizeof (? any) int\n"
        "func \"\".Alignof (? any) int\n"
-       "func \"\".Typeof (i interface { }) (typ interface { })\n"
+       "func \"\".Typeof (i interface { }) interface { }\n"
        "func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n"
-       "func \"\".Unreflect (typ interface { }, addr \"\".Pointer) (ret interface { })\n"
+       "func \"\".Unreflect (typ interface { }, addr \"\".Pointer) interface { }\n"
        "func \"\".New (typ interface { }) \"\".Pointer\n"
        "func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n"
        "\n"
index e08e1f601743f37ced5a69570c5a5c5cdb900bfb..392de17a00ac99cbea0276359ded0b27c8a613a4 100644 (file)
@@ -65,7 +65,7 @@ func ifacethash(i1 any) (ret uint32)
 func efacethash(i1 any) (ret uint32)
 
 // *byte is really *runtime.Type
-func makemap(key, val *byte, hint int) (hmap map[any]any)
+func makemap(key, val *byte, hint int64) (hmap map[any]any)
 func mapaccess1(hmap map[any]any, key any) (val any)
 func mapaccess2(hmap map[any]any, key any) (val any, pres bool)
 func mapassign1(hmap map[any]any, key any, val any)
@@ -76,7 +76,7 @@ func mapiter1(hiter *any) (key any)
 func mapiter2(hiter *any) (key any, val any)
 
 // *byte is really *runtime.Type
-func makechan(elem *byte, hint int) (hchan chan any)
+func makechan(elem *byte, hint int64) (hchan chan any)
 func chanrecv1(hchan <-chan any) (elem any)
 func chanrecv2(hchan <-chan any) (elem any, pres bool)
 func chansend1(hchan chan<- any, elem any)
@@ -90,7 +90,7 @@ func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
 func selectdefault(sel *byte) (selected bool)
 func selectgo(sel *byte)
 
-func makeslice(typ *byte, nel int, cap int) (ary []any)
+func makeslice(typ *byte, nel int64, cap int64) (ary []any)
 func sliceslice1(old []any, lb int, width int) (ary []any)
 func sliceslice(old []any, lb int, hb int, width int) (ary []any)
 func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
index ae1d13d17a57c5dd9fed6e426ca343b842d80250..707546b1095082dd9c409cd22ddd2ed7109bf94a 100644 (file)
@@ -929,13 +929,13 @@ reswitch:
                        l = args->n;
                        args = args->next;
                        typecheck(&l, Erv);
-                       defaultlit(&l, types[TUINT]);
+                       defaultlit(&l, types[TINT]);
                        r = N;
                        if(args != nil) {
                                r = args->n;
                                args = args->next;
                                typecheck(&r, Erv);
-                               defaultlit(&r, types[TUINT]);
+                               defaultlit(&r, types[TINT]);
                        }
                        if(l->type == T || (r && r->type == T))
                                goto error;
@@ -947,8 +947,6 @@ reswitch:
                                yyerror("non-integer cap argument to make(%T)", t);
                                goto error;
                        }
-                       if(r == N)
-                               r = nodintconst(0);
                        n->left = l;
                        n->right = r;
                        n->op = OMAKESLICE;
@@ -959,7 +957,7 @@ reswitch:
                                l = args->n;
                                args = args->next;
                                typecheck(&l, Erv);
-                               defaultlit(&l, types[TUINT]);
+                               defaultlit(&l, types[TINT]);
                                if(l->type == T)
                                        goto error;
                                if(!isint[l->type->etype]) {
@@ -978,7 +976,7 @@ reswitch:
                                l = args->n;
                                args = args->next;
                                typecheck(&l, Erv);
-                               defaultlit(&l, types[TUINT]);
+                               defaultlit(&l, types[TINT]);
                                if(l->type == T)
                                        goto error;
                                if(!isint[l->type->etype]) {
index 951496e604f0e82a24d01e83a02b69bc31df6d57..a79c75131f0ac39f355860d788f0a62ed67a60cd 100644 (file)
@@ -1138,7 +1138,7 @@ walkexpr(Node **np, NodeList **init)
        case OMAKECHAN:
                n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
                        typename(n->type->type),
-                       conv(n->left, types[TINT]));
+                       conv(n->left, types[TINT64]));
                goto ret;
 
        case OMAKEMAP:
@@ -1151,18 +1151,22 @@ walkexpr(Node **np, NodeList **init)
                n = mkcall1(fn, n->type, init,
                        typename(t->down),      // key type
                        typename(t->type),              // value type
-                       conv(n->left, types[TINT]));
+                       conv(n->left, types[TINT64]));
                goto ret;
 
        case OMAKESLICE:
-               // makeslice(nel int, max int, width int) (ary []any)
+               // makeslice(t *Type, nel int64, max int64) (ary []any)
+               l = n->left;
+               r = n->right;
+               if(r == nil)
+                       l = r = safeexpr(l, init);
                t = n->type;
                fn = syslook("makeslice", 1);
                argtype(fn, t->type);                   // any-1
                n = mkcall1(fn, n->type, init,
                        typename(n->type),
-                       conv(n->left, types[TINT]),
-                       conv(n->right, types[TINT]));
+                       conv(l, types[TINT64]),
+                       conv(r, types[TINT64]));
                goto ret;
 
        case ORUNESTR:
index 5793159062435166058b9255a56f9eb89e72f117..08cd75a6e53971e111edff93910d3c20ef7d33d7 100644 (file)
@@ -90,11 +90,14 @@ static      uint32  fastrand2(void);
 static void    destroychan(Hchan*);
 
 Hchan*
-makechan(Type *elem, uint32 hint)
+makechan(Type *elem, int64 hint)
 {
        Hchan *c;
        int32 i;
 
+       if(hint < 0 || (int32)hint != hint || hint > ((uintptr)-1) / elem->size)
+               panicstring("makechan: size out of range");
+
        if(elem->alg >= nelem(algarray)) {
                printf("chan(alg=%d)\n", elem->alg);
                throw("runtime.makechan: unsupported elem type");
@@ -141,9 +144,9 @@ destroychan(Hchan *c)
 }
 
 
-// makechan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
+// makechan(elem *Type, hint int64) (hchan *chan any);
 void
-·makechan(Type *elem, uint32 hint, Hchan *ret)
+·makechan(Type *elem, int64 hint, Hchan *ret)
 {
        ret = makechan(elem, hint);
        FLUSH(&ret);
index f27264b6826b21a10305f7b973b4492c5571b3e3..9b039121bb14e767ddc5d63b676164edda361799 100644 (file)
@@ -667,11 +667,14 @@ static    int32   debug   = 0;
 
 // makemap(key, val *Type, hint uint32) (hmap *map[any]any);
 Hmap*
-makemap(Type *key, Type *val, uint32 hint)
+makemap(Type *key, Type *val, int64 hint)
 {
        Hmap *h;
        int32 keyalg, valalg, keysize, valsize;
 
+       if(hint < 0 || (int32)hint != hint)
+               panicstring("makemap: size out of range");
+
        keyalg = key->alg;
        valalg = val->alg;
        keysize = key->size;
@@ -731,9 +734,9 @@ makemap(Type *key, Type *val, uint32 hint)
        return h;
 }
 
-// makemap(key, val *Type, hint uint32) (hmap *map[any]any);
+// makemap(key, val *Type, hint int64) (hmap *map[any]any);
 void
-·makemap(Type *key, Type *val, uint32 hint, Hmap *ret)
+·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
 {
        ret = makemap(key, val, hint);
        FLUSH(&ret);
index ff4f463b37cf28518d8db8f1f581f3a8f06ddcb3..4c9f52e85c0ce9d27dc89d90cf6ca5044e5c505b 100644 (file)
@@ -577,9 +577,9 @@ struct hash_iter*   mapiterinit(Hmap*);
 void   mapiternext(struct hash_iter*);
 bool   mapiterkey(struct hash_iter*, void*);
 void   mapiterkeyvalue(struct hash_iter*, void*, void*);
-Hmap*  makemap(Type*, Type*, uint32);
+Hmap*  makemap(Type*, Type*, int64);
 
-Hchan* makechan(Type*, uint32);
+Hchan* makechan(Type*, int64);
 void   chansend(Hchan*, void*, bool*);
 void   chanrecv(Hchan*, void*, bool*);
 void   chanclose(Hchan*);
index c3c079c670a6623693650ae0bcbab3039853c409..d967b1669b9460480b5a99e137f051bc8d1a5ffe 100644 (file)
@@ -9,17 +9,20 @@
 static int32   debug   = 0;
 
 // see also unsafe·NewArray
-// makeslice(typ *Type, nel int, cap int) (ary []any);
+// makeslice(typ *Type, len, cap int64) (ary []any);
 void
-·makeslice(SliceType *t, uint32 nel, uint32 cap, Slice ret)
+·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
 {
-       uint64 size;
+       uintptr size;
+
+       if(len < 0 || (int32)len != len)
+               panicstring("makeslice: len out of range");
+       if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
+               panicstring("makeslice: cap out of range");
 
-       if(cap < nel)
-               cap = nel;
        size = cap*t->elem->size;
 
-       ret.len = nel;
+       ret.len = len;
        ret.cap = cap;
 
        if((t->elem->kind&KindNoPointers))
@@ -30,8 +33,8 @@ void
        FLUSH(&ret);
 
        if(debug) {
-               printf("makeslice(%S, %d, %d); ret=",
-                       *t->string, nel, cap);
+               printf("makeslice(%S, %D, %D); ret=",
+                       *t->string, len, cap);
                ·printslice(ret);
        }
 }
diff --git a/test/fixedbugs/bug273.go b/test/fixedbugs/bug273.go
new file mode 100644 (file)
index 0000000..ff8f1c6
--- /dev/null
@@ -0,0 +1,95 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 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.
+
+// http://code.google.com/p/go/issues/detail?id=589
+
+package main
+
+import "unsafe"
+
+var bug = false
+
+var minus1 = -1
+var big int64 = 10 | 1<<32
+
+func shouldfail(f func(), desc string) {
+       defer func() { recover() }()
+       f()
+       if !bug {
+               println("BUG")
+               bug = true
+       }
+       println("didn't crash: ", desc)
+}
+
+func badlen() {
+       _ = make([]int, minus1)
+}
+
+func biglen() {
+       _ = make([]int, big)
+}
+
+func badcap() {
+       _ = make([]int, 10, minus1)
+}
+
+func badcap1() {
+       _ = make([]int, 10, 5)
+}
+
+func bigcap() {
+       _ = make([]int, 10, big)
+}
+
+const (
+       addrBits = 8*uint(unsafe.Sizeof((*byte)(nil)))
+       sh = addrBits/2 - 2
+)
+func overflow() {
+       _ = make([][1<<sh][1<<sh]byte, 64)
+}
+
+func badmapcap() {
+       _ = make(map[int]int, minus1)
+}
+
+func bigmapcap() {
+       _ = make(map[int]int, big)
+}
+
+func badchancap() {
+       _ = make(chan int, minus1)
+}
+
+func bigchancap() {
+       _ = make(chan int, big)
+}
+
+func overflowchan() {
+       if addrBits == 32 {
+               _ = make(chan [1<<15]byte, 1<<20)
+       } else {
+               // cannot overflow on 64-bit, because
+               // int is 32 bits and max chan value size
+               // in the implementation is 64 kB.
+               panic(1)
+       }
+}
+
+func main() {
+       shouldfail(badlen, "badlen")
+       shouldfail(biglen, "biglen")
+       shouldfail(badcap, "badcap")
+       shouldfail(badcap1, "badcap1")
+       shouldfail(bigcap, "bigcap")
+       shouldfail(overflow, "overflow")
+       shouldfail(badmapcap, "badmapcap")
+       shouldfail(bigmapcap, "bigmapcap")
+       shouldfail(badchancap, "badchancap")
+       shouldfail(bigchancap, "bigchancap")
+       shouldfail(overflowchan, "overflowchan")
+}