]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: keep autos if their address reaches a control value
authorMichael Munday <mike.munday@ibm.com>
Tue, 17 Jul 2018 07:39:30 +0000 (08:39 +0100)
committerMichael Munday <mike.munday@ibm.com>
Tue, 17 Jul 2018 14:58:54 +0000 (14:58 +0000)
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>
src/cmd/compile/internal/ssa/deadstore.go
test/fixedbugs/issue26407.go [new file with mode: 0644]

index 6359588129781458424b6100e6a270dbe2260a69..ca6bce972e27813137e0d79f468557cdecce2d70 100644 (file)
@@ -262,6 +262,14 @@ func elimDeadAutosGeneric(f *Func) {
                        for _, v := range b.Values {
                                changed = visit(v) || changed
                        }
+                       // keep the auto if its address reaches a control value
+                       if b.Control == nil {
+                               continue
+                       }
+                       if n, ok := addr[b.Control]; ok && !used[n] {
+                               used[n] = true
+                               changed = true
+                       }
                }
                if !changed {
                        break
diff --git a/test/fixedbugs/issue26407.go b/test/fixedbugs/issue26407.go
new file mode 100644 (file)
index 0000000..aa8e79c
--- /dev/null
@@ -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) { }