]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't walk field-name syntax in esc.go
authorDavid Chase <drchase@google.com>
Fri, 19 Feb 2016 17:06:31 +0000 (12:06 -0500)
committerDavid Chase <drchase@google.com>
Fri, 19 Feb 2016 19:40:49 +0000 (19:40 +0000)
Walking the field name as if it were an expression
caused a called to haspointers with a TFIELD, which panics.
Trigger was a field at a large offset within a large struct,
combined with a struct literal expression mentioning that
field.

Fixes #14405

Change-Id: I4589badae27cf3d7cf365f3a66c13447512f41f9
Reviewed-on: https://go-review.googlesource.com/19699
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/fmt.go
test/fixedbugs/issue14405.go [new file with mode: 0644]

index ccdb7810406b1fd7aee176b5250c815d4870344b..1a5a433eebdd923f46f25b9b0d9f0b543e7abbbf 100644 (file)
@@ -576,6 +576,12 @@ func esc(e *EscState, n *Node, up *Node) {
        if n == nil {
                return
        }
+       if n.Type != nil && n.Type.Etype == TFIELD {
+               // This is the left side of x:y in a struct literal.
+               // x is syntax, not an expression.
+               // See #14405.
+               return
+       }
 
        lno := int(setlineno(n))
 
@@ -602,9 +608,10 @@ func esc(e *EscState, n *Node, up *Node) {
 
        // Big stuff escapes unconditionally
        // "Big" conditions that were scattered around in walk have been gathered here
-       if n.Esc != EscHeap && n.Type != nil && (n.Type.Width > MaxStackVarSize ||
-               n.Op == ONEW && n.Type.Type.Width >= 1<<16 ||
-               n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
+       if n.Esc != EscHeap && n.Type != nil &&
+               (n.Type.Width > MaxStackVarSize ||
+                       n.Op == ONEW && n.Type.Type.Width >= 1<<16 ||
+                       n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
                if Debug['m'] > 1 {
                        Warnl(int(n.Lineno), "%v is too large for stack", n)
                }
index d00e5a6c462d5b590cc81084a382f01e085480e2..c0a1170839ab2a4704692ce37191d64dc95bdba2 100644 (file)
@@ -1542,7 +1542,7 @@ func nodedump(n *Node, flag int) string {
                } else {
                        fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
                }
-               if recur && n.Type == nil && n.Name.Param.Ntype != nil {
+               if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil {
                        indent(&buf)
                        fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Name.Param.Ntype)
                }
diff --git a/test/fixedbugs/issue14405.go b/test/fixedbugs/issue14405.go
new file mode 100644 (file)
index 0000000..c2a8946
--- /dev/null
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Mention of field with large offset in struct literal causes crash
+package p
+
+type T struct {
+       Slice [1 << 20][]int
+       Ptr   *int
+}
+
+func New(p *int) *T {
+       return &T{Ptr: p}
+}