зеркало из https://github.com/CryptoPro/go.git
70 строки
1.2 KiB
Go
70 строки
1.2 KiB
Go
// run
|
|
|
|
// Copyright 2020 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.
|
|
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
const N = 40
|
|
|
|
func main() {
|
|
var x [N]int // stack-allocated memory
|
|
for i := range x {
|
|
x[i] = 0x999
|
|
}
|
|
|
|
// This defer checks to see if x is uncorrupted.
|
|
defer func(p *[N]int) {
|
|
recover()
|
|
for i := range p {
|
|
if p[i] != 0x999 {
|
|
for j := range p {
|
|
fmt.Printf("p[%d]=0x%x\n", j, p[j])
|
|
}
|
|
panic("corrupted stack variable")
|
|
}
|
|
}
|
|
}(&x)
|
|
|
|
// This defer starts a new goroutine, which will (hopefully)
|
|
// overwrite x on the garbage stack.
|
|
defer func() {
|
|
c := make(chan bool)
|
|
go func() {
|
|
useStack(1000)
|
|
c <- true
|
|
}()
|
|
<-c
|
|
|
|
}()
|
|
|
|
// This defer causes a stack copy.
|
|
// The old stack is now garbage.
|
|
defer func() {
|
|
useStack(1000)
|
|
}()
|
|
|
|
// Trigger a segfault.
|
|
*g = 0
|
|
|
|
// Make the return statement unreachable.
|
|
// That makes the stack map at the deferreturn call empty.
|
|
// In particular, the argument to the first defer is not
|
|
// marked as a pointer, so it doesn't get adjusted
|
|
// during the stack copy.
|
|
for {
|
|
}
|
|
}
|
|
|
|
var g *int64
|
|
|
|
func useStack(n int) {
|
|
if n == 0 {
|
|
return
|
|
}
|
|
useStack(n - 1)
|
|
}
|