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