aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-05-01 13:15:42 -0700
committerRuss Cox <rsc@golang.org>2010-05-01 13:15:42 -0700
commit6361f52fc4ae682e3dae3264cee1f45876272c54 (patch)
treea65064ae7640c7a8164bf962f33c61998068ed4a
parent97576673bd22ab77e9ca9f9bea27f91a895ca4a2 (diff)
downloadgo-6361f52fc4ae682e3dae3264cee1f45876272c54.tar.gz
go-6361f52fc4ae682e3dae3264cee1f45876272c54.zip
gc: be pickier about slice, chan, array, and map sizes
Fixes #589. R=ken2 CC=golang-dev https://golang.org/cl/1032044
-rw-r--r--src/cmd/gc/align.c10
-rw-r--r--src/cmd/gc/builtin.c.boot58
-rw-r--r--src/cmd/gc/runtime.go6
-rw-r--r--src/cmd/gc/typecheck.c10
-rw-r--r--src/cmd/gc/walk.c14
-rw-r--r--src/pkg/runtime/chan.c9
-rw-r--r--src/pkg/runtime/hashmap.c9
-rw-r--r--src/pkg/runtime/runtime.h4
-rw-r--r--src/pkg/runtime/slice.c19
-rw-r--r--test/fixedbugs/bug273.go95
10 files changed, 174 insertions, 60 deletions
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index c4facf1be0..460358df18 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -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;
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index 94efa412bf..1e7a14947b 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -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"
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index e08e1f6017..392de17a00 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -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)
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index ae1d13d17a..707546b109 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -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]) {
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 951496e604..a79c75131f 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -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:
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index 5793159062..08cd75a6e5 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -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);
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index f27264b682..9b039121bb 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -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);
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index ff4f463b37..4c9f52e85c 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -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*);
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index c3c079c670..d967b1669b 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -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
index 0000000000..ff8f1c6af3
--- /dev/null
+++ b/test/fixedbugs/bug273.go
@@ -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")
+}