Home | History | Annotate | Download | only in fixedbugs
      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 }
    108