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