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

     1  // run
     2  
     3  // Copyright 2014 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  // Issue 8048. Incorrect handling of liveness when walking stack
     8  // containing faulting frame.
     9  
    10  package main
    11  
    12  import "runtime"
    13  
    14  func main() {
    15  	test1()
    16  	test2()
    17  	test3()
    18  }
    19  
    20  func test1() {
    21  	// test1f will panic without its own defer.
    22  	// The runtime.GC checks that we can walk the stack
    23  	// at that point and not get confused.
    24  	// The recover lets test1 exit normally.
    25  	defer func() {
    26  		runtime.GC()
    27  		recover()
    28  	}()
    29  	test1f()
    30  }
    31  
    32  func test1f() {
    33  	// Because b == false, the if does not execute,
    34  	// so x == nil, so the println(*x) faults reading
    35  	// from nil. The compiler will lay out the code
    36  	// so that the if body occurs above the *x,
    37  	// so if the liveness info at the *x is used, it will
    38  	// find the liveness at the call to runtime.GC.
    39  	// It will think y is live, but y is uninitialized,
    40  	// and the runtime will crash detecting a bad slice.
    41  	// The runtime should see that there are no defers
    42  	// corresponding to this panicked frame and ignore
    43  	// the frame entirely.
    44  	var x *int
    45  	var b bool
    46  	if b {
    47  		y := make([]int, 1)
    48  		runtime.GC()
    49  		x = &y[0]
    50  	}
    51  	println(*x)
    52  }
    53  
    54  func test2() {
    55  	// Same as test1, but the fault happens in the function with the defer.
    56  	// The runtime should see the defer and garbage collect the frame
    57  	// as if the PC were immediately after the defer statement.
    58  	defer func() {
    59  		runtime.GC()
    60  		recover()
    61  	}()
    62  	var x *int
    63  	var b bool
    64  	if b {
    65  		y := make([]int, 1)
    66  		runtime.GC()
    67  		x = &y[0]
    68  	}
    69  	println(*x)
    70  }
    71  
    72  func test3() {
    73  	// Like test1 but avoid array index, which does not
    74  	// move to end of function on ARM.
    75  	defer func() {
    76  		runtime.GC()
    77  		recover()
    78  	}()
    79  	test3setup()
    80  	test3f()
    81  }
    82  
    83  func test3setup() {
    84  	var x uintptr
    85  	var b bool
    86  	b = true
    87  	if b {
    88  		y := uintptr(123)
    89  		runtime.GC()
    90  		x = y
    91  	}
    92  	runtime.GC()
    93  	globl = x
    94  }
    95  
    96  var globl uintptr
    97  
    98  func test3f() {
    99  	var x *int
   100  	var b bool
   101  	if b {
   102  		y := new(int)
   103  		runtime.GC()
   104  		x = y
   105  	}
   106  	println(*x)
   107  }