Commit 6361f52f authored by Russ Cox's avatar Russ Cox

gc: be pickier about slice, chan, array, and map sizes

Fixes #589.

R=ken2
CC=golang-dev
https://golang.org/cl/1032044
parent 97576673
...@@ -96,7 +96,7 @@ void ...@@ -96,7 +96,7 @@ void
dowidth(Type *t) dowidth(Type *t)
{ {
int32 et; int32 et;
uint32 w; int64 w;
int lno; int lno;
Type *t1; Type *t1;
...@@ -222,7 +222,15 @@ dowidth(Type *t) ...@@ -222,7 +222,15 @@ dowidth(Type *t)
if(t->type == T) if(t->type == T)
break; break;
if(t->bound >= 0) { if(t->bound >= 0) {
uint64 cap;
dowidth(t->type); 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; w = t->bound * t->type->width;
if(w == 0) if(w == 0)
w = maxround; w = maxround;
......
...@@ -33,47 +33,47 @@ char *runtimeimport = ...@@ -33,47 +33,47 @@ char *runtimeimport =
"func \"\".stringiter (? string, ? int) int\n" "func \"\".stringiter (? string, ? int) int\n"
"func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n" "func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
"func \"\".slicecopy (to any, fr any, wid uint32) int\n" "func \"\".slicecopy (to any, fr any, wid uint32) int\n"
"func \"\".ifaceI2E (iface any) (ret any)\n" "func \"\".ifaceI2E (iface any) any\n"
"func \"\".ifaceE2I (typ *uint8, iface any) (ret any)\n" "func \"\".ifaceE2I (typ *uint8, iface any) any\n"
"func \"\".ifaceT2E (typ *uint8, elem any) (ret any)\n" "func \"\".ifaceT2E (typ *uint8, elem any) any\n"
"func \"\".ifaceE2T (typ *uint8, elem any) (ret any)\n" "func \"\".ifaceE2T (typ *uint8, elem any) any\n"
"func \"\".ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n" "func \"\".ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
"func \"\".ifaceE2T2 (typ *uint8, elem 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 \"\".ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) any\n"
"func \"\".ifaceI2T (typ *uint8, iface any) (ret any)\n" "func \"\".ifaceI2T (typ *uint8, iface any) any\n"
"func \"\".ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n" "func \"\".ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
"func \"\".ifaceI2I (typ *uint8, iface any) (ret any)\n" "func \"\".ifaceI2I (typ *uint8, iface any) any\n"
"func \"\".ifaceI2Ix (typ *uint8, iface any) (ret any)\n" "func \"\".ifaceI2Ix (typ *uint8, iface any) any\n"
"func \"\".ifaceI2I2 (typ *uint8, iface any) (ret any, ok bool)\n" "func \"\".ifaceI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
"func \"\".ifaceeq (i1 any, i2 any) (ret bool)\n" "func \"\".ifaceeq (i1 any, i2 any) bool\n"
"func \"\".efaceeq (i1 any, i2 any) (ret bool)\n" "func \"\".efaceeq (i1 any, i2 any) bool\n"
"func \"\".ifacethash (i1 any) (ret uint32)\n" "func \"\".ifacethash (i1 any) uint32\n"
"func \"\".efacethash (i1 any) (ret uint32)\n" "func \"\".efacethash (i1 any) uint32\n"
"func \"\".makemap (key *uint8, val *uint8, hint int) (hmap map[any] any)\n" "func \"\".makemap (key *uint8, val *uint8, hint int64) map[any] any\n"
"func \"\".mapaccess1 (hmap map[any] any, key any) (val 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 \"\".mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n"
"func \"\".mapassign1 (hmap map[any] any, key any, val any)\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 \"\".mapassign2 (hmap map[any] any, key any, val any, pres bool)\n"
"func \"\".mapiterinit (hmap map[any] any, hiter *any)\n" "func \"\".mapiterinit (hmap map[any] any, hiter *any)\n"
"func \"\".mapiternext (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 \"\".mapiter2 (hiter *any) (key any, val any)\n"
"func \"\".makechan (elem *uint8, hint int) (hchan chan any)\n" "func \"\".makechan (elem *uint8, hint int64) chan any\n"
"func \"\".chanrecv1 (hchan <-chan any) (elem any)\n" "func \"\".chanrecv1 (hchan <-chan any) any\n"
"func \"\".chanrecv2 (hchan <-chan any) (elem any, pres bool)\n" "func \"\".chanrecv2 (hchan <-chan any) (elem any, pres bool)\n"
"func \"\".chansend1 (hchan chan<- any, elem any)\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 \"\".closechan (hchan any)\n"
"func \"\".closedchan (hchan any) bool\n" "func \"\".closedchan (hchan any) bool\n"
"func \"\".newselect (size int) (sel *uint8)\n" "func \"\".newselect (size int) *uint8\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) (selected bool)\n" "func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) bool\n"
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) (selected bool)\n" "func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
"func \"\".selectdefault (sel *uint8) (selected bool)\n" "func \"\".selectdefault (sel *uint8) bool\n"
"func \"\".selectgo (sel *uint8)\n" "func \"\".selectgo (sel *uint8)\n"
"func \"\".makeslice (typ *uint8, nel int, cap int) (ary []any)\n" "func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
"func \"\".sliceslice1 (old []any, lb int, width int) (ary []any)\n" "func \"\".sliceslice1 (old []any, lb int, width int) []any\n"
"func \"\".sliceslice (old []any, lb int, hb int, width int) (ary []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) (ary []any)\n" "func \"\".slicearray (old *any, nel int, lb int, hb int, width int) []any\n"
"func \"\".closure ()\n" "func \"\".closure ()\n"
"func \"\".int64div (? int64, ? int64) int64\n" "func \"\".int64div (? int64, ? int64) int64\n"
"func \"\".uint64div (? uint64, ? uint64) uint64\n" "func \"\".uint64div (? uint64, ? uint64) uint64\n"
...@@ -81,7 +81,7 @@ char *runtimeimport = ...@@ -81,7 +81,7 @@ char *runtimeimport =
"func \"\".uint64mod (? uint64, ? uint64) uint64\n" "func \"\".uint64mod (? uint64, ? uint64) uint64\n"
"func \"\".float64toint64 (? float64) int64\n" "func \"\".float64toint64 (? float64) int64\n"
"func \"\".int64tofloat64 (? int64) float64\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"
"$$\n"; "$$\n";
char *unsafeimport = char *unsafeimport =
...@@ -90,9 +90,9 @@ char *unsafeimport = ...@@ -90,9 +90,9 @@ char *unsafeimport =
"func \"\".Offsetof (? any) int\n" "func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n" "func \"\".Sizeof (? any) int\n"
"func \"\".Alignof (? 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 \"\".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 \"\".New (typ interface { }) \"\".Pointer\n"
"func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n" "func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n"
"\n" "\n"
......
...@@ -65,7 +65,7 @@ func ifacethash(i1 any) (ret uint32) ...@@ -65,7 +65,7 @@ func ifacethash(i1 any) (ret uint32)
func efacethash(i1 any) (ret uint32) func efacethash(i1 any) (ret uint32)
// *byte is really *runtime.Type // *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 mapaccess1(hmap map[any]any, key any) (val any)
func mapaccess2(hmap map[any]any, key any) (val any, pres bool) func mapaccess2(hmap map[any]any, key any) (val any, pres bool)
func mapassign1(hmap map[any]any, key any, val any) func mapassign1(hmap map[any]any, key any, val any)
...@@ -76,7 +76,7 @@ func mapiter1(hiter *any) (key any) ...@@ -76,7 +76,7 @@ func mapiter1(hiter *any) (key any)
func mapiter2(hiter *any) (key any, val any) func mapiter2(hiter *any) (key any, val any)
// *byte is really *runtime.Type // *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 chanrecv1(hchan <-chan any) (elem any)
func chanrecv2(hchan <-chan any) (elem any, pres bool) func chanrecv2(hchan <-chan any) (elem any, pres bool)
func chansend1(hchan chan<- any, elem any) func chansend1(hchan chan<- any, elem any)
...@@ -90,7 +90,7 @@ func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool) ...@@ -90,7 +90,7 @@ func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
func selectdefault(sel *byte) (selected bool) func selectdefault(sel *byte) (selected bool)
func selectgo(sel *byte) 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 sliceslice1(old []any, lb int, width int) (ary []any)
func sliceslice(old []any, lb int, hb 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) func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
......
...@@ -929,13 +929,13 @@ reswitch: ...@@ -929,13 +929,13 @@ reswitch:
l = args->n; l = args->n;
args = args->next; args = args->next;
typecheck(&l, Erv); typecheck(&l, Erv);
defaultlit(&l, types[TUINT]); defaultlit(&l, types[TINT]);
r = N; r = N;
if(args != nil) { if(args != nil) {
r = args->n; r = args->n;
args = args->next; args = args->next;
typecheck(&r, Erv); typecheck(&r, Erv);
defaultlit(&r, types[TUINT]); defaultlit(&r, types[TINT]);
} }
if(l->type == T || (r && r->type == T)) if(l->type == T || (r && r->type == T))
goto error; goto error;
...@@ -947,8 +947,6 @@ reswitch: ...@@ -947,8 +947,6 @@ reswitch:
yyerror("non-integer cap argument to make(%T)", t); yyerror("non-integer cap argument to make(%T)", t);
goto error; goto error;
} }
if(r == N)
r = nodintconst(0);
n->left = l; n->left = l;
n->right = r; n->right = r;
n->op = OMAKESLICE; n->op = OMAKESLICE;
...@@ -959,7 +957,7 @@ reswitch: ...@@ -959,7 +957,7 @@ reswitch:
l = args->n; l = args->n;
args = args->next; args = args->next;
typecheck(&l, Erv); typecheck(&l, Erv);
defaultlit(&l, types[TUINT]); defaultlit(&l, types[TINT]);
if(l->type == T) if(l->type == T)
goto error; goto error;
if(!isint[l->type->etype]) { if(!isint[l->type->etype]) {
...@@ -978,7 +976,7 @@ reswitch: ...@@ -978,7 +976,7 @@ reswitch:
l = args->n; l = args->n;
args = args->next; args = args->next;
typecheck(&l, Erv); typecheck(&l, Erv);
defaultlit(&l, types[TUINT]); defaultlit(&l, types[TINT]);
if(l->type == T) if(l->type == T)
goto error; goto error;
if(!isint[l->type->etype]) { if(!isint[l->type->etype]) {
......
...@@ -1138,7 +1138,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -1138,7 +1138,7 @@ walkexpr(Node **np, NodeList **init)
case OMAKECHAN: case OMAKECHAN:
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init, n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
typename(n->type->type), typename(n->type->type),
conv(n->left, types[TINT])); conv(n->left, types[TINT64]));
goto ret; goto ret;
case OMAKEMAP: case OMAKEMAP:
...@@ -1151,18 +1151,22 @@ walkexpr(Node **np, NodeList **init) ...@@ -1151,18 +1151,22 @@ walkexpr(Node **np, NodeList **init)
n = mkcall1(fn, n->type, init, n = mkcall1(fn, n->type, init,
typename(t->down), // key type typename(t->down), // key type
typename(t->type), // value type typename(t->type), // value type
conv(n->left, types[TINT])); conv(n->left, types[TINT64]));
goto ret; goto ret;
case OMAKESLICE: 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; t = n->type;
fn = syslook("makeslice", 1); fn = syslook("makeslice", 1);
argtype(fn, t->type); // any-1 argtype(fn, t->type); // any-1
n = mkcall1(fn, n->type, init, n = mkcall1(fn, n->type, init,
typename(n->type), typename(n->type),
conv(n->left, types[TINT]), conv(l, types[TINT64]),
conv(n->right, types[TINT])); conv(r, types[TINT64]));
goto ret; goto ret;
case ORUNESTR: case ORUNESTR:
......
...@@ -90,11 +90,14 @@ static uint32 fastrand2(void); ...@@ -90,11 +90,14 @@ static uint32 fastrand2(void);
static void destroychan(Hchan*); static void destroychan(Hchan*);
Hchan* Hchan*
makechan(Type *elem, uint32 hint) makechan(Type *elem, int64 hint)
{ {
Hchan *c; Hchan *c;
int32 i; int32 i;
if(hint < 0 || (int32)hint != hint || hint > ((uintptr)-1) / elem->size)
panicstring("makechan: size out of range");
if(elem->alg >= nelem(algarray)) { if(elem->alg >= nelem(algarray)) {
printf("chan(alg=%d)\n", elem->alg); printf("chan(alg=%d)\n", elem->alg);
throw("runtime.makechan: unsupported elem type"); throw("runtime.makechan: unsupported elem type");
...@@ -141,9 +144,9 @@ destroychan(Hchan *c) ...@@ -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 void
·makechan(Type *elem, uint32 hint, Hchan *ret) ·makechan(Type *elem, int64 hint, Hchan *ret)
{ {
ret = makechan(elem, hint); ret = makechan(elem, hint);
FLUSH(&ret); FLUSH(&ret);
......
...@@ -667,11 +667,14 @@ static int32 debug = 0; ...@@ -667,11 +667,14 @@ static int32 debug = 0;
// makemap(key, val *Type, hint uint32) (hmap *map[any]any); // makemap(key, val *Type, hint uint32) (hmap *map[any]any);
Hmap* Hmap*
makemap(Type *key, Type *val, uint32 hint) makemap(Type *key, Type *val, int64 hint)
{ {
Hmap *h; Hmap *h;
int32 keyalg, valalg, keysize, valsize; int32 keyalg, valalg, keysize, valsize;
if(hint < 0 || (int32)hint != hint)
panicstring("makemap: size out of range");
keyalg = key->alg; keyalg = key->alg;
valalg = val->alg; valalg = val->alg;
keysize = key->size; keysize = key->size;
...@@ -731,9 +734,9 @@ makemap(Type *key, Type *val, uint32 hint) ...@@ -731,9 +734,9 @@ makemap(Type *key, Type *val, uint32 hint)
return h; return h;
} }
// makemap(key, val *Type, hint uint32) (hmap *map[any]any); // makemap(key, val *Type, hint int64) (hmap *map[any]any);
void void
·makemap(Type *key, Type *val, uint32 hint, Hmap *ret) ·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
{ {
ret = makemap(key, val, hint); ret = makemap(key, val, hint);
FLUSH(&ret); FLUSH(&ret);
......
...@@ -577,9 +577,9 @@ struct hash_iter* mapiterinit(Hmap*); ...@@ -577,9 +577,9 @@ struct hash_iter* mapiterinit(Hmap*);
void mapiternext(struct hash_iter*); void mapiternext(struct hash_iter*);
bool mapiterkey(struct hash_iter*, void*); bool mapiterkey(struct hash_iter*, void*);
void mapiterkeyvalue(struct hash_iter*, void*, 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 chansend(Hchan*, void*, bool*);
void chanrecv(Hchan*, void*, bool*); void chanrecv(Hchan*, void*, bool*);
void chanclose(Hchan*); void chanclose(Hchan*);
......
...@@ -9,17 +9,20 @@ ...@@ -9,17 +9,20 @@
static int32 debug = 0; static int32 debug = 0;
// see also unsafe·NewArray // see also unsafe·NewArray
// makeslice(typ *Type, nel int, cap int) (ary []any); // makeslice(typ *Type, len, cap int64) (ary []any);
void 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; size = cap*t->elem->size;
ret.len = nel; ret.len = len;
ret.cap = cap; ret.cap = cap;
if((t->elem->kind&KindNoPointers)) if((t->elem->kind&KindNoPointers))
...@@ -30,8 +33,8 @@ void ...@@ -30,8 +33,8 @@ void
FLUSH(&ret); FLUSH(&ret);
if(debug) { if(debug) {
printf("makeslice(%S, %d, %d); ret=", printf("makeslice(%S, %D, %D); ret=",
*t->string, nel, cap); *t->string, len, cap);
·printslice(ret); ·printslice(ret);
} }
} }
......
// $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")
}
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