-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Showing
2 changed files
with
71 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] | ||
} |