From 77b4beba2fd892a3f8e9da527fdad031f6ecc613 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Carvalho?= Date: Fri, 28 Jul 2017 20:31:20 -0300 Subject: [PATCH] reflect: handle types with unexported methods before exported ones The method Method expects index to be an index of exported fields, but, before this change, the index used by MethodByName could take into account unexported fields if those happened sort before the exported one. Fixes #21177 Change-Id: I90bb64a47b23e2e43fdd2b8a1e0a2c9a8a63ded2 Reviewed-on: https://go-review.googlesource.com/51810 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/reflect/all_test.go | 19 +++++++++++++++++++ src/reflect/type.go | 8 ++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 5a5c91b751..962c326c03 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -5521,6 +5521,25 @@ func TestKeepFuncLive(t *testing.T) { MakeFunc(typ, f).Call([]Value{ValueOf(10)}) } +type UnExportedFirst int + +func (i UnExportedFirst) ΦExported() {} +func (i UnExportedFirst) unexported() {} + +// Issue 21177 +func TestMethodByNameUnExportedFirst(t *testing.T) { + defer func() { + if recover() != nil { + t.Errorf("should not panic") + } + }() + typ := TypeOf(UnExportedFirst(0)) + m, _ := typ.MethodByName("ΦExported") + if m.Name != "ΦExported" { + t.Errorf("got %s, expected ΦExported", m.Name) + } +} + // Issue 18635 (method version). type KeepMethodLive struct{} diff --git a/src/reflect/type.go b/src/reflect/type.go index dbb65f14bf..9f02219c8e 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -871,11 +871,15 @@ func (t *rtype) MethodByName(name string) (m Method, ok bool) { return Method{}, false } utmethods := ut.methods() + var eidx int for i := 0; i < int(ut.mcount); i++ { p := utmethods[i] pname := t.nameOff(p.name) - if pname.isExported() && pname.name() == name { - return t.Method(i), true + if pname.isExported() { + if pname.name() == name { + return t.Method(eidx), true + } + eidx++ } } return Method{}, false -- 2.50.0