| // 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. | 
 |  | 
 | package main | 
 |  | 
 | import ( | 
 | 	"runtime" | 
 | ) | 
 |  | 
 | var nilp *int | 
 | var forceHeap interface{} | 
 |  | 
 | func main() { | 
 | 	// x is a pointer on the stack to heap-allocated memory. | 
 | 	x := new([32]*int) | 
 | 	forceHeap = x | 
 | 	forceHeap = nil | 
 |  | 
 | 	// Push a defer to be run when we panic below. | 
 | 	defer func() { | 
 | 		// Ignore the panic. | 
 | 		recover() | 
 | 		// Force a stack walk. Go 1.11 will fail because x is now | 
 | 		// considered live again. | 
 | 		runtime.GC() | 
 | 	}() | 
 | 	// Make x live at the defer's PC. | 
 | 	runtime.KeepAlive(x) | 
 |  | 
 | 	// x is no longer live. Garbage collect the [32]*int on the | 
 | 	// heap. | 
 | 	runtime.GC() | 
 | 	// At this point x's dead stack slot points to dead memory. | 
 |  | 
 | 	// Trigger a sigpanic. Since this is an implicit panic, we | 
 | 	// don't have an explicit liveness map here. | 
 | 	// Traceback used to use the liveness map of the most recent defer, | 
 | 	// but in that liveness map, x will be live again even though | 
 | 	// it points to dead memory. The fix is to use the liveness | 
 | 	// map of a deferreturn call instead. | 
 | 	*nilp = 0 | 
 | } |