internal/impl: handle extremely old messages
At some point in time, protoc-gen-go actually emitted an XXX_OneofFuncs
with a different signature. Adjust the logic for handling XXX_OneofFuncs
to not assume that the return arguments are in a specific order.
Change-Id: Idd9c09231c4129c655d4a635bb1ae094896a1ff4
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/226980
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/legacy_aberrant_test.go b/internal/impl/legacy_aberrant_test.go
index c51b0c7..905981a 100644
--- a/internal/impl/legacy_aberrant_test.go
+++ b/internal/impl/legacy_aberrant_test.go
@@ -86,7 +86,7 @@
return []protoiface.ExtensionRangeV1{{Start: 10, End: 100}}
}
-func (m *AberrantMessage) XXX_OneofWrappers() []interface{} {
+func (m *AberrantMessage) XXX_OneofFuncs() []interface{} {
return []interface{}{
(*OneofBool)(nil),
(*OneofInt32)(nil),
diff --git a/internal/impl/legacy_message.go b/internal/impl/legacy_message.go
index a723569..06c68e1 100644
--- a/internal/impl/legacy_message.go
+++ b/internal/impl/legacy_message.go
@@ -195,16 +195,15 @@
// Obtain a list of oneof wrapper types.
var oneofWrappers []reflect.Type
- if fn, ok := t.MethodByName("XXX_OneofFuncs"); ok {
- vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3]
- for _, v := range vs.Interface().([]interface{}) {
- oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
- }
- }
- if fn, ok := t.MethodByName("XXX_OneofWrappers"); ok {
- vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0]
- for _, v := range vs.Interface().([]interface{}) {
- oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
+ for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} {
+ if fn, ok := t.MethodByName(method); ok {
+ for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
+ if vs, ok := v.Interface().([]interface{}); ok {
+ for _, v := range vs {
+ oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
+ }
+ }
+ }
}
}
diff --git a/internal/impl/message.go b/internal/impl/message.go
index 65de48a..c1d8902 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -182,11 +182,14 @@
// Derive a mapping of oneof wrappers to fields.
oneofWrappers := mi.OneofWrappers
- if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
- oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
- }
- if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
- oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
+ for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} {
+ if fn, ok := reflect.PtrTo(t).MethodByName(method); ok {
+ for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
+ if vs, ok := v.Interface().([]interface{}); ok {
+ oneofWrappers = vs
+ }
+ }
+ }
}
for _, v := range oneofWrappers {
tf := reflect.TypeOf(v).Elem()