checkinit.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 impl
  5. import (
  6. "sync"
  7. "google.golang.org/protobuf/internal/errors"
  8. "google.golang.org/protobuf/reflect/protoreflect"
  9. "google.golang.org/protobuf/runtime/protoiface"
  10. )
  11. func (mi *MessageInfo) checkInitialized(in protoiface.CheckInitializedInput) (protoiface.CheckInitializedOutput, error) {
  12. var p pointer
  13. if ms, ok := in.Message.(*messageState); ok {
  14. p = ms.pointer()
  15. } else {
  16. p = in.Message.(*messageReflectWrapper).pointer()
  17. }
  18. return protoiface.CheckInitializedOutput{}, mi.checkInitializedPointer(p)
  19. }
  20. func (mi *MessageInfo) checkInitializedPointer(p pointer) error {
  21. mi.init()
  22. if !mi.needsInitCheck {
  23. return nil
  24. }
  25. if p.IsNil() {
  26. for _, f := range mi.orderedCoderFields {
  27. if f.isRequired {
  28. return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName()))
  29. }
  30. }
  31. return nil
  32. }
  33. var presence presence
  34. if mi.presenceOffset.IsValid() {
  35. presence = p.Apply(mi.presenceOffset).PresenceInfo()
  36. }
  37. if mi.extensionOffset.IsValid() {
  38. e := p.Apply(mi.extensionOffset).Extensions()
  39. if err := mi.isInitExtensions(e); err != nil {
  40. return err
  41. }
  42. }
  43. for _, f := range mi.orderedCoderFields {
  44. if !f.isRequired && f.funcs.isInit == nil {
  45. continue
  46. }
  47. if f.presenceIndex != noPresence {
  48. if !presence.Present(f.presenceIndex) {
  49. if f.isRequired {
  50. return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName()))
  51. }
  52. continue
  53. }
  54. if f.funcs.isInit != nil {
  55. f.mi.init()
  56. if f.mi.needsInitCheck {
  57. if f.isLazy && p.Apply(f.offset).AtomicGetPointer().IsNil() {
  58. lazy := *p.Apply(mi.lazyOffset).LazyInfoPtr()
  59. if !lazy.AllowedPartial() {
  60. // Nothing to see here, it was checked on unmarshal
  61. continue
  62. }
  63. mi.lazyUnmarshal(p, f.num)
  64. }
  65. if err := f.funcs.isInit(p.Apply(f.offset), f); err != nil {
  66. return err
  67. }
  68. }
  69. }
  70. continue
  71. }
  72. fptr := p.Apply(f.offset)
  73. if f.isPointer && fptr.Elem().IsNil() {
  74. if f.isRequired {
  75. return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName()))
  76. }
  77. continue
  78. }
  79. if f.funcs.isInit == nil {
  80. continue
  81. }
  82. if err := f.funcs.isInit(fptr, f); err != nil {
  83. return err
  84. }
  85. }
  86. return nil
  87. }
  88. func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error {
  89. if ext == nil {
  90. return nil
  91. }
  92. for _, x := range *ext {
  93. ei := getExtensionFieldInfo(x.Type())
  94. if ei.funcs.isInit == nil || x.isUnexpandedLazy() {
  95. continue
  96. }
  97. v := x.Value()
  98. if !v.IsValid() {
  99. continue
  100. }
  101. if err := ei.funcs.isInit(v); err != nil {
  102. return err
  103. }
  104. }
  105. return nil
  106. }
  107. var (
  108. needsInitCheckMu sync.Mutex
  109. needsInitCheckMap sync.Map
  110. )
  111. // needsInitCheck reports whether a message needs to be checked for partial initialization.
  112. //
  113. // It returns true if the message transitively includes any required or extension fields.
  114. func needsInitCheck(md protoreflect.MessageDescriptor) bool {
  115. if v, ok := needsInitCheckMap.Load(md); ok {
  116. if has, ok := v.(bool); ok {
  117. return has
  118. }
  119. }
  120. needsInitCheckMu.Lock()
  121. defer needsInitCheckMu.Unlock()
  122. return needsInitCheckLocked(md)
  123. }
  124. func needsInitCheckLocked(md protoreflect.MessageDescriptor) (has bool) {
  125. if v, ok := needsInitCheckMap.Load(md); ok {
  126. // If has is true, we've previously determined that this message
  127. // needs init checks.
  128. //
  129. // If has is false, we've previously determined that it can never
  130. // be uninitialized.
  131. //
  132. // If has is not a bool, we've just encountered a cycle in the
  133. // message graph. In this case, it is safe to return false: If
  134. // the message does have required fields, we'll detect them later
  135. // in the graph traversal.
  136. has, ok := v.(bool)
  137. return ok && has
  138. }
  139. needsInitCheckMap.Store(md, struct{}{}) // avoid cycles while descending into this message
  140. defer func() {
  141. needsInitCheckMap.Store(md, has)
  142. }()
  143. if md.RequiredNumbers().Len() > 0 {
  144. return true
  145. }
  146. if md.ExtensionRanges().Len() > 0 {
  147. return true
  148. }
  149. for i := 0; i < md.Fields().Len(); i++ {
  150. fd := md.Fields().Get(i)
  151. // Map keys are never messages, so just consider the map value.
  152. if fd.IsMap() {
  153. fd = fd.MapValue()
  154. }
  155. fmd := fd.Message()
  156. if fmd != nil && needsInitCheckLocked(fmd) {
  157. return true
  158. }
  159. }
  160. return false
  161. }