1// run
2
3// Copyright 2020 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
7package main
8
9import "fmt"
10
11const N = 40
12
13func main() {
14	var x [N]int // stack-allocated memory
15	for i := range x {
16		x[i] = 0x999
17	}
18
19	// This defer checks to see if x is uncorrupted.
20	defer func(p *[N]int) {
21		recover()
22		for i := range p {
23			if p[i] != 0x999 {
24				for j := range p {
25					fmt.Printf("p[%d]=0x%x\n", j, p[j])
26				}
27				panic("corrupted stack variable")
28			}
29		}
30	}(&x)
31
32	// This defer starts a new goroutine, which will (hopefully)
33	// overwrite x on the garbage stack.
34	defer func() {
35		c := make(chan bool)
36		go func() {
37			useStack(1000)
38			c <- true
39		}()
40		<-c
41
42	}()
43
44	// This defer causes a stack copy.
45	// The old stack is now garbage.
46	defer func() {
47		useStack(1000)
48	}()
49
50	// Trigger a segfault.
51	*g = 0
52
53	// Make the return statement unreachable.
54	// That makes the stack map at the deferreturn call empty.
55	// In particular, the argument to the first defer is not
56	// marked as a pointer, so it doesn't get adjusted
57	// during the stack copy.
58	for {
59	}
60}
61
62var g *int64
63
64func useStack(n int) {
65	if n == 0 {
66		return
67	}
68	useStack(n - 1)
69}
70