diff options
Diffstat (limited to 'libgo/go/reflect/all_test.go')
-rw-r--r-- | libgo/go/reflect/all_test.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index f51e95fd734..6b143df00e1 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -26,6 +26,8 @@ import ( "unsafe" ) +var sink interface{} + func TestBool(t *testing.T) { v := ValueOf(true) if v.Bool() != true { @@ -5348,6 +5350,72 @@ func TestCallGC(t *testing.T) { f2("four", "five5", "six666", "seven77", "eight888") } +// Issue 18635 (function version). +func TestKeepFuncLive(t *testing.T) { + // Test that we keep makeFuncImpl live as long as it is + // referenced on the stack. + typ := TypeOf(func(i int) {}) + var f, g func(in []Value) []Value + f = func(in []Value) []Value { + clobber() + i := int(in[0].Int()) + if i > 0 { + // We can't use Value.Call here because + // runtime.call* will keep the makeFuncImpl + // alive. However, by converting it to an + // interface value and calling that, + // reflect.callReflect is the only thing that + // can keep the makeFuncImpl live. + // + // Alternate between f and g so that if we do + // reuse the memory prematurely it's more + // likely to get obviously corrupted. + MakeFunc(typ, g).Interface().(func(i int))(i - 1) + } + return nil + } + g = func(in []Value) []Value { + clobber() + i := int(in[0].Int()) + MakeFunc(typ, f).Interface().(func(i int))(i) + return nil + } + MakeFunc(typ, f).Call([]Value{ValueOf(10)}) +} + +// Issue 18635 (method version). +type KeepMethodLive struct{} + +func (k KeepMethodLive) Method1(i int) { + clobber() + if i > 0 { + ValueOf(k).MethodByName("Method2").Interface().(func(i int))(i - 1) + } +} + +func (k KeepMethodLive) Method2(i int) { + clobber() + ValueOf(k).MethodByName("Method1").Interface().(func(i int))(i) +} + +func TestKeepMethodLive(t *testing.T) { + // Test that we keep methodValue live as long as it is + // referenced on the stack. + KeepMethodLive{}.Method1(10) +} + +// clobber tries to clobber unreachable memory. +func clobber() { + runtime.GC() + for i := 1; i < 32; i++ { + for j := 0; j < 10; j++ { + obj := make([]*byte, i) + sink = obj + } + } + runtime.GC() +} + type funcLayoutTest struct { rcvr, t Type size, argsize, retOffset uintptr |