| // run | 
 |  | 
 | // Copyright 2014 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. | 
 |  | 
 | // The liveness code used to say that, in func g, s was live | 
 | // starting at its declaration, because it appears to have its | 
 | // address taken by the closure (different s, but the parser | 
 | // gets slightly confused, a separate bug). The liveness analysis | 
 | // saw s as having its address taken but the register optimizer | 
 | // did not. This mismatch meant that s would be marked live | 
 | // (and therefore initialized) at the call to f, but the register optimizer | 
 | // would optimize away the initialization of s before f, causing the | 
 | // garbage collector to use unused data. | 
 | // The register optimizer has been changed to respect the | 
 | // same "address taken" flag that the liveness analysis uses, | 
 | // even if it cannot see any address being taken in the actual | 
 | // machine code. This is conservative but keeps the two consistent, | 
 | // which is the most important thing. | 
 |  | 
 | package main | 
 |  | 
 | import "runtime" | 
 |  | 
 | var c bool | 
 |  | 
 | func f() interface{} { | 
 | 	if c { // disable inlining | 
 | 		f() | 
 | 	} | 
 | 	runtime.GC() | 
 | 	return nil | 
 | } | 
 |  | 
 | func g() { | 
 | 	if c { // disable inlining | 
 | 		g() | 
 | 	} | 
 | 	var s interface{} | 
 | 	_ = func() { | 
 | 		s := f() | 
 | 		_ = s | 
 | 	} | 
 | 	s = f() | 
 | 	useiface(s) | 
 | 	useiface(s) | 
 | } | 
 |  | 
 | func useiface(x interface{}) { | 
 | 	if c {	// disable inlining | 
 | 		useiface(x) | 
 | 	} | 
 | } | 
 |  | 
 | func h() { | 
 | 	if c { // disable inlining | 
 | 		h() | 
 | 	} | 
 | 	var x [16]uintptr | 
 | 	for i := range x { | 
 | 		x[i] = 1 | 
 | 	} | 
 | 	 | 
 | 	useint(x[0]) | 
 | 	useint(x[1]) | 
 | 	useint(x[2]) | 
 | 	useint(x[3]) | 
 | } | 
 |  | 
 | func useint(x uintptr) { | 
 | 	if c {	// disable inlining | 
 | 		useint(x) | 
 | 	} | 
 | } | 
 |  | 
 | func main() { | 
 | 	// scribble non-zero values on stack | 
 | 	h() | 
 | 	// call function that used to let the garbage collector | 
 | 	// see uninitialized stack values; it will see the | 
 | 	// nonzero values. | 
 | 	g() | 
 | } | 
 |  | 
 | func big(x int) { | 
 | 	if x >= 0 { | 
 | 		big(x-1) | 
 | 	} | 
 | } |