]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix order-of-assignment issue w/ defers
authorMatthew Dempsky <mdempsky@google.com>
Fri, 22 Jan 2021 03:27:12 +0000 (19:27 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 25 Jan 2021 23:54:36 +0000 (23:54 +0000)
CL 261677 fixed a logic issue in walk's alias detection, where it was
checking the RHS expression instead of the LHS expression when trying
to determine the kind of assignment. However, correcting this exposed
a latent issue with assigning to result parameters in functions with
defers, where an assignment could become visible earlier than intended
if a later expression could panic.

Fixes #43835.

Change-Id: I061ced125e3896e26d65f45b28c99db2c8a74a8c
Reviewed-on: https://go-review.googlesource.com/c/go/+/285633
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/gc/walk.go
test/fixedbugs/issue43835.go [new file with mode: 0644]

index a7b6e7fcb3c7657ed7574cc267c63fe2ea42bca9..2133a160b2b6cf12c1d32f106734e7dded0f5c95 100644 (file)
@@ -267,7 +267,7 @@ func walkstmt(n *Node) *Node {
                if n.List.Len() == 0 {
                        break
                }
-               if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) {
+               if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) || Curfn.Func.HasDefer() {
                        // assign to the function out parameters,
                        // so that reorder3 can fix up conflicts
                        var rl []*Node
@@ -2233,7 +2233,15 @@ func aliased(r *Node, all []*Node) bool {
                        memwrite = true
                        continue
 
-               case PAUTO, PPARAM, PPARAMOUT:
+               case PPARAMOUT:
+                       // Assignments to a result parameter in a function with defers
+                       // becomes visible early if evaluation of any later expression
+                       // panics (#43835).
+                       if Curfn.Func.HasDefer() {
+                               return true
+                       }
+                       fallthrough
+               case PAUTO, PPARAM:
                        if l.Name.Addrtaken() {
                                memwrite = true
                                continue
diff --git a/test/fixedbugs/issue43835.go b/test/fixedbugs/issue43835.go
new file mode 100644 (file)
index 0000000..449eb72
--- /dev/null
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2021 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.
+
+package main
+
+func main() {
+       if f() {
+               panic("FAIL")
+       }
+       if bad, _ := g(); bad {
+               panic("FAIL")
+       }
+}
+
+func f() (bad bool) {
+       defer func() {
+               recover()
+       }()
+       var p *int
+       bad, _ = true, *p
+       return
+}
+
+func g() (bool, int) {
+       defer func() {
+               recover()
+       }()
+       var p *int
+       return true, *p
+}