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