-
Notifications
You must be signed in to change notification settings - Fork 17.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/compile: keep autos if their address reaches a control value
Autos must be kept if their address reaches the control value of a block. We didn't see this before because it is rare for an auto's address to reach a control value without also reaching a phi or being written to memory. We can probably optimize away the comparisons that lead to this scenario since autos cannot alias with pointers from elsewhere, however for now we take the conservative approach and just ensure the auto is properly initialised if its address reaches a control value. Fixes #26407. Change-Id: I02265793f010a9e001c3e1a5397c290c6769d4de Reviewed-on: https://go-review.googlesource.com/124335 Reviewed-by: David Chase <drchase@google.com>
- Loading branch information
Showing
2 changed files
with
66 additions
and
0 deletions.
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,58 @@ | ||
// run | ||
|
||
// Copyright 2018 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. | ||
|
||
// Issue 26407: ensure that stack variables which have | ||
// had their address taken and then used in a comparison, | ||
// but are otherwise unused, are cleared. | ||
|
||
package main | ||
|
||
func main() { | ||
poison() | ||
test() | ||
} | ||
|
||
//go:noinline | ||
func poison() { | ||
// initialise the stack with invalid pointers | ||
var large [256]uintptr | ||
for i := range large { | ||
large[i] = 1 | ||
} | ||
use(large[:]) | ||
} | ||
|
||
//go:noinline | ||
func test() { | ||
a := 2 | ||
x := &a | ||
if x != compare(&x) { | ||
panic("not possible") | ||
} | ||
} | ||
|
||
//go:noinline | ||
func compare(x **int) *int { | ||
var y *int | ||
if x == &y { | ||
panic("not possible") | ||
} | ||
// grow the stack to trigger a check for invalid pointers | ||
grow() | ||
if x == &y { | ||
panic("not possible") | ||
} | ||
return *x | ||
} | ||
|
||
//go:noinline | ||
func grow() { | ||
var large [1 << 16]uintptr | ||
use(large[:]) | ||
} | ||
|
||
//go:noinline | ||
func use(_ []uintptr) { } |