1// run 2 3// Copyright 2014 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// Issue 8048. Incorrect handling of liveness when walking stack 8// containing faulting frame. 9 10package main 11 12import "runtime" 13 14func main() { 15 test1() 16 test2() 17 test3() 18} 19 20func test1() { 21 // test1f will panic without its own defer. 22 // The runtime.GC checks that we can walk the stack 23 // at that point and not get confused. 24 // The recover lets test1 exit normally. 25 defer func() { 26 runtime.GC() 27 recover() 28 }() 29 test1f() 30} 31 32func test1f() { 33 // Because b == false, the if does not execute, 34 // so x == nil, so the println(*x) faults reading 35 // from nil. The compiler will lay out the code 36 // so that the if body occurs above the *x, 37 // so if the liveness info at the *x is used, it will 38 // find the liveness at the call to runtime.GC. 39 // It will think y is live, but y is uninitialized, 40 // and the runtime will crash detecting a bad slice. 41 // The runtime should see that there are no defers 42 // corresponding to this panicked frame and ignore 43 // the frame entirely. 44 var x *int 45 var b bool 46 if b { 47 y := make([]int, 1) 48 runtime.GC() 49 x = &y[0] 50 } 51 println(*x) 52} 53 54func test2() { 55 // Same as test1, but the fault happens in the function with the defer. 56 // The runtime should see the defer and garbage collect the frame 57 // as if the PC were immediately after the defer statement. 58 defer func() { 59 runtime.GC() 60 recover() 61 }() 62 var x *int 63 var b bool 64 if b { 65 y := make([]int, 1) 66 runtime.GC() 67 x = &y[0] 68 } 69 println(*x) 70} 71 72func test3() { 73 // Like test1 but avoid array index, which does not 74 // move to end of function on ARM. 75 defer func() { 76 runtime.GC() 77 recover() 78 }() 79 test3setup() 80 test3f() 81} 82 83func test3setup() { 84 var x uintptr 85 var b bool 86 b = true 87 if b { 88 y := uintptr(123) 89 runtime.GC() 90 x = y 91 } 92 runtime.GC() 93 globl = x 94} 95 96var globl uintptr 97 98func test3f() { 99 var x *int 100 var b bool 101 if b { 102 y := new(int) 103 runtime.GC() 104 x = y 105 } 106 println(*x) 107} 108