cue: limit number of position errors

Retrieving locations of possible errors does not
do cycle checking. Limit number of positions
to avoid getting a stack overflow.

Fixes #269.

Change-Id: Ibd297eeae64386e557a864577b141d2dc8c62dab
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4840
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cmd/cue/cmd/testdata/script/issue269.txt b/cmd/cue/cmd/testdata/script/issue269.txt
new file mode 100644
index 0000000..30bb2da
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/issue269.txt
@@ -0,0 +1,25 @@
+! cue eval ./struct.cue
+cmp stderr expect-stderr
+-- struct.cue --
+type :: {
+    x: 0
+    y: 0
+
+    if x == 0 {i: 0}
+    if y == 0 {j: 0}
+}
+
+data: {
+    a: type
+    b: type
+
+    b: x: a.x
+    a: y: b.y
+}
+-- expect-stderr --
+data.a: conflicting values 0 and a.x (mismatched types int and struct):
+    ./struct.cue:2:8
+    ./struct.cue:13:11
+data.b: conflicting values 0 and a.x (mismatched types int and struct):
+    ./struct.cue:2:8
+    ./struct.cue:13:11
diff --git a/cue/errors.go b/cue/errors.go
index bf6739f..07c308e 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -173,6 +173,9 @@
 }
 
 func appendPositions(ctx *context, pos []token.Pos, src source) []token.Pos {
+	if len(pos) > 15 {
+		return pos
+	}
 	if src != nil {
 		if p := src.Pos(); p != token.NoPos {
 			pos = append(pos, src.Pos())