aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2017-06-22 16:28:11 -0700
committerRobert Griesemer <gri@golang.org>2017-06-23 00:10:43 +0000
commit7c02beb96a601001091c91a9cf0fe4cb6ce459a0 (patch)
tree34c9543e9f856454d62272b8fcf4148a176b34cd
parentb88efc7e7ac15f9e0b5d8d9c82f870294f6a3839 (diff)
downloadgo-7c02beb96a601001091c91a9cf0fe4cb6ce459a0.tar.gz
go-7c02beb96a601001091c91a9cf0fe4cb6ce459a0.zip
go/types: prevent crash in type cycles involving non-type expressions
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>
-rw-r--r--src/go/types/expr.go22
-rw-r--r--src/go/types/testdata/cycles.src11
2 files changed, 32 insertions, 1 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 1624858329..461f0a525b 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -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)
diff --git a/src/go/types/testdata/cycles.src b/src/go/types/testdata/cycles.src
index 621d83c945..b4bd5d8b15 100644
--- a/src/go/types/testdata/cycles.src
+++ b/src/go/types/testdata/cycles.src
@@ -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
+)