]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: prevent crash in type cycles involving non-type expressions
authorRobert Griesemer <gri@golang.org>
Thu, 22 Jun 2017 23:28:11 +0000 (16:28 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 23 Jun 2017 00:10:43 +0000 (00:10 +0000)
Fixes #18643.

Change-Id: I36dca943d552a178a71094ff883b0319fe03d130
Reviewed-on: https://go-review.googlesource.com/46467
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/go/types/expr.go
src/go/types/testdata/cycles.src

index 1624858329cbf5635b7c11d15f84b6f1acac30f6..461f0a525ba88fb525262cc8049aa0b9ff398488 100644 (file)
@@ -1125,6 +1125,16 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        }
 
                case *Array:
+                       // Prevent crash if the array referred to is not yet set up.
+                       // This is a stop-gap solution; a better approach would use the mechanism of
+                       // Checker.ident (typexpr.go) using a path of types. But that would require
+                       // passing the path everywhere (all expression-checking methods, not just
+                       // type expression checking), and we're not set up for that (quite possibly
+                       // an indication that cycle detection needs to be rethought). Was issue #18643.
+                       if utyp.elem == nil {
+                               check.error(e.Pos(), "illegal cycle in type declaration")
+                               goto Error
+                       }
                        n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
                        // If we have an "open" [...]T array, set the length now that we know it
                        // and record the type for [...] (usually done by check.typExpr which is
@@ -1135,9 +1145,21 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        }
 
                case *Slice:
+                       // Prevent crash if the slice referred to is not yet set up.
+                       // See analogous comment for *Array.
+                       if utyp.elem == nil {
+                               check.error(e.Pos(), "illegal cycle in type declaration")
+                               goto Error
+                       }
                        check.indexedElts(e.Elts, utyp.elem, -1)
 
                case *Map:
+                       // Prevent crash if the map referred to is not yet set up.
+                       // See analogous comment for *Array.
+                       if utyp.key == nil || utyp.elem == nil {
+                               check.error(e.Pos(), "illegal cycle in type declaration")
+                               goto Error
+                       }
                        visited := make(map[interface{}][]Type, len(e.Elts))
                        for _, e := range e.Elts {
                                kv, _ := e.(*ast.KeyValueExpr)
index 621d83c9450a03f7823a657e0b01a96a0dc098b3..b4bd5d8b157694871dfc77e8ad5843335cb77d79 100644 (file)
@@ -140,4 +140,13 @@ func (*T12) m() {}
 type (
        P3 *T13
        T13 /* ERROR cycle */ T13
-)
\ No newline at end of file
+)
+
+// test cases for issue 18643
+// (type cycle detection when non-type expressions are involved)
+type (
+       T14 [len(T14 /* ERROR cycle */ {})]int
+       T15 [][len(T15 /* ERROR cycle */ {})]int
+       T16 map[[len(T16 /* ERROR cycle */ {1:2})]int]int
+       T17 map[int][len(T17 /* ERROR cycle */ {1:2})]int
+)