summaryrefslogtreecommitdiffstats
path: root/test/fixedbugs/issue19078.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/fixedbugs/issue19078.go')
-rw-r--r--test/fixedbugs/issue19078.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/test/fixedbugs/issue19078.go b/test/fixedbugs/issue19078.go
new file mode 100644
index 0000000..b19e874
--- /dev/null
+++ b/test/fixedbugs/issue19078.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2017 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 19078: liveness & zero-initialization of results
+// when there is a defer.
+package main
+
+import "unsafe"
+
+func main() {
+ // Construct an invalid pointer. We do this by
+ // making a pointer which points to the unused space
+ // between the last 48-byte object in a span and the
+ // end of the span (there are 32 unused bytes there).
+ p := new([48]byte) // make a 48-byte object
+ sink = &p // escape it, so it allocates for real
+ u := uintptr(unsafe.Pointer(p)) // get its address
+ u = u >> 13 << 13 // round down to page size
+ u += 1<<13 - 1 // add almost a page
+
+ for i := 0; i < 1000000; i++ {
+ _ = identity(u) // installs u at return slot
+ _ = liveReturnSlot(nil) // incorrectly marks return slot as live
+ }
+}
+
+//go:noinline
+func liveReturnSlot(x *int) *int {
+ defer func() {}() // causes return slot to be marked live
+ sink = &x // causes x to be moved to the heap, triggering allocation
+ return x
+}
+
+//go:noinline
+func identity(x uintptr) uintptr {
+ return x
+}
+
+var sink interface{}