1
0
mirror of https://github.com/golang/go synced 2024-11-25 04:57:56 -07:00

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

Fixes #589.

R=ken2
CC=golang-dev
https://golang.org/cl/1032044
This commit is contained in:
Russ Cox 2010-05-01 13:15:42 -07:00
parent 97576673bd
commit 6361f52fc4
10 changed files with 174 additions and 60 deletions

View 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;

View 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"

View 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)

View 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]) {

View 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:

View 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);

View 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);

View 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*);

View 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);
}
}

95
test/fixedbugs/bug273.go Normal file
View File

@ -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")
}