From: Tal Shprecher Date: Sun, 14 Feb 2016 06:39:16 +0000 (-0800) Subject: cmd/compile: avoid leak of dottype expression if type does not contain pointers. X-Git-Tag: go1.7beta1~1829 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5c5e8d41054940ccf9e1c025bf21c86e85f33bde;p=gostls13.git cmd/compile: avoid leak of dottype expression if type does not contain pointers. Fixes #13805 Change-Id: Ica9aae2e054b74f67d28ab27f72c52a3f03eeb59 Reviewed-on: https://go-review.googlesource.com/19489 Run-TryBot: Michael Matloob TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index ff983e717e..ccdb781040 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -962,7 +962,7 @@ func escassign(e *EscState, dst *Node, src *Node) { dst = &e.theSink } - case ODOT: // treat "dst.x = src" as "dst = src" + case ODOT: // treat "dst.x = src" as "dst = src" escassign(e, dst.Left, src) return @@ -1042,7 +1042,6 @@ func escassign(e *EscState, dst *Node, src *Node) { ODOTMETH, // treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC // iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here - ODOTTYPE, ODOTTYPE2, OSLICE, OSLICE3, @@ -1052,6 +1051,12 @@ func escassign(e *EscState, dst *Node, src *Node) { // Conversions, field access, slice all preserve the input value. escassign(e, dst, src.Left) + case ODOTTYPE: + if src.Type != nil && !haspointers(src.Type) { + break + } + escassign(e, dst, src.Left) + case OAPPEND: // Append returns first argument. // Subsequent arguments are already leaked because they are operands to append. @@ -1549,9 +1554,9 @@ func escflows(e *EscState, dst *Node, src *Node) { // finding an OADDR just means we're following the upstream of a dereference, // so this address doesn't leak (yet). // If level == 0, it means the /value/ of this node can reach the root of this flood. -// so if this node is an OADDR, it's argument should be marked as escaping iff -// it's currfn/e->loopdepth are different from the flood's root. -// Once an object has been moved to the heap, all of it's upstream should be considered +// so if this node is an OADDR, its argument should be marked as escaping iff +// its currfn/e->loopdepth are different from the flood's root. +// Once an object has been moved to the heap, all of its upstream should be considered // escaping to the global scope. func escflood(e *EscState, dst *Node) { switch dst.Op { diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index f74bb334aa..8fd6f85575 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -936,7 +936,6 @@ OpSwitch: n.Type = n.Right.Type n.Right = nil if n.Type == nil { - n.Type = nil return } } diff --git a/test/escape_iface.go b/test/escape_iface.go index 2b1144ad2c..9149fa1770 100644 --- a/test/escape_iface.go +++ b/test/escape_iface.go @@ -225,3 +225,23 @@ func dotTypeEscape() *T2 { // #11931 T1: *(x.(*T1)), // ERROR "&T2 literal escapes to heap" } } + +func dotTypeEscape2() { // #13805 + { + i := 0 + var v int + var x interface{} = i // ERROR "i does not escape" + *(&v) = x.(int) // ERROR "&v does not escape" + } + { + i := 0 + var x interface{} = i // ERROR "i does not escape" + sink = x.(int) // ERROR "x.\(int\) escapes to heap" + + } + { + i := 0 // ERROR "moved to heap: i" + var x interface{} = &i // ERROR "&i escapes to heap" + sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap" + } +}