From 047cff816d1457fa3894b7cd2a61752f669704c7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Feb 2012 06:18:41 +0000 Subject: [PATCH] compiler, runtime: Check make int64 args for overflow. From-SVN: r183994 --- gcc/go/gofrontend/expressions.cc | 32 ++++++++++++++++++++++++++------ gcc/go/gofrontend/runtime.def | 7 +++++++ libgo/runtime/chan.c | 6 ++++++ libgo/runtime/go-make-slice.c | 24 ++++++++++++++++++++++++ libgo/runtime/go-new-map.c | 14 ++++++++++++++ 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index f906b22..395a375 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7744,6 +7744,10 @@ Builtin_call_expression::lower_make() return Expression::make_error(this->location()); } + bool have_big_args = false; + Type* uintptr_type = Type::lookup_integer_type("uintptr"); + int uintptr_bits = uintptr_type->integer_type()->bits(); + ++parg; Expression* len_arg; if (parg == args->end()) @@ -7767,6 +7771,9 @@ Builtin_call_expression::lower_make() this->report_error(_("bad size for make")); return Expression::make_error(this->location()); } + if (len_arg->type()->integer_type() != NULL + && len_arg->type()->integer_type()->bits() > uintptr_bits) + have_big_args = true; ++parg; } @@ -7779,6 +7786,9 @@ Builtin_call_expression::lower_make() this->report_error(_("bad capacity when making slice")); return Expression::make_error(this->location()); } + if (cap_arg->type()->integer_type() != NULL + && cap_arg->type()->integer_type()->bits() > uintptr_bits) + have_big_args = true; ++parg; } @@ -7801,16 +7811,26 @@ Builtin_call_expression::lower_make() if (is_slice) { if (cap_arg == NULL) - call = Runtime::make_call(Runtime::MAKESLICE1, loc, 2, type_arg, - len_arg); + call = Runtime::make_call((have_big_args + ? Runtime::MAKESLICE1BIG + : Runtime::MAKESLICE1), + loc, 2, type_arg, len_arg); else - call = Runtime::make_call(Runtime::MAKESLICE2, loc, 3, type_arg, - len_arg, cap_arg); + call = Runtime::make_call((have_big_args + ? Runtime::MAKESLICE2BIG + : Runtime::MAKESLICE2), + loc, 3, type_arg, len_arg, cap_arg); } else if (is_map) - call = Runtime::make_call(Runtime::MAKEMAP, loc, 2, type_arg, len_arg); + call = Runtime::make_call((have_big_args + ? Runtime::MAKEMAPBIG + : Runtime::MAKEMAP), + loc, 2, type_arg, len_arg); else if (is_chan) - call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg); + call = Runtime::make_call((have_big_args + ? Runtime::MAKECHANBIG + : Runtime::MAKECHAN), + loc, 2, type_arg, len_arg); else go_unreachable(); diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 57d5090..7dda539 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -72,10 +72,16 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array", DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE)) DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR), R1(SLICE)) +DEF_GO_RUNTIME(MAKESLICE1BIG, "__go_make_slice1_big", P2(TYPE, UINT64), + R1(SLICE)) +DEF_GO_RUNTIME(MAKESLICE2BIG, "__go_make_slice2_big", P3(TYPE, UINT64, UINT64), + R1(SLICE)) // Make a map. DEF_GO_RUNTIME(MAKEMAP, "__go_new_map", P2(MAPDESCRIPTOR, UINTPTR), R1(MAP)) +DEF_GO_RUNTIME(MAKEMAPBIG, "__go_new_map_big", P2(MAPDESCRIPTOR, UINT64), + R1(MAP)) // Build a map from a composite literal. DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map", @@ -116,6 +122,7 @@ DEF_GO_RUNTIME(MAPITERNEXT, "runtime.mapiternext", P1(MAPITER), R0()) // Make a channel. DEF_GO_RUNTIME(MAKECHAN, "__go_new_channel", P2(TYPE, UINTPTR), R1(CHAN)) +DEF_GO_RUNTIME(MAKECHANBIG, "__go_new_channel_big", P2(TYPE, UINT64), R1(CHAN)) // Get the length of a channel (the number of unread values). DEF_GO_RUNTIME(CHAN_LEN, "__go_chan_len", P1(CHAN), R1(INT)) diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c index a246992..4fc2d60 100644 --- a/libgo/runtime/chan.c +++ b/libgo/runtime/chan.c @@ -130,6 +130,12 @@ __go_new_channel(ChanType *t, uintptr hint) return runtime_makechan_c(t, hint); } +Hchan* +__go_new_channel_big(ChanType *t, uint64 hint) +{ + return runtime_makechan_c(t, hint); +} + /* * generic single channel send/recv * if the bool pointer is nil, diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c index 765e7c0..42b412c 100644 --- a/libgo/runtime/go-make-slice.c +++ b/libgo/runtime/go-make-slice.c @@ -57,3 +57,27 @@ __go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len) { return __go_make_slice2 (td, len, len); } + +struct __go_open_array +__go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len, + uint64_t cap) +{ + uintptr_t slen; + uintptr_t scap; + + slen = (uintptr_t) len; + if ((uint64_t) slen != len) + runtime_panicstring ("makeslice: len out of range"); + + scap = (uintptr_t) cap; + if ((uint64_t) scap != cap) + runtime_panicstring ("makeslice: cap out of range"); + + return __go_make_slice2 (td, slen, scap); +} + +struct __go_open_array +__go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len) +{ + return __go_make_slice2_big (td, len, len); +} diff --git a/libgo/runtime/go-new-map.c b/libgo/runtime/go-new-map.c index 288e188..eef71dd 100644 --- a/libgo/runtime/go-new-map.c +++ b/libgo/runtime/go-new-map.c @@ -125,3 +125,17 @@ __go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries) __builtin_memset (ret->__buckets, 0, entries * sizeof (void *)); return ret; } + +/* Allocate a new map when the argument to make is a large type. */ + +struct __go_map * +__go_new_map_big (const struct __go_map_descriptor *descriptor, + uint64_t entries) +{ + uintptr_t sentries; + + sentries = (uintptr_t) entries; + if ((uint64_t) sentries != entries) + runtime_panicstring ("map size out of range"); + return __go_new_map (descriptor, sentries); +} -- 2.7.4