modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/fixedbugs/issue16095.go (about)

     1  // run
     2  
     3  // Copyright 2016 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 (
    10  	"fmt"
    11  	"runtime"
    12  )
    13  
    14  var sink *[20]byte
    15  
    16  func f() (x [20]byte) {
    17  	// Initialize x.
    18  	for i := range x {
    19  		x[i] = byte(i)
    20  	}
    21  
    22  	// Force x to be allocated on the heap.
    23  	sink = &x
    24  	sink = nil
    25  
    26  	// Go to deferreturn after the panic below.
    27  	defer func() {
    28  		recover()
    29  	}()
    30  
    31  	// This call collects the heap-allocated version of x (oops!)
    32  	runtime.GC()
    33  
    34  	// Allocate that same object again and clobber it.
    35  	y := new([20]byte)
    36  	for i := 0; i < 20; i++ {
    37  		y[i] = 99
    38  	}
    39  	// Make sure y is heap allocated.
    40  	sink = y
    41  
    42  	panic(nil)
    43  
    44  	// After the recover we reach the deferreturn, which
    45  	// copies the heap version of x back to the stack.
    46  	// It gets the pointer to x from a stack slot that was
    47  	// not marked as live during the call to runtime.GC().
    48  }
    49  
    50  var sinkint int
    51  
    52  func g(p *int) (x [20]byte) {
    53  	// Initialize x.
    54  	for i := range x {
    55  		x[i] = byte(i)
    56  	}
    57  
    58  	// Force x to be allocated on the heap.
    59  	sink = &x
    60  	sink = nil
    61  
    62  	// Go to deferreturn after the panic below.
    63  	defer func() {
    64  		recover()
    65  	}()
    66  
    67  	// This call collects the heap-allocated version of x (oops!)
    68  	runtime.GC()
    69  
    70  	// Allocate that same object again and clobber it.
    71  	y := new([20]byte)
    72  	for i := 0; i < 20; i++ {
    73  		y[i] = 99
    74  	}
    75  	// Make sure y is heap allocated.
    76  	sink = y
    77  
    78  	// panic with a non-call (with no fallthrough)
    79  	for {
    80  		sinkint = *p
    81  	}
    82  
    83  	// After the recover we reach the deferreturn, which
    84  	// copies the heap version of x back to the stack.
    85  	// It gets the pointer to x from a stack slot that was
    86  	// not marked as live during the call to runtime.GC().
    87  }
    88  
    89  func main() {
    90  	x := f()
    91  	for i, v := range x {
    92  		if v != byte(i) {
    93  			fmt.Printf("%v\n", x)
    94  			panic("bad f")
    95  		}
    96  	}
    97  	x = g(nil)
    98  	for i, v := range x {
    99  		if v != byte(i) {
   100  			fmt.Printf("%v\n", x)
   101  			panic("bad g")
   102  		}
   103  	}
   104  }