mirror of
https://github.com/golang/go
synced 2024-11-26 11:38:01 -07:00
cmd/compile: fix order-of-assignment issue w/ defers
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>
This commit is contained in:
parent
ad2ca26a52
commit
deaf29a8a8
@ -267,7 +267,7 @@ func walkstmt(n *Node) *Node {
|
|||||||
if n.List.Len() == 0 {
|
if n.List.Len() == 0 {
|
||||||
break
|
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,
|
// assign to the function out parameters,
|
||||||
// so that reorder3 can fix up conflicts
|
// so that reorder3 can fix up conflicts
|
||||||
var rl []*Node
|
var rl []*Node
|
||||||
@ -2233,7 +2233,15 @@ func aliased(r *Node, all []*Node) bool {
|
|||||||
memwrite = true
|
memwrite = true
|
||||||
continue
|
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() {
|
if l.Name.Addrtaken() {
|
||||||
memwrite = true
|
memwrite = true
|
||||||
continue
|
continue
|
||||||
|
33
test/fixedbugs/issue43835.go
Normal file
33
test/fixedbugs/issue43835.go
Normal file
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user