1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package impl 6 7import ( 8 "fmt" 9 "reflect" 10 "strings" 11 "sync" 12 13 "google.golang.org/protobuf/internal/descopts" 14 ptag "google.golang.org/protobuf/internal/encoding/tag" 15 "google.golang.org/protobuf/internal/errors" 16 "google.golang.org/protobuf/internal/filedesc" 17 "google.golang.org/protobuf/internal/strs" 18 "google.golang.org/protobuf/reflect/protoreflect" 19 pref "google.golang.org/protobuf/reflect/protoreflect" 20 "google.golang.org/protobuf/runtime/protoiface" 21 piface "google.golang.org/protobuf/runtime/protoiface" 22) 23 24// legacyWrapMessage wraps v as a protoreflect.Message, 25// where v must be a *struct kind and not implement the v2 API already. 26func legacyWrapMessage(v reflect.Value) pref.Message { 27 typ := v.Type() 28 if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Struct { 29 return aberrantMessage{v: v} 30 } 31 mt := legacyLoadMessageInfo(typ, "") 32 return mt.MessageOf(v.Interface()) 33} 34 35var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo 36 37// legacyLoadMessageInfo dynamically loads a *MessageInfo for t, 38// where t must be a *struct kind and not implement the v2 API already. 39// The provided name is used if it cannot be determined from the message. 40func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo { 41 // Fast-path: check if a MessageInfo is cached for this concrete type. 42 if mt, ok := legacyMessageTypeCache.Load(t); ok { 43 return mt.(*MessageInfo) 44 } 45 46 // Slow-path: derive message descriptor and initialize MessageInfo. 47 mi := &MessageInfo{ 48 Desc: legacyLoadMessageDesc(t, name), 49 GoReflectType: t, 50 } 51 52 v := reflect.Zero(t).Interface() 53 if _, ok := v.(legacyMarshaler); ok { 54 mi.methods.Marshal = legacyMarshal 55 56 // We have no way to tell whether the type's Marshal method 57 // supports deterministic serialization or not, but this 58 // preserves the v1 implementation's behavior of always 59 // calling Marshal methods when present. 60 mi.methods.Flags |= piface.SupportMarshalDeterministic 61 } 62 if _, ok := v.(legacyUnmarshaler); ok { 63 mi.methods.Unmarshal = legacyUnmarshal 64 } 65 if _, ok := v.(legacyMerger); ok { 66 mi.methods.Merge = legacyMerge 67 } 68 69 if mi, ok := legacyMessageTypeCache.LoadOrStore(t, mi); ok { 70 return mi.(*MessageInfo) 71 } 72 return mi 73} 74 75var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor 76 77// LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type, 78// which must be a *struct kind and not implement the v2 API already. 79// 80// This is exported for testing purposes. 81func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor { 82 return legacyLoadMessageDesc(t, "") 83} 84func legacyLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { 85 // Fast-path: check if a MessageDescriptor is cached for this concrete type. 86 if mi, ok := legacyMessageDescCache.Load(t); ok { 87 return mi.(pref.MessageDescriptor) 88 } 89 90 // Slow-path: initialize MessageDescriptor from the raw descriptor. 91 mv := reflect.Zero(t).Interface() 92 if _, ok := mv.(pref.ProtoMessage); ok { 93 panic(fmt.Sprintf("%v already implements proto.Message", t)) 94 } 95 mdV1, ok := mv.(messageV1) 96 if !ok { 97 return aberrantLoadMessageDesc(t, name) 98 } 99 100 // If this is a dynamic message type where there isn't a 1-1 mapping between 101 // Go and protobuf types, calling the Descriptor method on the zero value of 102 // the message type isn't likely to work. If it panics, swallow the panic and 103 // continue as if the Descriptor method wasn't present. 104 b, idxs := func() ([]byte, []int) { 105 defer func() { 106 recover() 107 }() 108 return mdV1.Descriptor() 109 }() 110 if b == nil { 111 return aberrantLoadMessageDesc(t, name) 112 } 113 114 // If the Go type has no fields, then this might be a proto3 empty message 115 // from before the size cache was added. If there are any fields, check to 116 // see that at least one of them looks like something we generated. 117 if nfield := t.Elem().NumField(); nfield > 0 { 118 hasProtoField := false 119 for i := 0; i < nfield; i++ { 120 f := t.Elem().Field(i) 121 if f.Tag.Get("protobuf") != "" || f.Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(f.Name, "XXX_") { 122 hasProtoField = true 123 break 124 } 125 } 126 if !hasProtoField { 127 return aberrantLoadMessageDesc(t, name) 128 } 129 } 130 131 md := legacyLoadFileDesc(b).Messages().Get(idxs[0]) 132 for _, i := range idxs[1:] { 133 md = md.Messages().Get(i) 134 } 135 if name != "" && md.FullName() != name { 136 panic(fmt.Sprintf("mismatching message name: got %v, want %v", md.FullName(), name)) 137 } 138 if md, ok := legacyMessageDescCache.LoadOrStore(t, md); ok { 139 return md.(protoreflect.MessageDescriptor) 140 } 141 return md 142} 143 144var ( 145 aberrantMessageDescLock sync.Mutex 146 aberrantMessageDescCache map[reflect.Type]protoreflect.MessageDescriptor 147) 148 149// aberrantLoadMessageDesc returns an MessageDescriptor derived from the Go type, 150// which must not implement protoreflect.ProtoMessage or messageV1. 151// 152// This is a best-effort derivation of the message descriptor using the protobuf 153// tags on the struct fields. 154func aberrantLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { 155 aberrantMessageDescLock.Lock() 156 defer aberrantMessageDescLock.Unlock() 157 if aberrantMessageDescCache == nil { 158 aberrantMessageDescCache = make(map[reflect.Type]protoreflect.MessageDescriptor) 159 } 160 return aberrantLoadMessageDescReentrant(t, name) 161} 162func aberrantLoadMessageDescReentrant(t reflect.Type, name pref.FullName) pref.MessageDescriptor { 163 // Fast-path: check if an MessageDescriptor is cached for this concrete type. 164 if md, ok := aberrantMessageDescCache[t]; ok { 165 return md 166 } 167 168 // Slow-path: construct a descriptor from the Go struct type (best-effort). 169 // Cache the MessageDescriptor early on so that we can resolve internal 170 // cyclic references. 171 md := &filedesc.Message{L2: new(filedesc.MessageL2)} 172 md.L0.FullName = aberrantDeriveMessageName(t, name) 173 md.L0.ParentFile = filedesc.SurrogateProto2 174 aberrantMessageDescCache[t] = md 175 176 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { 177 return md 178 } 179 180 // Try to determine if the message is using proto3 by checking scalars. 181 for i := 0; i < t.Elem().NumField(); i++ { 182 f := t.Elem().Field(i) 183 if tag := f.Tag.Get("protobuf"); tag != "" { 184 switch f.Type.Kind() { 185 case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: 186 md.L0.ParentFile = filedesc.SurrogateProto3 187 } 188 for _, s := range strings.Split(tag, ",") { 189 if s == "proto3" { 190 md.L0.ParentFile = filedesc.SurrogateProto3 191 } 192 } 193 } 194 } 195 196 // Obtain a list of oneof wrapper types. 197 var oneofWrappers []reflect.Type 198 for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { 199 if fn, ok := t.MethodByName(method); ok { 200 for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { 201 if vs, ok := v.Interface().([]interface{}); ok { 202 for _, v := range vs { 203 oneofWrappers = append(oneofWrappers, reflect.TypeOf(v)) 204 } 205 } 206 } 207 } 208 } 209 210 // Obtain a list of the extension ranges. 211 if fn, ok := t.MethodByName("ExtensionRangeArray"); ok { 212 vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0] 213 for i := 0; i < vs.Len(); i++ { 214 v := vs.Index(i) 215 md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, [2]pref.FieldNumber{ 216 pref.FieldNumber(v.FieldByName("Start").Int()), 217 pref.FieldNumber(v.FieldByName("End").Int() + 1), 218 }) 219 md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, nil) 220 } 221 } 222 223 // Derive the message fields by inspecting the struct fields. 224 for i := 0; i < t.Elem().NumField(); i++ { 225 f := t.Elem().Field(i) 226 if tag := f.Tag.Get("protobuf"); tag != "" { 227 tagKey := f.Tag.Get("protobuf_key") 228 tagVal := f.Tag.Get("protobuf_val") 229 aberrantAppendField(md, f.Type, tag, tagKey, tagVal) 230 } 231 if tag := f.Tag.Get("protobuf_oneof"); tag != "" { 232 n := len(md.L2.Oneofs.List) 233 md.L2.Oneofs.List = append(md.L2.Oneofs.List, filedesc.Oneof{}) 234 od := &md.L2.Oneofs.List[n] 235 od.L0.FullName = md.FullName().Append(pref.Name(tag)) 236 od.L0.ParentFile = md.L0.ParentFile 237 od.L0.Parent = md 238 od.L0.Index = n 239 240 for _, t := range oneofWrappers { 241 if t.Implements(f.Type) { 242 f := t.Elem().Field(0) 243 if tag := f.Tag.Get("protobuf"); tag != "" { 244 aberrantAppendField(md, f.Type, tag, "", "") 245 fd := &md.L2.Fields.List[len(md.L2.Fields.List)-1] 246 fd.L1.ContainingOneof = od 247 od.L1.Fields.List = append(od.L1.Fields.List, fd) 248 } 249 } 250 } 251 } 252 } 253 254 return md 255} 256 257func aberrantDeriveMessageName(t reflect.Type, name pref.FullName) pref.FullName { 258 if name.IsValid() { 259 return name 260 } 261 func() { 262 defer func() { recover() }() // swallow possible nil panics 263 if m, ok := reflect.Zero(t).Interface().(interface{ XXX_MessageName() string }); ok { 264 name = pref.FullName(m.XXX_MessageName()) 265 } 266 }() 267 if name.IsValid() { 268 return name 269 } 270 if t.Kind() == reflect.Ptr { 271 t = t.Elem() 272 } 273 return AberrantDeriveFullName(t) 274} 275 276func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey, tagVal string) { 277 t := goType 278 isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct 279 isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 280 if isOptional || isRepeated { 281 t = t.Elem() 282 } 283 fd := ptag.Unmarshal(tag, t, placeholderEnumValues{}).(*filedesc.Field) 284 285 // Append field descriptor to the message. 286 n := len(md.L2.Fields.List) 287 md.L2.Fields.List = append(md.L2.Fields.List, *fd) 288 fd = &md.L2.Fields.List[n] 289 fd.L0.FullName = md.FullName().Append(fd.Name()) 290 fd.L0.ParentFile = md.L0.ParentFile 291 fd.L0.Parent = md 292 fd.L0.Index = n 293 294 if fd.L1.IsWeak || fd.L1.HasPacked { 295 fd.L1.Options = func() pref.ProtoMessage { 296 opts := descopts.Field.ProtoReflect().New() 297 if fd.L1.IsWeak { 298 opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true)) 299 } 300 if fd.L1.HasPacked { 301 opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.IsPacked)) 302 } 303 return opts.Interface() 304 } 305 } 306 307 // Populate Enum and Message. 308 if fd.Enum() == nil && fd.Kind() == pref.EnumKind { 309 switch v := reflect.Zero(t).Interface().(type) { 310 case pref.Enum: 311 fd.L1.Enum = v.Descriptor() 312 default: 313 fd.L1.Enum = LegacyLoadEnumDesc(t) 314 } 315 } 316 if fd.Message() == nil && (fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind) { 317 switch v := reflect.Zero(t).Interface().(type) { 318 case pref.ProtoMessage: 319 fd.L1.Message = v.ProtoReflect().Descriptor() 320 case messageV1: 321 fd.L1.Message = LegacyLoadMessageDesc(t) 322 default: 323 if t.Kind() == reflect.Map { 324 n := len(md.L1.Messages.List) 325 md.L1.Messages.List = append(md.L1.Messages.List, filedesc.Message{L2: new(filedesc.MessageL2)}) 326 md2 := &md.L1.Messages.List[n] 327 md2.L0.FullName = md.FullName().Append(pref.Name(strs.MapEntryName(string(fd.Name())))) 328 md2.L0.ParentFile = md.L0.ParentFile 329 md2.L0.Parent = md 330 md2.L0.Index = n 331 332 md2.L1.IsMapEntry = true 333 md2.L2.Options = func() pref.ProtoMessage { 334 opts := descopts.Message.ProtoReflect().New() 335 opts.Set(opts.Descriptor().Fields().ByName("map_entry"), protoreflect.ValueOfBool(true)) 336 return opts.Interface() 337 } 338 339 aberrantAppendField(md2, t.Key(), tagKey, "", "") 340 aberrantAppendField(md2, t.Elem(), tagVal, "", "") 341 342 fd.L1.Message = md2 343 break 344 } 345 fd.L1.Message = aberrantLoadMessageDescReentrant(t, "") 346 } 347 } 348} 349 350type placeholderEnumValues struct { 351 protoreflect.EnumValueDescriptors 352} 353 354func (placeholderEnumValues) ByNumber(n pref.EnumNumber) pref.EnumValueDescriptor { 355 return filedesc.PlaceholderEnumValue(pref.FullName(fmt.Sprintf("UNKNOWN_%d", n))) 356} 357 358// legacyMarshaler is the proto.Marshaler interface superseded by protoiface.Methoder. 359type legacyMarshaler interface { 360 Marshal() ([]byte, error) 361} 362 363// legacyUnmarshaler is the proto.Unmarshaler interface superseded by protoiface.Methoder. 364type legacyUnmarshaler interface { 365 Unmarshal([]byte) error 366} 367 368// legacyMerger is the proto.Merger interface superseded by protoiface.Methoder. 369type legacyMerger interface { 370 Merge(protoiface.MessageV1) 371} 372 373var legacyProtoMethods = &piface.Methods{ 374 Marshal: legacyMarshal, 375 Unmarshal: legacyUnmarshal, 376 Merge: legacyMerge, 377 378 // We have no way to tell whether the type's Marshal method 379 // supports deterministic serialization or not, but this 380 // preserves the v1 implementation's behavior of always 381 // calling Marshal methods when present. 382 Flags: piface.SupportMarshalDeterministic, 383} 384 385func legacyMarshal(in piface.MarshalInput) (piface.MarshalOutput, error) { 386 v := in.Message.(unwrapper).protoUnwrap() 387 marshaler, ok := v.(legacyMarshaler) 388 if !ok { 389 return piface.MarshalOutput{}, errors.New("%T does not implement Marshal", v) 390 } 391 out, err := marshaler.Marshal() 392 if in.Buf != nil { 393 out = append(in.Buf, out...) 394 } 395 return piface.MarshalOutput{ 396 Buf: out, 397 }, err 398} 399 400func legacyUnmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) { 401 v := in.Message.(unwrapper).protoUnwrap() 402 unmarshaler, ok := v.(legacyUnmarshaler) 403 if !ok { 404 return piface.UnmarshalOutput{}, errors.New("%T does not implement Marshal", v) 405 } 406 return piface.UnmarshalOutput{}, unmarshaler.Unmarshal(in.Buf) 407} 408 409func legacyMerge(in piface.MergeInput) piface.MergeOutput { 410 dstv := in.Destination.(unwrapper).protoUnwrap() 411 merger, ok := dstv.(legacyMerger) 412 if !ok { 413 return piface.MergeOutput{} 414 } 415 merger.Merge(Export{}.ProtoMessageV1Of(in.Source)) 416 return piface.MergeOutput{Flags: piface.MergeComplete} 417} 418 419// aberrantMessageType implements MessageType for all types other than pointer-to-struct. 420type aberrantMessageType struct { 421 t reflect.Type 422} 423 424func (mt aberrantMessageType) New() pref.Message { 425 return aberrantMessage{reflect.Zero(mt.t)} 426} 427func (mt aberrantMessageType) Zero() pref.Message { 428 return aberrantMessage{reflect.Zero(mt.t)} 429} 430func (mt aberrantMessageType) GoType() reflect.Type { 431 return mt.t 432} 433func (mt aberrantMessageType) Descriptor() pref.MessageDescriptor { 434 return LegacyLoadMessageDesc(mt.t) 435} 436 437// aberrantMessage implements Message for all types other than pointer-to-struct. 438// 439// When the underlying type implements legacyMarshaler or legacyUnmarshaler, 440// the aberrant Message can be marshaled or unmarshaled. Otherwise, there is 441// not much that can be done with values of this type. 442type aberrantMessage struct { 443 v reflect.Value 444} 445 446func (m aberrantMessage) ProtoReflect() pref.Message { 447 return m 448} 449 450func (m aberrantMessage) Descriptor() pref.MessageDescriptor { 451 return LegacyLoadMessageDesc(m.v.Type()) 452} 453func (m aberrantMessage) Type() pref.MessageType { 454 return aberrantMessageType{m.v.Type()} 455} 456func (m aberrantMessage) New() pref.Message { 457 return aberrantMessage{reflect.Zero(m.v.Type())} 458} 459func (m aberrantMessage) Interface() pref.ProtoMessage { 460 return m 461} 462func (m aberrantMessage) Range(f func(pref.FieldDescriptor, pref.Value) bool) { 463} 464func (m aberrantMessage) Has(pref.FieldDescriptor) bool { 465 panic("invalid field descriptor") 466} 467func (m aberrantMessage) Clear(pref.FieldDescriptor) { 468 panic("invalid field descriptor") 469} 470func (m aberrantMessage) Get(pref.FieldDescriptor) pref.Value { 471 panic("invalid field descriptor") 472} 473func (m aberrantMessage) Set(pref.FieldDescriptor, pref.Value) { 474 panic("invalid field descriptor") 475} 476func (m aberrantMessage) Mutable(pref.FieldDescriptor) pref.Value { 477 panic("invalid field descriptor") 478} 479func (m aberrantMessage) NewField(pref.FieldDescriptor) pref.Value { 480 panic("invalid field descriptor") 481} 482func (m aberrantMessage) WhichOneof(pref.OneofDescriptor) pref.FieldDescriptor { 483 panic("invalid oneof descriptor") 484} 485func (m aberrantMessage) GetUnknown() pref.RawFields { 486 return nil 487} 488func (m aberrantMessage) SetUnknown(pref.RawFields) { 489 // SetUnknown discards its input on messages which don't support unknown field storage. 490} 491func (m aberrantMessage) IsValid() bool { 492 // An invalid message is a read-only, empty message. Since we don't know anything 493 // about the alleged contents of this message, we can't say with confidence that 494 // it is invalid in this sense. Therefore, report it as valid. 495 return true 496} 497func (m aberrantMessage) ProtoMethods() *piface.Methods { 498 return legacyProtoMethods 499} 500func (m aberrantMessage) protoUnwrap() interface{} { 501 return m.v.Interface() 502} 503