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 }