desc_validate.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // Copyright 2019 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. package protodesc
  5. import (
  6. "strings"
  7. "unicode"
  8. "google.golang.org/protobuf/encoding/protowire"
  9. "google.golang.org/protobuf/internal/errors"
  10. "google.golang.org/protobuf/internal/filedesc"
  11. "google.golang.org/protobuf/internal/flags"
  12. "google.golang.org/protobuf/internal/genid"
  13. "google.golang.org/protobuf/internal/strs"
  14. "google.golang.org/protobuf/reflect/protoreflect"
  15. "google.golang.org/protobuf/types/descriptorpb"
  16. )
  17. func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescriptorProto) error {
  18. for i, ed := range eds {
  19. e := &es[i]
  20. if err := e.L2.ReservedNames.CheckValid(); err != nil {
  21. return errors.New("enum %q reserved names has %v", e.FullName(), err)
  22. }
  23. if err := e.L2.ReservedRanges.CheckValid(); err != nil {
  24. return errors.New("enum %q reserved ranges has %v", e.FullName(), err)
  25. }
  26. if len(ed.GetValue()) == 0 {
  27. return errors.New("enum %q must contain at least one value declaration", e.FullName())
  28. }
  29. allowAlias := ed.GetOptions().GetAllowAlias()
  30. foundAlias := false
  31. for i := 0; i < e.Values().Len(); i++ {
  32. v1 := e.Values().Get(i)
  33. if v2 := e.Values().ByNumber(v1.Number()); v1 != v2 {
  34. foundAlias = true
  35. if !allowAlias {
  36. return errors.New("enum %q has conflicting non-aliased values on number %d: %q with %q", e.FullName(), v1.Number(), v1.Name(), v2.Name())
  37. }
  38. }
  39. }
  40. if allowAlias && !foundAlias {
  41. return errors.New("enum %q allows aliases, but none were found", e.FullName())
  42. }
  43. if e.Syntax() == protoreflect.Proto3 {
  44. if v := e.Values().Get(0); v.Number() != 0 {
  45. return errors.New("enum %q using proto3 semantics must have zero number for the first value", v.FullName())
  46. }
  47. // Verify that value names in proto3 do not conflict if the
  48. // case-insensitive prefix is removed.
  49. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055
  50. names := map[string]protoreflect.EnumValueDescriptor{}
  51. prefix := strings.Replace(strings.ToLower(string(e.Name())), "_", "", -1)
  52. for i := 0; i < e.Values().Len(); i++ {
  53. v1 := e.Values().Get(i)
  54. s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix))
  55. if v2, ok := names[s]; ok && v1.Number() != v2.Number() {
  56. return errors.New("enum %q using proto3 semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name())
  57. }
  58. names[s] = v1
  59. }
  60. }
  61. for j, vd := range ed.GetValue() {
  62. v := &e.L2.Values.List[j]
  63. if vd.Number == nil {
  64. return errors.New("enum value %q must have a specified number", v.FullName())
  65. }
  66. if e.L2.ReservedNames.Has(v.Name()) {
  67. return errors.New("enum value %q must not use reserved name", v.FullName())
  68. }
  69. if e.L2.ReservedRanges.Has(v.Number()) {
  70. return errors.New("enum value %q must not use reserved number %d", v.FullName(), v.Number())
  71. }
  72. }
  73. }
  74. return nil
  75. }
  76. func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error {
  77. for i, md := range mds {
  78. m := &ms[i]
  79. // Handle the message descriptor itself.
  80. isMessageSet := md.GetOptions().GetMessageSetWireFormat()
  81. if err := m.L2.ReservedNames.CheckValid(); err != nil {
  82. return errors.New("message %q reserved names has %v", m.FullName(), err)
  83. }
  84. if err := m.L2.ReservedRanges.CheckValid(isMessageSet); err != nil {
  85. return errors.New("message %q reserved ranges has %v", m.FullName(), err)
  86. }
  87. if err := m.L2.ExtensionRanges.CheckValid(isMessageSet); err != nil {
  88. return errors.New("message %q extension ranges has %v", m.FullName(), err)
  89. }
  90. if err := (*filedesc.FieldRanges).CheckOverlap(&m.L2.ReservedRanges, &m.L2.ExtensionRanges); err != nil {
  91. return errors.New("message %q reserved and extension ranges has %v", m.FullName(), err)
  92. }
  93. for i := 0; i < m.Fields().Len(); i++ {
  94. f1 := m.Fields().Get(i)
  95. if f2 := m.Fields().ByNumber(f1.Number()); f1 != f2 {
  96. return errors.New("message %q has conflicting fields: %q with %q", m.FullName(), f1.Name(), f2.Name())
  97. }
  98. }
  99. if isMessageSet && !flags.ProtoLegacy {
  100. return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName())
  101. }
  102. if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
  103. return errors.New("message %q is an invalid proto1 MessageSet", m.FullName())
  104. }
  105. if m.Syntax() == protoreflect.Proto3 {
  106. if m.ExtensionRanges().Len() > 0 {
  107. return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName())
  108. }
  109. // Verify that field names in proto3 do not conflict if lowercased
  110. // with all underscores removed.
  111. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:5830-5847
  112. names := map[string]protoreflect.FieldDescriptor{}
  113. for i := 0; i < m.Fields().Len(); i++ {
  114. f1 := m.Fields().Get(i)
  115. s := strings.Replace(strings.ToLower(string(f1.Name())), "_", "", -1)
  116. if f2, ok := names[s]; ok {
  117. return errors.New("message %q using proto3 semantics has conflict: %q with %q", m.FullName(), f1.Name(), f2.Name())
  118. }
  119. names[s] = f1
  120. }
  121. }
  122. for j, fd := range md.GetField() {
  123. f := &m.L2.Fields.List[j]
  124. if m.L2.ReservedNames.Has(f.Name()) {
  125. return errors.New("message field %q must not use reserved name", f.FullName())
  126. }
  127. if !f.Number().IsValid() {
  128. return errors.New("message field %q has an invalid number: %d", f.FullName(), f.Number())
  129. }
  130. if !f.Cardinality().IsValid() {
  131. return errors.New("message field %q has an invalid cardinality: %d", f.FullName(), f.Cardinality())
  132. }
  133. if m.L2.ReservedRanges.Has(f.Number()) {
  134. return errors.New("message field %q must not use reserved number %d", f.FullName(), f.Number())
  135. }
  136. if m.L2.ExtensionRanges.Has(f.Number()) {
  137. return errors.New("message field %q with number %d in extension range", f.FullName(), f.Number())
  138. }
  139. if fd.Extendee != nil {
  140. return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee())
  141. }
  142. if f.L1.IsProto3Optional {
  143. if f.Syntax() != protoreflect.Proto3 {
  144. return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName())
  145. }
  146. if f.Cardinality() != protoreflect.Optional {
  147. return errors.New("message field %q under proto3 optional semantics must have optional cardinality", f.FullName())
  148. }
  149. if f.ContainingOneof() != nil && f.ContainingOneof().Fields().Len() != 1 {
  150. return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName())
  151. }
  152. }
  153. if f.IsWeak() && !flags.ProtoLegacy {
  154. return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName())
  155. }
  156. if f.IsWeak() && (f.Syntax() != protoreflect.Proto2 || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
  157. return errors.New("message field %q may only be weak for an optional message", f.FullName())
  158. }
  159. if f.IsPacked() && !isPackable(f) {
  160. return errors.New("message field %q is not packable", f.FullName())
  161. }
  162. if err := checkValidGroup(f); err != nil {
  163. return errors.New("message field %q is an invalid group: %v", f.FullName(), err)
  164. }
  165. if err := checkValidMap(f); err != nil {
  166. return errors.New("message field %q is an invalid map: %v", f.FullName(), err)
  167. }
  168. if f.Syntax() == protoreflect.Proto3 {
  169. if f.Cardinality() == protoreflect.Required {
  170. return errors.New("message field %q using proto3 semantics cannot be required", f.FullName())
  171. }
  172. if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().Syntax() != protoreflect.Proto3 {
  173. return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", f.FullName())
  174. }
  175. }
  176. }
  177. seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs
  178. for j := range md.GetOneofDecl() {
  179. o := &m.L2.Oneofs.List[j]
  180. if o.Fields().Len() == 0 {
  181. return errors.New("message oneof %q must contain at least one field declaration", o.FullName())
  182. }
  183. if n := o.Fields().Len(); n-1 != (o.Fields().Get(n-1).Index() - o.Fields().Get(0).Index()) {
  184. return errors.New("message oneof %q must have consecutively declared fields", o.FullName())
  185. }
  186. if o.IsSynthetic() {
  187. seenSynthetic = true
  188. continue
  189. }
  190. if !o.IsSynthetic() && seenSynthetic {
  191. return errors.New("message oneof %q must be declared before synthetic oneofs", o.FullName())
  192. }
  193. for i := 0; i < o.Fields().Len(); i++ {
  194. f := o.Fields().Get(i)
  195. if f.Cardinality() != protoreflect.Optional {
  196. return errors.New("message field %q belongs in a oneof and must be optional", f.FullName())
  197. }
  198. if f.IsWeak() {
  199. return errors.New("message field %q belongs in a oneof and must not be a weak reference", f.FullName())
  200. }
  201. }
  202. }
  203. if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil {
  204. return err
  205. }
  206. if err := validateMessageDeclarations(m.L1.Messages.List, md.GetNestedType()); err != nil {
  207. return err
  208. }
  209. if err := validateExtensionDeclarations(m.L1.Extensions.List, md.GetExtension()); err != nil {
  210. return err
  211. }
  212. }
  213. return nil
  214. }
  215. func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error {
  216. for i, xd := range xds {
  217. x := &xs[i]
  218. // NOTE: Avoid using the IsValid method since extensions to MessageSet
  219. // may have a field number higher than normal. This check only verifies
  220. // that the number is not negative or reserved. We check again later
  221. // if we know that the extendee is definitely not a MessageSet.
  222. if n := x.Number(); n < 0 || (protowire.FirstReservedNumber <= n && n <= protowire.LastReservedNumber) {
  223. return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
  224. }
  225. if !x.Cardinality().IsValid() || x.Cardinality() == protoreflect.Required {
  226. return errors.New("extension field %q has an invalid cardinality: %d", x.FullName(), x.Cardinality())
  227. }
  228. if xd.JsonName != nil {
  229. // A bug in older versions of protoc would always populate the
  230. // "json_name" option for extensions when it is meaningless.
  231. // When it did so, it would always use the camel-cased field name.
  232. if xd.GetJsonName() != strs.JSONCamelCase(string(x.Name())) {
  233. return errors.New("extension field %q may not have an explicitly set JSON name: %q", x.FullName(), xd.GetJsonName())
  234. }
  235. }
  236. if xd.OneofIndex != nil {
  237. return errors.New("extension field %q may not be part of a oneof", x.FullName())
  238. }
  239. if md := x.ContainingMessage(); !md.IsPlaceholder() {
  240. if !md.ExtensionRanges().Has(x.Number()) {
  241. return errors.New("extension field %q extends %q with non-extension field number: %d", x.FullName(), md.FullName(), x.Number())
  242. }
  243. isMessageSet := md.Options().(*descriptorpb.MessageOptions).GetMessageSetWireFormat()
  244. if isMessageSet && !isOptionalMessage(x) {
  245. return errors.New("extension field %q extends MessageSet and must be an optional message", x.FullName())
  246. }
  247. if !isMessageSet && !x.Number().IsValid() {
  248. return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
  249. }
  250. }
  251. if xd.GetOptions().GetWeak() {
  252. return errors.New("extension field %q cannot be a weak reference", x.FullName())
  253. }
  254. if x.IsPacked() && !isPackable(x) {
  255. return errors.New("extension field %q is not packable", x.FullName())
  256. }
  257. if err := checkValidGroup(x); err != nil {
  258. return errors.New("extension field %q is an invalid group: %v", x.FullName(), err)
  259. }
  260. if md := x.Message(); md != nil && md.IsMapEntry() {
  261. return errors.New("extension field %q cannot be a map entry", x.FullName())
  262. }
  263. if x.Syntax() == protoreflect.Proto3 {
  264. switch x.ContainingMessage().FullName() {
  265. case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName():
  266. case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName():
  267. case (*descriptorpb.EnumValueOptions)(nil).ProtoReflect().Descriptor().FullName():
  268. case (*descriptorpb.MessageOptions)(nil).ProtoReflect().Descriptor().FullName():
  269. case (*descriptorpb.FieldOptions)(nil).ProtoReflect().Descriptor().FullName():
  270. case (*descriptorpb.OneofOptions)(nil).ProtoReflect().Descriptor().FullName():
  271. case (*descriptorpb.ExtensionRangeOptions)(nil).ProtoReflect().Descriptor().FullName():
  272. case (*descriptorpb.ServiceOptions)(nil).ProtoReflect().Descriptor().FullName():
  273. case (*descriptorpb.MethodOptions)(nil).ProtoReflect().Descriptor().FullName():
  274. default:
  275. return errors.New("extension field %q cannot be declared in proto3 unless extended descriptor options", x.FullName())
  276. }
  277. }
  278. }
  279. return nil
  280. }
  281. // isOptionalMessage reports whether this is an optional message.
  282. // If the kind is unknown, it is assumed to be a message.
  283. func isOptionalMessage(fd protoreflect.FieldDescriptor) bool {
  284. return (fd.Kind() == 0 || fd.Kind() == protoreflect.MessageKind) && fd.Cardinality() == protoreflect.Optional
  285. }
  286. // isPackable checks whether the pack option can be specified.
  287. func isPackable(fd protoreflect.FieldDescriptor) bool {
  288. switch fd.Kind() {
  289. case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
  290. return false
  291. }
  292. return fd.IsList()
  293. }
  294. // checkValidGroup reports whether fd is a valid group according to the same
  295. // rules that protoc imposes.
  296. func checkValidGroup(fd protoreflect.FieldDescriptor) error {
  297. md := fd.Message()
  298. switch {
  299. case fd.Kind() != protoreflect.GroupKind:
  300. return nil
  301. case fd.Syntax() != protoreflect.Proto2:
  302. return errors.New("invalid under proto2 semantics")
  303. case md == nil || md.IsPlaceholder():
  304. return errors.New("message must be resolvable")
  305. case fd.FullName().Parent() != md.FullName().Parent():
  306. return errors.New("message and field must be declared in the same scope")
  307. case !unicode.IsUpper(rune(md.Name()[0])):
  308. return errors.New("message name must start with an uppercase")
  309. case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))):
  310. return errors.New("field name must be lowercased form of the message name")
  311. }
  312. return nil
  313. }
  314. // checkValidMap checks whether the field is a valid map according to the same
  315. // rules that protoc imposes.
  316. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:6045-6115
  317. func checkValidMap(fd protoreflect.FieldDescriptor) error {
  318. md := fd.Message()
  319. switch {
  320. case md == nil || !md.IsMapEntry():
  321. return nil
  322. case fd.FullName().Parent() != md.FullName().Parent():
  323. return errors.New("message and field must be declared in the same scope")
  324. case md.Name() != protoreflect.Name(strs.MapEntryName(string(fd.Name()))):
  325. return errors.New("incorrect implicit map entry name")
  326. case fd.Cardinality() != protoreflect.Repeated:
  327. return errors.New("field must be repeated")
  328. case md.Fields().Len() != 2:
  329. return errors.New("message must have exactly two fields")
  330. case md.ExtensionRanges().Len() > 0:
  331. return errors.New("message must not have any extension ranges")
  332. case md.Enums().Len()+md.Messages().Len()+md.Extensions().Len() > 0:
  333. return errors.New("message must not have any nested declarations")
  334. }
  335. kf := md.Fields().Get(0)
  336. vf := md.Fields().Get(1)
  337. switch {
  338. case kf.Name() != genid.MapEntry_Key_field_name || kf.Number() != genid.MapEntry_Key_field_number || kf.Cardinality() != protoreflect.Optional || kf.ContainingOneof() != nil || kf.HasDefault():
  339. return errors.New("invalid key field")
  340. case vf.Name() != genid.MapEntry_Value_field_name || vf.Number() != genid.MapEntry_Value_field_number || vf.Cardinality() != protoreflect.Optional || vf.ContainingOneof() != nil || vf.HasDefault():
  341. return errors.New("invalid value field")
  342. }
  343. switch kf.Kind() {
  344. case protoreflect.BoolKind: // bool
  345. case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: // int32
  346. case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: // int64
  347. case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: // uint32
  348. case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: // uint64
  349. case protoreflect.StringKind: // string
  350. default:
  351. return errors.New("invalid key kind: %v", kf.Kind())
  352. }
  353. if e := vf.Enum(); e != nil && e.Values().Len() > 0 && e.Values().Get(0).Number() != 0 {
  354. return errors.New("map enum value must have zero number for the first value")
  355. }
  356. return nil
  357. }