зеркало из https://github.com/CryptoPro/go.git
43 строки
1.2 KiB
Go
43 строки
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{}
|