diff --git a/_fixtures/reflecttypefncall.go b/_fixtures/reflecttypefncall.go new file mode 100644 index 00000000..5fc5d30b --- /dev/null +++ b/_fixtures/reflecttypefncall.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "reflect" +) + +func reflectFunc(value reflect.Value) { + fmt.Printf("%s\n", value.Type().Name()) +} + +func main() { + i := 2 + val := reflect.ValueOf(i) + reflectFunc(val) +} diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index 13100434..f5dd79a9 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -760,6 +760,9 @@ func alignAddr(addr, align int64) int64 { } func escapeCheck(v *Variable, name string, stack stack) error { + if v.Unreadable != nil { + return fmt.Errorf("escape check for %s failed, variable unreadable: %v", name, v.Unreadable) + } switch v.Kind { case reflect.Ptr: var w *Variable diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 3c18975e..4fdf77ad 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -6043,3 +6043,13 @@ func TestFollowExec(t *testing.T) { } }) } + +func TestEscapeCheckUnreadable(t *testing.T) { + // A failure in escapeCheck to dereference a field should not cause + // infinite recursion. See issue #3310. + withTestProcessArgs("reflecttypefncall", t, ".", []string{}, protest.AllNonOptimized, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { + setFileBreakpoint(p, t, fixture.Source, 9) + assertNoError(grp.Continue(), t, "Continue") + proc.EvalExpressionWithCalls(grp, p.SelectedGoroutine(), "value.Type()", normalLoadConfig, true) + }) +}