Source file test/fixedbugs/issue27695b.go

     1  // run
     2  
     3  // Copyright 2018 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  // Make sure return values aren't scanned until they
     8  // are initialized, when calling functions and methods
     9  // via reflect.
    10  
    11  package main
    12  
    13  import (
    14  	"reflect"
    15  	"runtime"
    16  	"unsafe"
    17  )
    18  
    19  var badPtr uintptr
    20  
    21  var sink []byte
    22  
    23  func init() {
    24  	// Allocate large enough to use largeAlloc.
    25  	b := make([]byte, 1<<16-1)
    26  	sink = b // force heap allocation
    27  	//  Any space between the object and the end of page is invalid to point to.
    28  	badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
    29  }
    30  
    31  func f(d func() *byte) *byte {
    32  	// Initialize callee args section with a bad pointer.
    33  	g(badPtr)
    34  
    35  	// Then call a function which returns a pointer.
    36  	// That return slot starts out holding a bad pointer.
    37  	return d()
    38  }
    39  
    40  //go:noinline
    41  func g(x uintptr) {
    42  }
    43  
    44  type T struct {
    45  }
    46  
    47  func (t *T) Foo() *byte {
    48  	runtime.GC()
    49  	return nil
    50  }
    51  
    52  func main() {
    53  	// Functions
    54  	d := reflect.MakeFunc(reflect.TypeOf(func() *byte { return nil }),
    55  		func(args []reflect.Value) []reflect.Value {
    56  			runtime.GC()
    57  			return []reflect.Value{reflect.ValueOf((*byte)(nil))}
    58  		}).Interface().(func() *byte)
    59  	f(d)
    60  
    61  	// Methods
    62  	e := reflect.ValueOf(&T{}).Method(0).Interface().(func() *byte)
    63  	f(e)
    64  }
    65  

View as plain text