Source file test/fixedbugs/issue40629.go

     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  
     7  package main
     8  
     9  import "fmt"
    10  
    11  const N = 40
    12  
    13  func 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  
    62  var g *int64
    63  
    64  func useStack(n int) {
    65  	if n == 0 {
    66  		return
    67  	}
    68  	useStack(n - 1)
    69  }
    70  

View as plain text