diff options
| author | André Carvalho <asantostc@gmail.com> | 2017-07-28 20:31:20 -0300 |
|---|---|---|
| committer | Ian Lance Taylor <iant@golang.org> | 2017-08-23 23:48:49 +0000 |
| commit | 77b4beba2fd892a3f8e9da527fdad031f6ecc613 (patch) | |
| tree | 597fc82c2e5d6e5c5608e8949525ed5c886b4232 | |
| parent | e0ab505a97eed8773ea16842f2748b6d518fedd9 (diff) | |
| download | go-77b4beba2fd892a3f8e9da527fdad031f6ecc613.tar.xz | |
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 <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
| -rw-r--r-- | src/reflect/all_test.go | 19 | ||||
| -rw-r--r-- | 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 |
