Source file test/fixedbugs/issue8048.go
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 10 package main 11 12 import "runtime" 13 14 func main() { 15 test1() 16 test2() 17 test3() 18 } 19 20 func 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 32 func 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 54 func 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 72 func 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 83 func 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 96 var globl uintptr 97 98 func 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