xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/dynamic_message.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: [email protected] (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // DynamicMessage is implemented by constructing a data structure which
36 // has roughly the same memory layout as a generated message would have.
37 // Then, we use Reflection to implement our reflection interface.  All
38 // the other operations we need to implement (e.g.  parsing, copying,
39 // etc.) are already implemented in terms of Reflection, so the rest is
40 // easy.
41 //
42 // The up side of this strategy is that it's very efficient.  We don't
43 // need to use hash_maps or generic representations of fields.  The
44 // down side is that this is a low-level memory management hack which
45 // can be tricky to get right.
46 //
47 // As mentioned in the header, we only expose a DynamicMessageFactory
48 // publicly, not the DynamicMessage class itself.  This is because
49 // GenericMessageReflection wants to have a pointer to a "default"
50 // copy of the class, with all fields initialized to their default
51 // values.  We only want to construct one of these per message type,
52 // so DynamicMessageFactory stores a cache of default messages for
53 // each type it sees (each unique Descriptor pointer).  The code
54 // refers to the "default" copy of the class as the "prototype".
55 //
56 // Note on memory allocation:  This module often calls "operator new()"
57 // to allocate untyped memory, rather than calling something like
58 // "new uint8_t[]".  This is because "operator new()" means "Give me some
59 // space which I can use as I please." while "new uint8_t[]" means "Give
60 // me an array of 8-bit integers.".  In practice, the later may return
61 // a pointer that is not aligned correctly for general use.  I believe
62 // Item 8 of "More Effective C++" discusses this in more detail, though
63 // I don't have the book on me right now so I'm not sure.
64 
65 #include <google/protobuf/dynamic_message.h>
66 
67 #include <algorithm>
68 #include <cstddef>
69 #include <memory>
70 #include <new>
71 #include <unordered_map>
72 
73 #include <google/protobuf/descriptor.h>
74 #include <google/protobuf/descriptor.pb.h>
75 #include <google/protobuf/generated_message_reflection.h>
76 #include <google/protobuf/generated_message_util.h>
77 #include <google/protobuf/unknown_field_set.h>
78 #include <google/protobuf/stubs/hash.h>
79 #include <google/protobuf/arenastring.h>
80 #include <google/protobuf/extension_set.h>
81 #include <google/protobuf/map_field.h>
82 #include <google/protobuf/map_field_inl.h>
83 #include <google/protobuf/map_type_handler.h>
84 #include <google/protobuf/reflection_ops.h>
85 #include <google/protobuf/repeated_field.h>
86 #include <google/protobuf/wire_format.h>
87 
88 // Must be included last.
89 #include <google/protobuf/port_def.inc>
90 
91 namespace google {
92 namespace protobuf {
93 
94 using internal::DynamicMapField;
95 using internal::ExtensionSet;
96 using internal::MapField;
97 
98 
99 using internal::ArenaStringPtr;
100 
101 // ===================================================================
102 // Some helper tables and functions...
103 
104 namespace {
105 
IsMapFieldInApi(const FieldDescriptor * field)106 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
107 
108 // Sync with helpers.h.
HasHasbit(const FieldDescriptor * field)109 inline bool HasHasbit(const FieldDescriptor* field) {
110   // This predicate includes proto3 message fields only if they have "optional".
111   //   Foo submsg1 = 1;           // HasHasbit() == false
112   //   optional Foo submsg2 = 2;  // HasHasbit() == true
113   // This is slightly odd, as adding "optional" to a singular proto3 field does
114   // not change the semantics or API. However whenever any field in a message
115   // has a hasbit, it forces reflection to include hasbit offsets for *all*
116   // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
117   // causing a sudden size regression for ~all proto3 messages, we give proto3
118   // message fields a hasbit only if "optional" is present. If the user is
119   // explicitly writing "optional", it is likely they are writing it on
120   // primitive fields also.
121   return (field->has_optional_keyword() || field->is_required()) &&
122          !field->options().weak();
123 }
124 
InRealOneof(const FieldDescriptor * field)125 inline bool InRealOneof(const FieldDescriptor* field) {
126   return field->containing_oneof() &&
127          !field->containing_oneof()->is_synthetic();
128 }
129 
130 // Compute the byte size of the in-memory representation of the field.
FieldSpaceUsed(const FieldDescriptor * field)131 int FieldSpaceUsed(const FieldDescriptor* field) {
132   typedef FieldDescriptor FD;  // avoid line wrapping
133   if (field->label() == FD::LABEL_REPEATED) {
134     switch (field->cpp_type()) {
135       case FD::CPPTYPE_INT32:
136         return sizeof(RepeatedField<int32_t>);
137       case FD::CPPTYPE_INT64:
138         return sizeof(RepeatedField<int64_t>);
139       case FD::CPPTYPE_UINT32:
140         return sizeof(RepeatedField<uint32_t>);
141       case FD::CPPTYPE_UINT64:
142         return sizeof(RepeatedField<uint64_t>);
143       case FD::CPPTYPE_DOUBLE:
144         return sizeof(RepeatedField<double>);
145       case FD::CPPTYPE_FLOAT:
146         return sizeof(RepeatedField<float>);
147       case FD::CPPTYPE_BOOL:
148         return sizeof(RepeatedField<bool>);
149       case FD::CPPTYPE_ENUM:
150         return sizeof(RepeatedField<int>);
151       case FD::CPPTYPE_MESSAGE:
152         if (IsMapFieldInApi(field)) {
153           return sizeof(DynamicMapField);
154         } else {
155           return sizeof(RepeatedPtrField<Message>);
156         }
157 
158       case FD::CPPTYPE_STRING:
159         switch (field->options().ctype()) {
160           default:  // TODO(kenton):  Support other string reps.
161           case FieldOptions::STRING:
162             return sizeof(RepeatedPtrField<std::string>);
163         }
164         break;
165     }
166   } else {
167     switch (field->cpp_type()) {
168       case FD::CPPTYPE_INT32:
169         return sizeof(int32_t);
170       case FD::CPPTYPE_INT64:
171         return sizeof(int64_t);
172       case FD::CPPTYPE_UINT32:
173         return sizeof(uint32_t);
174       case FD::CPPTYPE_UINT64:
175         return sizeof(uint64_t);
176       case FD::CPPTYPE_DOUBLE:
177         return sizeof(double);
178       case FD::CPPTYPE_FLOAT:
179         return sizeof(float);
180       case FD::CPPTYPE_BOOL:
181         return sizeof(bool);
182       case FD::CPPTYPE_ENUM:
183         return sizeof(int);
184 
185       case FD::CPPTYPE_MESSAGE:
186         return sizeof(Message*);
187 
188       case FD::CPPTYPE_STRING:
189         switch (field->options().ctype()) {
190           default:  // TODO(kenton):  Support other string reps.
191           case FieldOptions::STRING:
192             return sizeof(ArenaStringPtr);
193         }
194         break;
195     }
196   }
197 
198   GOOGLE_LOG(DFATAL) << "Can't get here.";
199   return 0;
200 }
201 
DivideRoundingUp(int i,int j)202 inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
203 
204 static const int kSafeAlignment = sizeof(uint64_t);
205 static const int kMaxOneofUnionSize = sizeof(uint64_t);
206 
AlignTo(int offset,int alignment)207 inline int AlignTo(int offset, int alignment) {
208   return DivideRoundingUp(offset, alignment) * alignment;
209 }
210 
211 // Rounds the given byte offset up to the next offset aligned such that any
212 // type may be stored at it.
AlignOffset(int offset)213 inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); }
214 
215 #define bitsizeof(T) (sizeof(T) * 8)
216 
217 }  // namespace
218 
219 // ===================================================================
220 
221 class DynamicMessage : public Message {
222  public:
223   explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info);
224 
225   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
226   DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory);
227 
228   ~DynamicMessage() override;
229 
230   // Called on the prototype after construction to initialize message fields.
231   // Cross linking the default instances allows for fast reflection access of
232   // unset message fields. Without it we would have to go to the MessageFactory
233   // to get the prototype, which is a much more expensive operation.
234   //
235   // Generated messages do not cross-link to avoid dynamic initialization of the
236   // global instances.
237   // Instead, they keep the default instances in the FieldDescriptor objects.
238   void CrossLinkPrototypes();
239 
240   // implements Message ----------------------------------------------
241 
242   Message* New(Arena* arena) const override;
243 
244   int GetCachedSize() const override;
245   void SetCachedSize(int size) const override;
246 
247   Metadata GetMetadata() const override;
248 
249 #if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
250   static void operator delete(DynamicMessage* msg, std::destroying_delete_t);
251 #else
252   // We actually allocate more memory than sizeof(*this) when this
253   // class's memory is allocated via the global operator new. Thus, we need to
254   // manually call the global operator delete. Calling the destructor is taken
255   // care of for us. This makes DynamicMessage compatible with -fsized-delete.
256   // It doesn't work for MSVC though.
257 #ifndef _MSC_VER
operator delete(void * ptr)258   static void operator delete(void* ptr) { ::operator delete(ptr); }
259 #endif  // !_MSC_VER
260 #endif
261 
262  private:
263   DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
264                  Arena* arena);
265 
266   void SharedCtor(bool lock_factory);
267 
268   // Needed to get the offset of the internal metadata member.
269   friend class DynamicMessageFactory;
270 
271   bool is_prototype() const;
272 
OffsetToPointer(int offset)273   inline void* OffsetToPointer(int offset) {
274     return reinterpret_cast<uint8_t*>(this) + offset;
275   }
OffsetToPointer(int offset) const276   inline const void* OffsetToPointer(int offset) const {
277     return reinterpret_cast<const uint8_t*>(this) + offset;
278   }
279 
280   void* MutableRaw(int i);
281   void* MutableExtensionsRaw();
282   void* MutableWeakFieldMapRaw();
283   void* MutableOneofCaseRaw(int i);
284   void* MutableOneofFieldRaw(const FieldDescriptor* f);
285 
286   const DynamicMessageFactory::TypeInfo* type_info_;
287   mutable std::atomic<int> cached_byte_size_;
288   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
289 };
290 
291 struct DynamicMessageFactory::TypeInfo {
292   int size;
293   int has_bits_offset;
294   int oneof_case_offset;
295   int extensions_offset;
296 
297   // Not owned by the TypeInfo.
298   DynamicMessageFactory* factory;  // The factory that created this object.
299   const DescriptorPool* pool;      // The factory's DescriptorPool.
300   const Descriptor* type;          // Type of this DynamicMessage.
301 
302   // Warning:  The order in which the following pointers are defined is
303   //   important (the prototype must be deleted *before* the offsets).
304   std::unique_ptr<uint32_t[]> offsets;
305   std::unique_ptr<uint32_t[]> has_bits_indices;
306   std::unique_ptr<const Reflection> reflection;
307   // Don't use a unique_ptr to hold the prototype: the destructor for
308   // DynamicMessage needs to know whether it is the prototype, and does so by
309   // looking back at this field. This would assume details about the
310   // implementation of unique_ptr.
311   const DynamicMessage* prototype;
312   int weak_field_map_offset;  // The offset for the weak_field_map;
313 
TypeInfogoogle::protobuf::DynamicMessageFactory::TypeInfo314   TypeInfo() : prototype(nullptr) {}
315 
~TypeInfogoogle::protobuf::DynamicMessageFactory::TypeInfo316   ~TypeInfo() { delete prototype; }
317 };
318 
DynamicMessage(const DynamicMessageFactory::TypeInfo * type_info)319 DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info)
320     : type_info_(type_info), cached_byte_size_(0) {
321   SharedCtor(true);
322 }
323 
DynamicMessage(const DynamicMessageFactory::TypeInfo * type_info,Arena * arena)324 DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
325                                Arena* arena)
326     : Message(arena), type_info_(type_info), cached_byte_size_(0) {
327   SharedCtor(true);
328 }
329 
DynamicMessage(DynamicMessageFactory::TypeInfo * type_info,bool lock_factory)330 DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info,
331                                bool lock_factory)
332     : type_info_(type_info), cached_byte_size_(0) {
333   // The prototype in type_info has to be set before creating the prototype
334   // instance on memory. e.g., message Foo { map<int32_t, Foo> a = 1; }. When
335   // creating prototype for Foo, prototype of the map entry will also be
336   // created, which needs the address of the prototype of Foo (the value in
337   // map). To break the cyclic dependency, we have to assign the address of
338   // prototype into type_info first.
339   type_info->prototype = this;
340   SharedCtor(lock_factory);
341 }
342 
MutableRaw(int i)343 inline void* DynamicMessage::MutableRaw(int i) {
344   return OffsetToPointer(type_info_->offsets[i]);
345 }
MutableExtensionsRaw()346 inline void* DynamicMessage::MutableExtensionsRaw() {
347   return OffsetToPointer(type_info_->extensions_offset);
348 }
MutableWeakFieldMapRaw()349 inline void* DynamicMessage::MutableWeakFieldMapRaw() {
350   return OffsetToPointer(type_info_->weak_field_map_offset);
351 }
MutableOneofCaseRaw(int i)352 inline void* DynamicMessage::MutableOneofCaseRaw(int i) {
353   return OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32_t) * i);
354 }
MutableOneofFieldRaw(const FieldDescriptor * f)355 inline void* DynamicMessage::MutableOneofFieldRaw(const FieldDescriptor* f) {
356   return OffsetToPointer(type_info_->offsets[type_info_->type->field_count() +
357                                              f->containing_oneof()->index()]);
358 }
359 
SharedCtor(bool lock_factory)360 void DynamicMessage::SharedCtor(bool lock_factory) {
361   // We need to call constructors for various fields manually and set
362   // default values where appropriate.  We use placement new to call
363   // constructors.  If you haven't heard of placement new, I suggest Googling
364   // it now.  We use placement new even for primitive types that don't have
365   // constructors for consistency.  (In theory, placement new should be used
366   // any time you are trying to convert untyped memory to typed memory, though
367   // in practice that's not strictly necessary for types that don't have a
368   // constructor.)
369 
370   const Descriptor* descriptor = type_info_->type;
371   // Initialize oneof cases.
372   int oneof_count = 0;
373   for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
374     if (descriptor->oneof_decl(i)->is_synthetic()) continue;
375     new (MutableOneofCaseRaw(oneof_count++)) uint32_t{0};
376   }
377 
378   if (type_info_->extensions_offset != -1) {
379     new (MutableExtensionsRaw()) ExtensionSet(GetArenaForAllocation());
380   }
381   for (int i = 0; i < descriptor->field_count(); i++) {
382     const FieldDescriptor* field = descriptor->field(i);
383     void* field_ptr = MutableRaw(i);
384     if (InRealOneof(field)) {
385       continue;
386     }
387     switch (field->cpp_type()) {
388 #define HANDLE_TYPE(CPPTYPE, TYPE)                                  \
389   case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
390     if (!field->is_repeated()) {                                    \
391       new (field_ptr) TYPE(field->default_value_##TYPE());          \
392     } else {                                                        \
393       new (field_ptr) RepeatedField<TYPE>(GetArenaForAllocation()); \
394     }                                                               \
395     break;
396 
397       HANDLE_TYPE(INT32, int32_t);
398       HANDLE_TYPE(INT64, int64_t);
399       HANDLE_TYPE(UINT32, uint32_t);
400       HANDLE_TYPE(UINT64, uint64_t);
401       HANDLE_TYPE(DOUBLE, double);
402       HANDLE_TYPE(FLOAT, float);
403       HANDLE_TYPE(BOOL, bool);
404 #undef HANDLE_TYPE
405 
406       case FieldDescriptor::CPPTYPE_ENUM:
407         if (!field->is_repeated()) {
408           new (field_ptr) int{field->default_value_enum()->number()};
409         } else {
410           new (field_ptr) RepeatedField<int>(GetArenaForAllocation());
411         }
412         break;
413 
414       case FieldDescriptor::CPPTYPE_STRING:
415         switch (field->options().ctype()) {
416           default:  // TODO(kenton):  Support other string reps.
417           case FieldOptions::STRING:
418             if (!field->is_repeated()) {
419               ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
420               asp->InitDefault();
421             } else {
422               new (field_ptr)
423                   RepeatedPtrField<std::string>(GetArenaForAllocation());
424             }
425             break;
426         }
427         break;
428 
429       case FieldDescriptor::CPPTYPE_MESSAGE: {
430         if (!field->is_repeated()) {
431           new (field_ptr) Message*(nullptr);
432         } else {
433           if (IsMapFieldInApi(field)) {
434             // We need to lock in most cases to avoid data racing. Only not lock
435             // when the constructor is called inside GetPrototype(), in which
436             // case we have already locked the factory.
437             if (lock_factory) {
438               if (GetArenaForAllocation() != nullptr) {
439                 new (field_ptr) DynamicMapField(
440                     type_info_->factory->GetPrototype(field->message_type()),
441                     GetArenaForAllocation());
442                 if (GetOwningArena() != nullptr) {
443                   // Needs to destroy the mutex member.
444                   GetOwningArena()->OwnDestructor(
445                       static_cast<DynamicMapField*>(field_ptr));
446                 }
447               } else {
448                 new (field_ptr) DynamicMapField(
449                     type_info_->factory->GetPrototype(field->message_type()));
450               }
451             } else {
452               if (GetArenaForAllocation() != nullptr) {
453                 new (field_ptr)
454                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
455                                         field->message_type()),
456                                     GetArenaForAllocation());
457                 if (GetOwningArena() != nullptr) {
458                   // Needs to destroy the mutex member.
459                   GetOwningArena()->OwnDestructor(
460                       static_cast<DynamicMapField*>(field_ptr));
461                 }
462               } else {
463                 new (field_ptr)
464                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
465                         field->message_type()));
466               }
467             }
468           } else {
469             new (field_ptr) RepeatedPtrField<Message>(GetArenaForAllocation());
470           }
471         }
472         break;
473       }
474     }
475   }
476 }
477 
is_prototype() const478 bool DynamicMessage::is_prototype() const {
479   return type_info_->prototype == this ||
480          // If type_info_->prototype is nullptr, then we must be constructing
481          // the prototype now, which means we must be the prototype.
482          type_info_->prototype == nullptr;
483 }
484 
485 #if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
operator delete(DynamicMessage * msg,std::destroying_delete_t)486 void DynamicMessage::operator delete(DynamicMessage* msg,
487                                      std::destroying_delete_t) {
488   const size_t size = msg->type_info_->size;
489   msg->~DynamicMessage();
490   ::operator delete(msg, size);
491 }
492 #endif
493 
~DynamicMessage()494 DynamicMessage::~DynamicMessage() {
495   const Descriptor* descriptor = type_info_->type;
496 
497   _internal_metadata_.Delete<UnknownFieldSet>();
498 
499   if (type_info_->extensions_offset != -1) {
500     reinterpret_cast<ExtensionSet*>(MutableExtensionsRaw())->~ExtensionSet();
501   }
502 
503   // We need to manually run the destructors for repeated fields and strings,
504   // just as we ran their constructors in the DynamicMessage constructor.
505   // We also need to manually delete oneof fields if it is set and is string
506   // or message.
507   // Additionally, if any singular embedded messages have been allocated, we
508   // need to delete them, UNLESS we are the prototype message of this type,
509   // in which case any embedded messages are other prototypes and shouldn't
510   // be touched.
511   for (int i = 0; i < descriptor->field_count(); i++) {
512     const FieldDescriptor* field = descriptor->field(i);
513     if (InRealOneof(field)) {
514       void* field_ptr = MutableOneofCaseRaw(field->containing_oneof()->index());
515       if (*(reinterpret_cast<const int32_t*>(field_ptr)) == field->number()) {
516         field_ptr = MutableOneofFieldRaw(field);
517         if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
518           switch (field->options().ctype()) {
519             default:
520             case FieldOptions::STRING: {
521               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy();
522               break;
523             }
524           }
525         } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
526             delete *reinterpret_cast<Message**>(field_ptr);
527         }
528       }
529       continue;
530     }
531     void* field_ptr = MutableRaw(i);
532 
533     if (field->is_repeated()) {
534       switch (field->cpp_type()) {
535 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                  \
536   case FieldDescriptor::CPPTYPE_##UPPERCASE:               \
537     reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
538         ->~RepeatedField<LOWERCASE>();                     \
539     break
540 
541         HANDLE_TYPE(INT32, int32_t);
542         HANDLE_TYPE(INT64, int64_t);
543         HANDLE_TYPE(UINT32, uint32_t);
544         HANDLE_TYPE(UINT64, uint64_t);
545         HANDLE_TYPE(DOUBLE, double);
546         HANDLE_TYPE(FLOAT, float);
547         HANDLE_TYPE(BOOL, bool);
548         HANDLE_TYPE(ENUM, int);
549 #undef HANDLE_TYPE
550 
551         case FieldDescriptor::CPPTYPE_STRING:
552           switch (field->options().ctype()) {
553             default:  // TODO(kenton):  Support other string reps.
554             case FieldOptions::STRING:
555               reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr)
556                   ->~RepeatedPtrField<std::string>();
557               break;
558           }
559           break;
560 
561         case FieldDescriptor::CPPTYPE_MESSAGE:
562           if (IsMapFieldInApi(field)) {
563             reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
564           } else {
565             reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
566                 ->~RepeatedPtrField<Message>();
567           }
568           break;
569       }
570 
571     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
572       switch (field->options().ctype()) {
573         default:  // TODO(kenton):  Support other string reps.
574         case FieldOptions::STRING: {
575           reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy();
576           break;
577         }
578       }
579     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
580           if (!is_prototype()) {
581         Message* message = *reinterpret_cast<Message**>(field_ptr);
582         if (message != nullptr) {
583           delete message;
584         }
585       }
586     }
587   }
588 }
589 
CrossLinkPrototypes()590 void DynamicMessage::CrossLinkPrototypes() {
591   // This should only be called on the prototype message.
592   GOOGLE_CHECK(is_prototype());
593 
594   DynamicMessageFactory* factory = type_info_->factory;
595   const Descriptor* descriptor = type_info_->type;
596 
597   // Cross-link default messages.
598   for (int i = 0; i < descriptor->field_count(); i++) {
599     const FieldDescriptor* field = descriptor->field(i);
600     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
601         !field->options().weak() && !InRealOneof(field) &&
602         !field->is_repeated()) {
603       void* field_ptr = MutableRaw(i);
604       // For fields with message types, we need to cross-link with the
605       // prototype for the field's type.
606       // For singular fields, the field is just a pointer which should
607       // point to the prototype.
608       *reinterpret_cast<const Message**>(field_ptr) =
609           factory->GetPrototypeNoLock(field->message_type());
610     }
611   }
612 }
613 
New(Arena * arena) const614 Message* DynamicMessage::New(Arena* arena) const {
615   if (arena != nullptr) {
616     void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
617     memset(new_base, 0, type_info_->size);
618     return new (new_base) DynamicMessage(type_info_, arena);
619   } else {
620     void* new_base = operator new(type_info_->size);
621     memset(new_base, 0, type_info_->size);
622     return new (new_base) DynamicMessage(type_info_);
623   }
624 }
625 
GetCachedSize() const626 int DynamicMessage::GetCachedSize() const {
627   return cached_byte_size_.load(std::memory_order_relaxed);
628 }
629 
SetCachedSize(int size) const630 void DynamicMessage::SetCachedSize(int size) const {
631   cached_byte_size_.store(size, std::memory_order_relaxed);
632 }
633 
GetMetadata() const634 Metadata DynamicMessage::GetMetadata() const {
635   Metadata metadata;
636   metadata.descriptor = type_info_->type;
637   metadata.reflection = type_info_->reflection.get();
638   return metadata;
639 }
640 
641 // ===================================================================
642 
DynamicMessageFactory()643 DynamicMessageFactory::DynamicMessageFactory()
644     : pool_(nullptr), delegate_to_generated_factory_(false) {}
645 
DynamicMessageFactory(const DescriptorPool * pool)646 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
647     : pool_(pool), delegate_to_generated_factory_(false) {}
648 
~DynamicMessageFactory()649 DynamicMessageFactory::~DynamicMessageFactory() {
650   for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) {
651     delete iter->second;
652   }
653 }
654 
GetPrototype(const Descriptor * type)655 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
656   MutexLock lock(&prototypes_mutex_);
657   return GetPrototypeNoLock(type);
658 }
659 
GetPrototypeNoLock(const Descriptor * type)660 const Message* DynamicMessageFactory::GetPrototypeNoLock(
661     const Descriptor* type) {
662   if (delegate_to_generated_factory_ &&
663       type->file()->pool() == DescriptorPool::generated_pool()) {
664     return MessageFactory::generated_factory()->GetPrototype(type);
665   }
666 
667   const TypeInfo** target = &prototypes_[type];
668   if (*target != nullptr) {
669     // Already exists.
670     return (*target)->prototype;
671   }
672 
673   TypeInfo* type_info = new TypeInfo;
674   *target = type_info;
675 
676   type_info->type = type;
677   type_info->pool = (pool_ == nullptr) ? type->file()->pool() : pool_;
678   type_info->factory = this;
679 
680   // We need to construct all the structures passed to Reflection's constructor.
681   // This includes:
682   // - A block of memory that contains space for all the message's fields.
683   // - An array of integers indicating the byte offset of each field within
684   //   this block.
685   // - A big bitfield containing a bit for each field indicating whether
686   //   or not that field is set.
687   int real_oneof_count = 0;
688   for (int i = 0; i < type->oneof_decl_count(); i++) {
689     if (!type->oneof_decl(i)->is_synthetic()) {
690       real_oneof_count++;
691     }
692   }
693 
694   // Compute size and offsets.
695   uint32_t* offsets = new uint32_t[type->field_count() + real_oneof_count];
696   type_info->offsets.reset(offsets);
697 
698   // Decide all field offsets by packing in order.
699   // We place the DynamicMessage object itself at the beginning of the allocated
700   // space.
701   int size = sizeof(DynamicMessage);
702   size = AlignOffset(size);
703 
704   // Next the has_bits, which is an array of uint32s.
705   type_info->has_bits_offset = -1;
706   int max_hasbit = 0;
707   for (int i = 0; i < type->field_count(); i++) {
708     if (HasHasbit(type->field(i))) {
709       if (type_info->has_bits_offset == -1) {
710         // At least one field in the message requires a hasbit, so allocate
711         // hasbits.
712         type_info->has_bits_offset = size;
713         uint32_t* has_bits_indices = new uint32_t[type->field_count()];
714         for (int j = 0; j < type->field_count(); j++) {
715           // Initialize to -1, fields that need a hasbit will overwrite.
716           has_bits_indices[j] = static_cast<uint32_t>(-1);
717         }
718         type_info->has_bits_indices.reset(has_bits_indices);
719       }
720       type_info->has_bits_indices[i] = max_hasbit++;
721     }
722   }
723 
724   if (max_hasbit > 0) {
725     int has_bits_array_size = DivideRoundingUp(max_hasbit, bitsizeof(uint32_t));
726     size += has_bits_array_size * sizeof(uint32_t);
727     size = AlignOffset(size);
728   }
729 
730   // The oneof_case, if any. It is an array of uint32s.
731   if (real_oneof_count > 0) {
732     type_info->oneof_case_offset = size;
733     size += real_oneof_count * sizeof(uint32_t);
734     size = AlignOffset(size);
735   }
736 
737   // The ExtensionSet, if any.
738   if (type->extension_range_count() > 0) {
739     type_info->extensions_offset = size;
740     size += sizeof(ExtensionSet);
741     size = AlignOffset(size);
742   } else {
743     // No extensions.
744     type_info->extensions_offset = -1;
745   }
746 
747   // All the fields.
748   //
749   // TODO(b/31226269):  Optimize the order of fields to minimize padding.
750   for (int i = 0; i < type->field_count(); i++) {
751     // Make sure field is aligned to avoid bus errors.
752     // Oneof fields do not use any space.
753     if (!InRealOneof(type->field(i))) {
754       int field_size = FieldSpaceUsed(type->field(i));
755       size = AlignTo(size, std::min(kSafeAlignment, field_size));
756       offsets[i] = size;
757       size += field_size;
758     }
759   }
760 
761   // The oneofs.
762   for (int i = 0; i < type->oneof_decl_count(); i++) {
763     if (!type->oneof_decl(i)->is_synthetic()) {
764       size = AlignTo(size, kSafeAlignment);
765       offsets[type->field_count() + i] = size;
766       size += kMaxOneofUnionSize;
767     }
768   }
769 
770   type_info->weak_field_map_offset = -1;
771 
772   // Align the final size to make sure no clever allocators think that
773   // alignment is not necessary.
774   type_info->size = size;
775 
776   // Construct the reflection object.
777 
778   // Compute the size of default oneof instance and offsets of default
779   // oneof fields.
780   for (int i = 0; i < type->oneof_decl_count(); i++) {
781     if (type->oneof_decl(i)->is_synthetic()) continue;
782     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
783       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
784       // oneof fields are not accessed through offsets, but we still have the
785       // entry from a legacy implementation. This should be removed at some
786       // point.
787       // Mark the field to prevent unintentional access through reflection.
788       // Don't use the top bit because that is for unused fields.
789       offsets[field->index()] = internal::kInvalidFieldOffsetTag;
790     }
791   }
792 
793   // Allocate the prototype fields.
794   void* base = operator new(size);
795   memset(base, 0, size);
796 
797   // We have already locked the factory so we should not lock in the constructor
798   // of dynamic message to avoid dead lock.
799   DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
800 
801   internal::ReflectionSchema schema = {
802       type_info->prototype,
803       type_info->offsets.get(),
804       type_info->has_bits_indices.get(),
805       type_info->has_bits_offset,
806       PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_),
807       type_info->extensions_offset,
808       type_info->oneof_case_offset,
809       type_info->size,
810       type_info->weak_field_map_offset,
811       nullptr /* inlined_string_indices_ */,
812       0 /* inlined_string_donated_offset_ */};
813 
814   type_info->reflection.reset(
815       new Reflection(type_info->type, schema, type_info->pool, this));
816 
817   // Cross link prototypes.
818   prototype->CrossLinkPrototypes();
819 
820   return prototype;
821 }
822 
823 }  // namespace protobuf
824 }  // namespace google
825 
826 #include <google/protobuf/port_undef.inc>  // NOLINT
827