Go patch committed: Don't crash on cyclic var/type dependencies

Message ID CAOyqgcW31KrgHaWA7ZpjQjsjuG7ttw62gSktZ=VTNVgAu09WTw@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Don't crash on cyclic var/type dependencies
Related show

Commit Message

Ian Lance Taylor June 4, 2018, 7:10 p.m.
This patch by Than McIntosh fixes type traversal in the Go frontend 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 https://golang.org/issue/{25299,25679,25315,25680}.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 261041)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-79eca4fd642724d89e9bec8f79889451f6632a46
+8e74a218e11ef6eaaf7014a3ad1cd0b13359c607
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 261041)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -8061,9 +8061,13 @@  Builtin_call_expression::do_is_constant(
 	  arg_type = arg_type->points_to();
 
 	if (arg_type->array_type() != NULL
-	    && arg_type->array_type()->length() != NULL
-	    && Builtin_call_expression::array_len_is_constant(arg))
-	  return true;
+	    && arg_type->array_type()->length() != NULL)
+          {
+	    this->seen_ = true;
+	    bool ret = Builtin_call_expression::array_len_is_constant(arg);
+	    this->seen_ = false;
+	    return ret;
+          }
 
 	if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
 	  {
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 261041)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -8258,8 +8258,16 @@  Traverse::remember_type(const Type* type
   // We mostly only have to remember named types.  But it turns out
   // that an interface type can refer to itself without using a name
   // by relying on interface inheritance, as in
-  // type I interface { F() interface{I} }
+  //
+  //         type I interface { F() interface{I} }
+  //
+  // Similarly it is possible for array types to refer to themselves
+  // without a name, e.g.
+  //
+  //         var x [uintptr(unsafe.Sizeof(&x))]byte
+  //
   if (type->classification() != Type::TYPE_NAMED
+      && type->classification() != Type::TYPE_ARRAY
       && type->classification() != Type::TYPE_INTERFACE)
     return false;
   if (this->types_seen_ == NULL)