messageset.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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 messageset encodes and decodes the obsolete MessageSet wire format.
  5. package messageset
  6. import (
  7. "math"
  8. "google.golang.org/protobuf/encoding/protowire"
  9. "google.golang.org/protobuf/internal/errors"
  10. pref "google.golang.org/protobuf/reflect/protoreflect"
  11. )
  12. // The MessageSet wire format is equivalent to a message defined as follows,
  13. // where each Item defines an extension field with a field number of 'type_id'
  14. // and content of 'message'. MessageSet extensions must be non-repeated message
  15. // fields.
  16. //
  17. // message MessageSet {
  18. // repeated group Item = 1 {
  19. // required int32 type_id = 2;
  20. // required string message = 3;
  21. // }
  22. // }
  23. const (
  24. FieldItem = protowire.Number(1)
  25. FieldTypeID = protowire.Number(2)
  26. FieldMessage = protowire.Number(3)
  27. )
  28. // ExtensionName is the field name for extensions of MessageSet.
  29. //
  30. // A valid MessageSet extension must be of the form:
  31. // message MyMessage {
  32. // extend proto2.bridge.MessageSet {
  33. // optional MyMessage message_set_extension = 1234;
  34. // }
  35. // ...
  36. // }
  37. const ExtensionName = "message_set_extension"
  38. // IsMessageSet returns whether the message uses the MessageSet wire format.
  39. func IsMessageSet(md pref.MessageDescriptor) bool {
  40. xmd, ok := md.(interface{ IsMessageSet() bool })
  41. return ok && xmd.IsMessageSet()
  42. }
  43. // IsMessageSetExtension reports this field properly extends a MessageSet.
  44. func IsMessageSetExtension(fd pref.FieldDescriptor) bool {
  45. switch {
  46. case fd.Name() != ExtensionName:
  47. return false
  48. case !IsMessageSet(fd.ContainingMessage()):
  49. return false
  50. case fd.FullName().Parent() != fd.Message().FullName():
  51. return false
  52. }
  53. return true
  54. }
  55. // SizeField returns the size of a MessageSet item field containing an extension
  56. // with the given field number, not counting the contents of the message subfield.
  57. func SizeField(num protowire.Number) int {
  58. return 2*protowire.SizeTag(FieldItem) + protowire.SizeTag(FieldTypeID) + protowire.SizeVarint(uint64(num))
  59. }
  60. // Unmarshal parses a MessageSet.
  61. //
  62. // It calls fn with the type ID and value of each item in the MessageSet.
  63. // Unknown fields are discarded.
  64. //
  65. // If wantLen is true, the item values include the varint length prefix.
  66. // This is ugly, but simplifies the fast-path decoder in internal/impl.
  67. func Unmarshal(b []byte, wantLen bool, fn func(typeID protowire.Number, value []byte) error) error {
  68. for len(b) > 0 {
  69. num, wtyp, n := protowire.ConsumeTag(b)
  70. if n < 0 {
  71. return protowire.ParseError(n)
  72. }
  73. b = b[n:]
  74. if num != FieldItem || wtyp != protowire.StartGroupType {
  75. n := protowire.ConsumeFieldValue(num, wtyp, b)
  76. if n < 0 {
  77. return protowire.ParseError(n)
  78. }
  79. b = b[n:]
  80. continue
  81. }
  82. typeID, value, n, err := ConsumeFieldValue(b, wantLen)
  83. if err != nil {
  84. return err
  85. }
  86. b = b[n:]
  87. if typeID == 0 {
  88. continue
  89. }
  90. if err := fn(typeID, value); err != nil {
  91. return err
  92. }
  93. }
  94. return nil
  95. }
  96. // ConsumeFieldValue parses b as a MessageSet item field value until and including
  97. // the trailing end group marker. It assumes the start group tag has already been parsed.
  98. // It returns the contents of the type_id and message subfields and the total
  99. // item length.
  100. //
  101. // If wantLen is true, the returned message value includes the length prefix.
  102. func ConsumeFieldValue(b []byte, wantLen bool) (typeid protowire.Number, message []byte, n int, err error) {
  103. ilen := len(b)
  104. for {
  105. num, wtyp, n := protowire.ConsumeTag(b)
  106. if n < 0 {
  107. return 0, nil, 0, protowire.ParseError(n)
  108. }
  109. b = b[n:]
  110. switch {
  111. case num == FieldItem && wtyp == protowire.EndGroupType:
  112. if wantLen && len(message) == 0 {
  113. // The message field was missing, which should never happen.
  114. // Be prepared for this case anyway.
  115. message = protowire.AppendVarint(message, 0)
  116. }
  117. return typeid, message, ilen - len(b), nil
  118. case num == FieldTypeID && wtyp == protowire.VarintType:
  119. v, n := protowire.ConsumeVarint(b)
  120. if n < 0 {
  121. return 0, nil, 0, protowire.ParseError(n)
  122. }
  123. b = b[n:]
  124. if v < 1 || v > math.MaxInt32 {
  125. return 0, nil, 0, errors.New("invalid type_id in message set")
  126. }
  127. typeid = protowire.Number(v)
  128. case num == FieldMessage && wtyp == protowire.BytesType:
  129. m, n := protowire.ConsumeBytes(b)
  130. if n < 0 {
  131. return 0, nil, 0, protowire.ParseError(n)
  132. }
  133. if message == nil {
  134. if wantLen {
  135. message = b[:n:n]
  136. } else {
  137. message = m[:len(m):len(m)]
  138. }
  139. } else {
  140. // This case should never happen in practice, but handle it for
  141. // correctness: The MessageSet item contains multiple message
  142. // fields, which need to be merged.
  143. //
  144. // In the case where we're returning the length, this becomes
  145. // quite inefficient since we need to strip the length off
  146. // the existing data and reconstruct it with the combined length.
  147. if wantLen {
  148. _, nn := protowire.ConsumeVarint(message)
  149. m0 := message[nn:]
  150. message = nil
  151. message = protowire.AppendVarint(message, uint64(len(m0)+len(m)))
  152. message = append(message, m0...)
  153. message = append(message, m...)
  154. } else {
  155. message = append(message, m...)
  156. }
  157. }
  158. b = b[n:]
  159. default:
  160. // We have no place to put it, so we just ignore unknown fields.
  161. n := protowire.ConsumeFieldValue(num, wtyp, b)
  162. if n < 0 {
  163. return 0, nil, 0, protowire.ParseError(n)
  164. }
  165. b = b[n:]
  166. }
  167. }
  168. }
  169. // AppendFieldStart appends the start of a MessageSet item field containing
  170. // an extension with the given number. The caller must add the message
  171. // subfield (including the tag).
  172. func AppendFieldStart(b []byte, num protowire.Number) []byte {
  173. b = protowire.AppendTag(b, FieldItem, protowire.StartGroupType)
  174. b = protowire.AppendTag(b, FieldTypeID, protowire.VarintType)
  175. b = protowire.AppendVarint(b, uint64(num))
  176. return b
  177. }
  178. // AppendFieldEnd appends the trailing end group marker for a MessageSet item field.
  179. func AppendFieldEnd(b []byte) []byte {
  180. return protowire.AppendTag(b, FieldItem, protowire.EndGroupType)
  181. }
  182. // SizeUnknown returns the size of an unknown fields section in MessageSet format.
  183. //
  184. // See AppendUnknown.
  185. func SizeUnknown(unknown []byte) (size int) {
  186. for len(unknown) > 0 {
  187. num, typ, n := protowire.ConsumeTag(unknown)
  188. if n < 0 || typ != protowire.BytesType {
  189. return 0
  190. }
  191. unknown = unknown[n:]
  192. _, n = protowire.ConsumeBytes(unknown)
  193. if n < 0 {
  194. return 0
  195. }
  196. unknown = unknown[n:]
  197. size += SizeField(num) + protowire.SizeTag(FieldMessage) + n
  198. }
  199. return size
  200. }
  201. // AppendUnknown appends unknown fields to b in MessageSet format.
  202. //
  203. // For historic reasons, unresolved items in a MessageSet are stored in a
  204. // message's unknown fields section in non-MessageSet format. That is, an
  205. // unknown item with typeID T and value V appears in the unknown fields as
  206. // a field with number T and value V.
  207. //
  208. // This function converts the unknown fields back into MessageSet form.
  209. func AppendUnknown(b, unknown []byte) ([]byte, error) {
  210. for len(unknown) > 0 {
  211. num, typ, n := protowire.ConsumeTag(unknown)
  212. if n < 0 || typ != protowire.BytesType {
  213. return nil, errors.New("invalid data in message set unknown fields")
  214. }
  215. unknown = unknown[n:]
  216. _, n = protowire.ConsumeBytes(unknown)
  217. if n < 0 {
  218. return nil, errors.New("invalid data in message set unknown fields")
  219. }
  220. b = AppendFieldStart(b, num)
  221. b = protowire.AppendTag(b, FieldMessage, protowire.BytesType)
  222. b = append(b, unknown[:n]...)
  223. b = AppendFieldEnd(b)
  224. unknown = unknown[n:]
  225. }
  226. return b, nil
  227. }