Skip to content

Commit 8e74a21

Browse files
thanmianlancetaylor
authored andcommitted
compiler: fix crashes on cyclic var/type references
This patch fixes type traversal to avoid compiler crashes for test cases where a type T includes an expression that refers back to the type without actually explicitly mentioning T. Examples include var x [uintptr(unsafe.Sizeof(&x))]byte var a [len(a)]int The fix involves expanding the set of types that the traversal code "remembers" (to avoid cycles) to include array types, and introducing an additional guard in Builtin_call_expression::do_is_constant to catch cyclic type constructs. Fixes golang/go#25299 Fixes golang/go#25679 Fixes golang/go#25315 Fixes golang/go#25680 Change-Id: I9e9bfe4413e3ddd7ce611d5164dea36c165dd4c6 Reviewed-on: https://go-review.googlesource.com/115796 Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 79eca4f commit 8e74a21

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

go/expressions.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8061,9 +8061,13 @@ Builtin_call_expression::do_is_constant() const
80618061
arg_type = arg_type->points_to();
80628062

80638063
if (arg_type->array_type() != NULL
8064-
&& arg_type->array_type()->length() != NULL
8065-
&& Builtin_call_expression::array_len_is_constant(arg))
8066-
return true;
8064+
&& arg_type->array_type()->length() != NULL)
8065+
{
8066+
this->seen_ = true;
8067+
bool ret = Builtin_call_expression::array_len_is_constant(arg);
8068+
this->seen_ = false;
8069+
return ret;
8070+
}
80678071

80688072
if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
80698073
{

go/gogo.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8258,8 +8258,16 @@ Traverse::remember_type(const Type* type)
82588258
// We mostly only have to remember named types. But it turns out
82598259
// that an interface type can refer to itself without using a name
82608260
// by relying on interface inheritance, as in
8261-
// type I interface { F() interface{I} }
8261+
//
8262+
// type I interface { F() interface{I} }
8263+
//
8264+
// Similarly it is possible for array types to refer to themselves
8265+
// without a name, e.g.
8266+
//
8267+
// var x [uintptr(unsafe.Sizeof(&x))]byte
8268+
//
82628269
if (type->classification() != Type::TYPE_NAMED
8270+
&& type->classification() != Type::TYPE_ARRAY
82638271
&& type->classification() != Type::TYPE_INTERFACE)
82648272
return false;
82658273
if (this->types_seen_ == NULL)

0 commit comments

Comments
 (0)