mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile: don't move nil checks across a VarDef
We need to make sure that there's no possible faulting instruction between a VarDef and that variable being fully initialized. If there was, then anything scanning the stack during the handling of that fault will see a live but uninitialized variable on the stack. If we have: NilCheck p VarDef x x = *p We can't rewrite that to VarDef x NilCheck p x = *p Particularly, even though *p faults on p==nil, we still have to do the explicit nil check before the VarDef. Fixes #32288 Change-Id: Ib8b88e6a5af3bf6f238ff5491ac86f53f3cf9fc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/179239 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
c10db03cbe
commit
64c134f90f
@ -219,9 +219,31 @@ func nilcheckelim2(f *Func) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
|
if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
|
||||||
if v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive {
|
if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(GCNode).Typ().HasHeapPointer()) {
|
||||||
// These ops don't really change memory.
|
// These ops don't really change memory.
|
||||||
continue
|
continue
|
||||||
|
// Note: OpVarDef requires that the defined variable not have pointers.
|
||||||
|
// We need to make sure that there's no possible faulting
|
||||||
|
// instruction between a VarDef and that variable being
|
||||||
|
// fully initialized. If there was, then anything scanning
|
||||||
|
// the stack during the handling of that fault will see
|
||||||
|
// a live but uninitialized pointer variable on the stack.
|
||||||
|
//
|
||||||
|
// If we have:
|
||||||
|
//
|
||||||
|
// NilCheck p
|
||||||
|
// VarDef x
|
||||||
|
// x = *p
|
||||||
|
//
|
||||||
|
// We can't rewrite that to
|
||||||
|
//
|
||||||
|
// VarDef x
|
||||||
|
// NilCheck p
|
||||||
|
// x = *p
|
||||||
|
//
|
||||||
|
// Particularly, even though *p faults on p==nil, we still
|
||||||
|
// have to do the explicit nil check before the VarDef.
|
||||||
|
// See issue #32288.
|
||||||
}
|
}
|
||||||
// This op changes memory. Any faulting instruction after v that
|
// This op changes memory. Any faulting instruction after v that
|
||||||
// we've recorded in the unnecessary map is now obsolete.
|
// we've recorded in the unnecessary map is now obsolete.
|
||||||
|
48
test/fixedbugs/issue32288.go
Normal file
48
test/fixedbugs/issue32288.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2019 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
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
s [1]string
|
||||||
|
pad [16]uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func f(t *int, p *int) []T {
|
||||||
|
var res []T
|
||||||
|
for {
|
||||||
|
var e *T
|
||||||
|
res = append(res, *e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer func() {
|
||||||
|
useStack(100) // force a stack copy
|
||||||
|
// We're expecting a panic.
|
||||||
|
// The bug in this issue causes a throw, which this recover() will not squash.
|
||||||
|
recover()
|
||||||
|
}()
|
||||||
|
junk() // fill the stack with invalid pointers
|
||||||
|
f(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func useStack(n int) {
|
||||||
|
if n == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
useStack(n - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func junk() uintptr {
|
||||||
|
var a [128]uintptr // 1k of bad pointers on the stack
|
||||||
|
for i := range a {
|
||||||
|
a[i] = 0xaa
|
||||||
|
}
|
||||||
|
return a[12]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user