mirror of
https://github.com/golang/go
synced 2024-11-05 15:26:15 -07:00
43 lines
1.2 KiB
Go
43 lines
1.2 KiB
Go
|
// 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{}
|