| // 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) | |
| } |