|  | // 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. | 
|  |  | 
|  | // Issue 8048. Incorrect handling of liveness when walking stack | 
|  | // containing faulting frame. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import "runtime" | 
|  |  | 
|  | func main() { | 
|  | test1() | 
|  | test2() | 
|  | test3() | 
|  | } | 
|  |  | 
|  | func test1() { | 
|  | // test1f will panic without its own defer. | 
|  | // The runtime.GC checks that we can walk the stack | 
|  | // at that point and not get confused. | 
|  | // The recover lets test1 exit normally. | 
|  | defer func() { | 
|  | runtime.GC() | 
|  | recover() | 
|  | }() | 
|  | test1f() | 
|  | } | 
|  |  | 
|  | func test1f() { | 
|  | // Because b == false, the if does not execute, | 
|  | // so x == nil, so the println(*x) faults reading | 
|  | // from nil. The compiler will lay out the code | 
|  | // so that the if body occurs above the *x, | 
|  | // so if the liveness info at the *x is used, it will | 
|  | // find the liveness at the call to runtime.GC. | 
|  | // It will think y is live, but y is uninitialized, | 
|  | // and the runtime will crash detecting a bad slice. | 
|  | // The runtime should see that there are no defers | 
|  | // corresponding to this panicked frame and ignore | 
|  | // the frame entirely. | 
|  | var x *int | 
|  | var b bool | 
|  | if b { | 
|  | y := make([]int, 1) | 
|  | runtime.GC() | 
|  | x = &y[0] | 
|  | } | 
|  | println(*x) | 
|  | } | 
|  |  | 
|  | func test2() { | 
|  | // Same as test1, but the fault happens in the function with the defer. | 
|  | // The runtime should see the defer and garbage collect the frame | 
|  | // as if the PC were immediately after the defer statement. | 
|  | defer func() { | 
|  | runtime.GC() | 
|  | recover() | 
|  | }() | 
|  | var x *int | 
|  | var b bool | 
|  | if b { | 
|  | y := make([]int, 1) | 
|  | runtime.GC() | 
|  | x = &y[0] | 
|  | } | 
|  | println(*x) | 
|  | } | 
|  |  | 
|  | func test3() { | 
|  | // Like test1 but avoid array index, which does not | 
|  | // move to end of function on ARM. | 
|  | defer func() { | 
|  | runtime.GC() | 
|  | recover() | 
|  | }() | 
|  | test3setup() | 
|  | test3f() | 
|  | } | 
|  |  | 
|  | func test3setup() { | 
|  | var x uintptr | 
|  | var b bool | 
|  | b = true | 
|  | if b { | 
|  | y := uintptr(123) | 
|  | runtime.GC() | 
|  | x = y | 
|  | } | 
|  | runtime.GC() | 
|  | globl = x | 
|  | } | 
|  |  | 
|  | var globl uintptr | 
|  |  | 
|  | func test3f() { | 
|  | var x *int | 
|  | var b bool | 
|  | if b { | 
|  | y := new(int) | 
|  | runtime.GC() | 
|  | x = y | 
|  | } | 
|  | println(*x) | 
|  | } |