• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: kenton@google.com (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[]".  This is because "operator new()" means "Give me some
59 // space which I can use as I please." while "new uint8[]" 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 <unordered_map>
71 
72 #include <google/protobuf/descriptor.pb.h>
73 #include <google/protobuf/descriptor.h>
74 #include <google/protobuf/generated_message_reflection.h>
75 #include <google/protobuf/generated_message_util.h>
76 #include <google/protobuf/unknown_field_set.h>
77 #include <google/protobuf/stubs/hash.h>
78 #include <google/protobuf/arenastring.h>
79 #include <google/protobuf/extension_set.h>
80 #include <google/protobuf/map_field.h>
81 #include <google/protobuf/map_field_inl.h>
82 #include <google/protobuf/map_type_handler.h>
83 #include <google/protobuf/reflection_ops.h>
84 #include <google/protobuf/repeated_field.h>
85 #include <google/protobuf/wire_format.h>
86 
87 #include <google/protobuf/port_def.inc>  // NOLINT
88 
89 namespace google {
90 namespace protobuf {
91 
92 using internal::DynamicMapField;
93 using internal::ExtensionSet;
94 using internal::MapField;
95 
96 
97 using internal::ArenaStringPtr;
98 
99 // ===================================================================
100 // Some helper tables and functions...
101 
102 namespace {
103 
IsMapFieldInApi(const FieldDescriptor * field)104 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
105 
106 // Sync with helpers.h.
HasHasbit(const FieldDescriptor * field)107 inline bool HasHasbit(const FieldDescriptor* field) {
108   // This predicate includes proto3 message fields only if they have "optional".
109   //   Foo submsg1 = 1;           // HasHasbit() == false
110   //   optional Foo submsg2 = 2;  // HasHasbit() == true
111   // This is slightly odd, as adding "optional" to a singular proto3 field does
112   // not change the semantics or API. However whenever any field in a message
113   // has a hasbit, it forces reflection to include hasbit offsets for *all*
114   // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
115   // causing a sudden size regression for ~all proto3 messages, we give proto3
116   // message fields a hasbit only if "optional" is present. If the user is
117   // explicitly writing "optional", it is likely they are writing it on
118   // primitive fields also.
119   return (field->has_optional_keyword() || field->is_required()) &&
120          !field->options().weak();
121 }
122 
InRealOneof(const FieldDescriptor * field)123 inline bool InRealOneof(const FieldDescriptor* field) {
124   return field->containing_oneof() &&
125          !field->containing_oneof()->is_synthetic();
126 }
127 
128 // Compute the byte size of the in-memory representation of the field.
FieldSpaceUsed(const FieldDescriptor * field)129 int FieldSpaceUsed(const FieldDescriptor* field) {
130   typedef FieldDescriptor FD;  // avoid line wrapping
131   if (field->label() == FD::LABEL_REPEATED) {
132     switch (field->cpp_type()) {
133       case FD::CPPTYPE_INT32:
134         return sizeof(RepeatedField<int32>);
135       case FD::CPPTYPE_INT64:
136         return sizeof(RepeatedField<int64>);
137       case FD::CPPTYPE_UINT32:
138         return sizeof(RepeatedField<uint32>);
139       case FD::CPPTYPE_UINT64:
140         return sizeof(RepeatedField<uint64>);
141       case FD::CPPTYPE_DOUBLE:
142         return sizeof(RepeatedField<double>);
143       case FD::CPPTYPE_FLOAT:
144         return sizeof(RepeatedField<float>);
145       case FD::CPPTYPE_BOOL:
146         return sizeof(RepeatedField<bool>);
147       case FD::CPPTYPE_ENUM:
148         return sizeof(RepeatedField<int>);
149       case FD::CPPTYPE_MESSAGE:
150         if (IsMapFieldInApi(field)) {
151           return sizeof(DynamicMapField);
152         } else {
153           return sizeof(RepeatedPtrField<Message>);
154         }
155 
156       case FD::CPPTYPE_STRING:
157         switch (field->options().ctype()) {
158           default:  // TODO(kenton):  Support other string reps.
159           case FieldOptions::STRING:
160             return sizeof(RepeatedPtrField<std::string>);
161         }
162         break;
163     }
164   } else {
165     switch (field->cpp_type()) {
166       case FD::CPPTYPE_INT32:
167         return sizeof(int32);
168       case FD::CPPTYPE_INT64:
169         return sizeof(int64);
170       case FD::CPPTYPE_UINT32:
171         return sizeof(uint32);
172       case FD::CPPTYPE_UINT64:
173         return sizeof(uint64);
174       case FD::CPPTYPE_DOUBLE:
175         return sizeof(double);
176       case FD::CPPTYPE_FLOAT:
177         return sizeof(float);
178       case FD::CPPTYPE_BOOL:
179         return sizeof(bool);
180       case FD::CPPTYPE_ENUM:
181         return sizeof(int);
182 
183       case FD::CPPTYPE_MESSAGE:
184         return sizeof(Message*);
185 
186       case FD::CPPTYPE_STRING:
187         switch (field->options().ctype()) {
188           default:  // TODO(kenton):  Support other string reps.
189           case FieldOptions::STRING:
190             return sizeof(ArenaStringPtr);
191         }
192         break;
193     }
194   }
195 
196   GOOGLE_LOG(DFATAL) << "Can't get here.";
197   return 0;
198 }
199 
200 // Compute the byte size of in-memory representation of the oneof fields
201 // in default oneof instance.
OneofFieldSpaceUsed(const FieldDescriptor * field)202 int OneofFieldSpaceUsed(const FieldDescriptor* field) {
203   typedef FieldDescriptor FD;  // avoid line wrapping
204   switch (field->cpp_type()) {
205     case FD::CPPTYPE_INT32:
206       return sizeof(int32);
207     case FD::CPPTYPE_INT64:
208       return sizeof(int64);
209     case FD::CPPTYPE_UINT32:
210       return sizeof(uint32);
211     case FD::CPPTYPE_UINT64:
212       return sizeof(uint64);
213     case FD::CPPTYPE_DOUBLE:
214       return sizeof(double);
215     case FD::CPPTYPE_FLOAT:
216       return sizeof(float);
217     case FD::CPPTYPE_BOOL:
218       return sizeof(bool);
219     case FD::CPPTYPE_ENUM:
220       return sizeof(int);
221 
222     case FD::CPPTYPE_MESSAGE:
223       return sizeof(Message*);
224 
225     case FD::CPPTYPE_STRING:
226       switch (field->options().ctype()) {
227         default:
228         case FieldOptions::STRING:
229           return sizeof(ArenaStringPtr);
230       }
231       break;
232   }
233 
234   GOOGLE_LOG(DFATAL) << "Can't get here.";
235   return 0;
236 }
237 
DivideRoundingUp(int i,int j)238 inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
239 
240 static const int kSafeAlignment = sizeof(uint64);
241 static const int kMaxOneofUnionSize = sizeof(uint64);
242 
AlignTo(int offset,int alignment)243 inline int AlignTo(int offset, int alignment) {
244   return DivideRoundingUp(offset, alignment) * alignment;
245 }
246 
247 // Rounds the given byte offset up to the next offset aligned such that any
248 // type may be stored at it.
AlignOffset(int offset)249 inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); }
250 
251 #define bitsizeof(T) (sizeof(T) * 8)
252 
253 }  // namespace
254 
255 // ===================================================================
256 
257 class DynamicMessage : public Message {
258  public:
259   struct TypeInfo {
260     int size;
261     int has_bits_offset;
262     int oneof_case_offset;
263     int extensions_offset;
264 
265     // Not owned by the TypeInfo.
266     DynamicMessageFactory* factory;  // The factory that created this object.
267     const DescriptorPool* pool;      // The factory's DescriptorPool.
268     const Descriptor* type;          // Type of this DynamicMessage.
269 
270     // Warning:  The order in which the following pointers are defined is
271     //   important (the prototype must be deleted *before* the offsets).
272     std::unique_ptr<uint32[]> offsets;
273     std::unique_ptr<uint32[]> has_bits_indices;
274     std::unique_ptr<const Reflection> reflection;
275     // Don't use a unique_ptr to hold the prototype: the destructor for
276     // DynamicMessage needs to know whether it is the prototype, and does so by
277     // looking back at this field. This would assume details about the
278     // implementation of unique_ptr.
279     const DynamicMessage* prototype;
280     int weak_field_map_offset;  // The offset for the weak_field_map;
281 
TypeInfogoogle::protobuf::DynamicMessage::TypeInfo282     TypeInfo() : prototype(NULL) {}
283 
~TypeInfogoogle::protobuf::DynamicMessage::TypeInfo284     ~TypeInfo() { delete prototype; }
285   };
286 
287   DynamicMessage(const TypeInfo* type_info);
288 
289   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
290   DynamicMessage(TypeInfo* type_info, bool lock_factory);
291 
292   ~DynamicMessage();
293 
294   // Called on the prototype after construction to initialize message fields.
295   void CrossLinkPrototypes();
296 
297   // implements Message ----------------------------------------------
298 
299   Message* New() const override;
300   Message* New(Arena* arena) const override;
301 
302   int GetCachedSize() const override;
303   void SetCachedSize(int size) const override;
304 
305   Metadata GetMetadata() const override;
306 
307   // We actually allocate more memory than sizeof(*this) when this
308   // class's memory is allocated via the global operator new. Thus, we need to
309   // manually call the global operator delete. Calling the destructor is taken
310   // care of for us. This makes DynamicMessage compatible with -fsized-delete.
311   // It doesn't work for MSVC though.
312 #ifndef _MSC_VER
operator delete(void * ptr)313   static void operator delete(void* ptr) { ::operator delete(ptr); }
314 #endif  // !_MSC_VER
315 
316  private:
317   DynamicMessage(const TypeInfo* type_info, Arena* arena);
318 
319   void SharedCtor(bool lock_factory);
320 
321   // Needed to get the offset of the internal metadata member.
322   friend class DynamicMessageFactory;
323 
is_prototype() const324   inline bool is_prototype() const {
325     return type_info_->prototype == this ||
326            // If type_info_->prototype is NULL, then we must be constructing
327            // the prototype now, which means we must be the prototype.
328            type_info_->prototype == NULL;
329   }
330 
OffsetToPointer(int offset)331   inline void* OffsetToPointer(int offset) {
332     return reinterpret_cast<uint8*>(this) + offset;
333   }
OffsetToPointer(int offset) const334   inline const void* OffsetToPointer(int offset) const {
335     return reinterpret_cast<const uint8*>(this) + offset;
336   }
337 
338   const TypeInfo* type_info_;
339   mutable std::atomic<int> cached_byte_size_;
340   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
341 };
342 
DynamicMessage(const TypeInfo * type_info)343 DynamicMessage::DynamicMessage(const TypeInfo* type_info)
344     : type_info_(type_info), cached_byte_size_(0) {
345   SharedCtor(true);
346 }
347 
DynamicMessage(const TypeInfo * type_info,Arena * arena)348 DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
349     : Message(arena),
350       type_info_(type_info),
351       cached_byte_size_(0) {
352   SharedCtor(true);
353 }
354 
DynamicMessage(TypeInfo * type_info,bool lock_factory)355 DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
356     : type_info_(type_info), cached_byte_size_(0) {
357   // The prototype in type_info has to be set before creating the prototype
358   // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
359   // creating prototype for Foo, prototype of the map entry will also be
360   // created, which needs the address of the prototype of Foo (the value in
361   // map). To break the cyclic dependency, we have to assign the address of
362   // prototype into type_info first.
363   type_info->prototype = this;
364   SharedCtor(lock_factory);
365 }
366 
SharedCtor(bool lock_factory)367 void DynamicMessage::SharedCtor(bool lock_factory) {
368   // We need to call constructors for various fields manually and set
369   // default values where appropriate.  We use placement new to call
370   // constructors.  If you haven't heard of placement new, I suggest Googling
371   // it now.  We use placement new even for primitive types that don't have
372   // constructors for consistency.  (In theory, placement new should be used
373   // any time you are trying to convert untyped memory to typed memory, though
374   // in practice that's not strictly necessary for types that don't have a
375   // constructor.)
376 
377   const Descriptor* descriptor = type_info_->type;
378   // Initialize oneof cases.
379   int oneof_count = 0;
380   for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
381     if (descriptor->oneof_decl(i)->is_synthetic()) continue;
382     new (OffsetToPointer(type_info_->oneof_case_offset +
383                          sizeof(uint32) * oneof_count++)) uint32(0);
384   }
385 
386   if (type_info_->extensions_offset != -1) {
387     new (OffsetToPointer(type_info_->extensions_offset))
388         ExtensionSet(GetArena());
389   }
390   for (int i = 0; i < descriptor->field_count(); i++) {
391     const FieldDescriptor* field = descriptor->field(i);
392     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
393     if (InRealOneof(field)) {
394       continue;
395     }
396     switch (field->cpp_type()) {
397 #define HANDLE_TYPE(CPPTYPE, TYPE)                         \
398   case FieldDescriptor::CPPTYPE_##CPPTYPE:                 \
399     if (!field->is_repeated()) {                           \
400       new (field_ptr) TYPE(field->default_value_##TYPE()); \
401     } else {                                               \
402       new (field_ptr) RepeatedField<TYPE>(GetArena());     \
403     }                                                      \
404     break;
405 
406       HANDLE_TYPE(INT32, int32);
407       HANDLE_TYPE(INT64, int64);
408       HANDLE_TYPE(UINT32, uint32);
409       HANDLE_TYPE(UINT64, uint64);
410       HANDLE_TYPE(DOUBLE, double);
411       HANDLE_TYPE(FLOAT, float);
412       HANDLE_TYPE(BOOL, bool);
413 #undef HANDLE_TYPE
414 
415       case FieldDescriptor::CPPTYPE_ENUM:
416         if (!field->is_repeated()) {
417           new (field_ptr) int(field->default_value_enum()->number());
418         } else {
419           new (field_ptr) RepeatedField<int>(GetArena());
420         }
421         break;
422 
423       case FieldDescriptor::CPPTYPE_STRING:
424         switch (field->options().ctype()) {
425           default:  // TODO(kenton):  Support other string reps.
426           case FieldOptions::STRING:
427             if (!field->is_repeated()) {
428               const std::string* default_value;
429               if (is_prototype()) {
430                 default_value = &field->default_value_string();
431               } else {
432                 default_value = &(reinterpret_cast<const ArenaStringPtr*>(
433                                       type_info_->prototype->OffsetToPointer(
434                                           type_info_->offsets[i]))
435                                       ->Get());
436               }
437               ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
438               asp->UnsafeSetDefault(default_value);
439             } else {
440               new (field_ptr) RepeatedPtrField<std::string>(GetArena());
441             }
442             break;
443         }
444         break;
445 
446       case FieldDescriptor::CPPTYPE_MESSAGE: {
447         if (!field->is_repeated()) {
448           new (field_ptr) Message*(NULL);
449         } else {
450           if (IsMapFieldInApi(field)) {
451             // We need to lock in most cases to avoid data racing. Only not lock
452             // when the constructor is called inside GetPrototype(), in which
453             // case we have already locked the factory.
454             if (lock_factory) {
455               if (GetArena() != nullptr) {
456                 new (field_ptr) DynamicMapField(
457                     type_info_->factory->GetPrototype(field->message_type()),
458                     GetArena());
459               } else {
460                 new (field_ptr) DynamicMapField(
461                     type_info_->factory->GetPrototype(field->message_type()));
462               }
463             } else {
464               if (GetArena() != nullptr) {
465                 new (field_ptr)
466                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
467                                         field->message_type()),
468                                     GetArena());
469               } else {
470                 new (field_ptr)
471                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
472                         field->message_type()));
473               }
474             }
475           } else {
476             new (field_ptr) RepeatedPtrField<Message>(GetArena());
477           }
478         }
479         break;
480       }
481     }
482   }
483 }
484 
~DynamicMessage()485 DynamicMessage::~DynamicMessage() {
486   const Descriptor* descriptor = type_info_->type;
487 
488   _internal_metadata_.Delete<UnknownFieldSet>();
489 
490   if (type_info_->extensions_offset != -1) {
491     reinterpret_cast<ExtensionSet*>(
492         OffsetToPointer(type_info_->extensions_offset))
493         ->~ExtensionSet();
494   }
495 
496   // We need to manually run the destructors for repeated fields and strings,
497   // just as we ran their constructors in the DynamicMessage constructor.
498   // We also need to manually delete oneof fields if it is set and is string
499   // or message.
500   // Additionally, if any singular embedded messages have been allocated, we
501   // need to delete them, UNLESS we are the prototype message of this type,
502   // in which case any embedded messages are other prototypes and shouldn't
503   // be touched.
504   for (int i = 0; i < descriptor->field_count(); i++) {
505     const FieldDescriptor* field = descriptor->field(i);
506     if (InRealOneof(field)) {
507       void* field_ptr =
508           OffsetToPointer(type_info_->oneof_case_offset +
509                           sizeof(uint32) * field->containing_oneof()->index());
510       if (*(reinterpret_cast<const uint32*>(field_ptr)) == field->number()) {
511         field_ptr = OffsetToPointer(
512             type_info_->offsets[descriptor->field_count() +
513                                 field->containing_oneof()->index()]);
514         if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
515           switch (field->options().ctype()) {
516             default:
517             case FieldOptions::STRING: {
518               const std::string* default_value =
519                   &(reinterpret_cast<const ArenaStringPtr*>(
520                         reinterpret_cast<const uint8*>(type_info_->prototype) +
521                         type_info_->offsets[i])
522                         ->Get());
523               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
524                   default_value, NULL);
525               break;
526             }
527           }
528         } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
529             delete *reinterpret_cast<Message**>(field_ptr);
530         }
531       }
532       continue;
533     }
534     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
535 
536     if (field->is_repeated()) {
537       switch (field->cpp_type()) {
538 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                  \
539   case FieldDescriptor::CPPTYPE_##UPPERCASE:               \
540     reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
541         ->~RepeatedField<LOWERCASE>();                     \
542     break
543 
544         HANDLE_TYPE(INT32, int32);
545         HANDLE_TYPE(INT64, int64);
546         HANDLE_TYPE(UINT32, uint32);
547         HANDLE_TYPE(UINT64, uint64);
548         HANDLE_TYPE(DOUBLE, double);
549         HANDLE_TYPE(FLOAT, float);
550         HANDLE_TYPE(BOOL, bool);
551         HANDLE_TYPE(ENUM, int);
552 #undef HANDLE_TYPE
553 
554         case FieldDescriptor::CPPTYPE_STRING:
555           switch (field->options().ctype()) {
556             default:  // TODO(kenton):  Support other string reps.
557             case FieldOptions::STRING:
558               reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr)
559                   ->~RepeatedPtrField<std::string>();
560               break;
561           }
562           break;
563 
564         case FieldDescriptor::CPPTYPE_MESSAGE:
565           if (IsMapFieldInApi(field)) {
566             reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
567           } else {
568             reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
569                 ->~RepeatedPtrField<Message>();
570           }
571           break;
572       }
573 
574     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
575       switch (field->options().ctype()) {
576         default:  // TODO(kenton):  Support other string reps.
577         case FieldOptions::STRING: {
578           const std::string* default_value =
579               &(reinterpret_cast<const ArenaStringPtr*>(
580                     type_info_->prototype->OffsetToPointer(
581                         type_info_->offsets[i]))
582                     ->Get());
583           reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
584                                                                 NULL);
585           break;
586         }
587       }
588     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
589           if (!is_prototype()) {
590         Message* message = *reinterpret_cast<Message**>(field_ptr);
591         if (message != NULL) {
592           delete message;
593         }
594       }
595     }
596   }
597 }
598 
CrossLinkPrototypes()599 void DynamicMessage::CrossLinkPrototypes() {
600   // This should only be called on the prototype message.
601   GOOGLE_CHECK(is_prototype());
602 
603   DynamicMessageFactory* factory = type_info_->factory;
604   const Descriptor* descriptor = type_info_->type;
605 
606   // Cross-link default messages.
607   for (int i = 0; i < descriptor->field_count(); i++) {
608     const FieldDescriptor* field = descriptor->field(i);
609     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
610     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
611         !field->is_repeated()) {
612       // For fields with message types, we need to cross-link with the
613       // prototype for the field's type.
614       // For singular fields, the field is just a pointer which should
615       // point to the prototype.
616       *reinterpret_cast<const Message**>(field_ptr) =
617           factory->GetPrototypeNoLock(field->message_type());
618     }
619   }
620 }
621 
New() const622 Message* DynamicMessage::New() const { return New(NULL); }
623 
New(Arena * arena) const624 Message* DynamicMessage::New(Arena* arena) const {
625   if (arena != NULL) {
626     void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
627     memset(new_base, 0, type_info_->size);
628     return new (new_base) DynamicMessage(type_info_, arena);
629   } else {
630     void* new_base = operator new(type_info_->size);
631     memset(new_base, 0, type_info_->size);
632     return new (new_base) DynamicMessage(type_info_);
633   }
634 }
635 
GetCachedSize() const636 int DynamicMessage::GetCachedSize() const {
637   return cached_byte_size_.load(std::memory_order_relaxed);
638 }
639 
SetCachedSize(int size) const640 void DynamicMessage::SetCachedSize(int size) const {
641   cached_byte_size_.store(size, std::memory_order_relaxed);
642 }
643 
GetMetadata() const644 Metadata DynamicMessage::GetMetadata() const {
645   Metadata metadata;
646   metadata.descriptor = type_info_->type;
647   metadata.reflection = type_info_->reflection.get();
648   return metadata;
649 }
650 
651 // ===================================================================
652 
653 struct DynamicMessageFactory::PrototypeMap {
654   typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
655       Map;
656   Map map_;
657 };
658 
DynamicMessageFactory()659 DynamicMessageFactory::DynamicMessageFactory()
660     : pool_(NULL),
661       delegate_to_generated_factory_(false),
662       prototypes_(new PrototypeMap) {}
663 
DynamicMessageFactory(const DescriptorPool * pool)664 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
665     : pool_(pool),
666       delegate_to_generated_factory_(false),
667       prototypes_(new PrototypeMap) {}
668 
~DynamicMessageFactory()669 DynamicMessageFactory::~DynamicMessageFactory() {
670   for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
671        iter != prototypes_->map_.end(); ++iter) {
672     DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
673                                iter->second->prototype);
674     delete iter->second;
675   }
676 }
677 
GetPrototype(const Descriptor * type)678 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
679   MutexLock lock(&prototypes_mutex_);
680   return GetPrototypeNoLock(type);
681 }
682 
GetPrototypeNoLock(const Descriptor * type)683 const Message* DynamicMessageFactory::GetPrototypeNoLock(
684     const Descriptor* type) {
685   if (delegate_to_generated_factory_ &&
686       type->file()->pool() == DescriptorPool::generated_pool()) {
687     return MessageFactory::generated_factory()->GetPrototype(type);
688   }
689 
690   const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
691   if (*target != NULL) {
692     // Already exists.
693     return (*target)->prototype;
694   }
695 
696   DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
697   *target = type_info;
698 
699   type_info->type = type;
700   type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
701   type_info->factory = this;
702 
703   // We need to construct all the structures passed to Reflection's constructor.
704   // This includes:
705   // - A block of memory that contains space for all the message's fields.
706   // - An array of integers indicating the byte offset of each field within
707   //   this block.
708   // - A big bitfield containing a bit for each field indicating whether
709   //   or not that field is set.
710   int real_oneof_count = 0;
711   for (int i = 0; i < type->oneof_decl_count(); i++) {
712     if (!type->oneof_decl(i)->is_synthetic()) {
713       real_oneof_count++;
714     }
715   }
716 
717   // Compute size and offsets.
718   uint32* offsets = new uint32[type->field_count() + real_oneof_count];
719   type_info->offsets.reset(offsets);
720 
721   // Decide all field offsets by packing in order.
722   // We place the DynamicMessage object itself at the beginning of the allocated
723   // space.
724   int size = sizeof(DynamicMessage);
725   size = AlignOffset(size);
726 
727   // Next the has_bits, which is an array of uint32s.
728   type_info->has_bits_offset = -1;
729   int max_hasbit = 0;
730   for (int i = 0; i < type->field_count(); i++) {
731     if (HasHasbit(type->field(i))) {
732       if (type_info->has_bits_offset == -1) {
733         // At least one field in the message requires a hasbit, so allocate
734         // hasbits.
735         type_info->has_bits_offset = size;
736         uint32* has_bits_indices = new uint32[type->field_count()];
737         for (int i = 0; i < type->field_count(); i++) {
738           // Initialize to -1, fields that need a hasbit will overwrite.
739           has_bits_indices[i] = static_cast<uint32>(-1);
740         }
741         type_info->has_bits_indices.reset(has_bits_indices);
742       }
743       type_info->has_bits_indices[i] = max_hasbit++;
744     }
745   }
746 
747   if (max_hasbit > 0) {
748     int has_bits_array_size = DivideRoundingUp(max_hasbit, bitsizeof(uint32));
749     size += has_bits_array_size * sizeof(uint32);
750     size = AlignOffset(size);
751   }
752 
753   // The oneof_case, if any. It is an array of uint32s.
754   if (real_oneof_count > 0) {
755     type_info->oneof_case_offset = size;
756     size += real_oneof_count * sizeof(uint32);
757     size = AlignOffset(size);
758   }
759 
760   // The ExtensionSet, if any.
761   if (type->extension_range_count() > 0) {
762     type_info->extensions_offset = size;
763     size += sizeof(ExtensionSet);
764     size = AlignOffset(size);
765   } else {
766     // No extensions.
767     type_info->extensions_offset = -1;
768   }
769 
770   // All the fields.
771   //
772   // TODO(b/31226269):  Optimize the order of fields to minimize padding.
773   int num_weak_fields = 0;
774   for (int i = 0; i < type->field_count(); i++) {
775     // Make sure field is aligned to avoid bus errors.
776     // Oneof fields do not use any space.
777     if (!InRealOneof(type->field(i))) {
778       int field_size = FieldSpaceUsed(type->field(i));
779       size = AlignTo(size, std::min(kSafeAlignment, field_size));
780       offsets[i] = size;
781       size += field_size;
782     }
783   }
784 
785   // The oneofs.
786   for (int i = 0; i < type->oneof_decl_count(); i++) {
787     if (!type->oneof_decl(i)->is_synthetic()) {
788       size = AlignTo(size, kSafeAlignment);
789       offsets[type->field_count() + i] = size;
790       size += kMaxOneofUnionSize;
791     }
792   }
793 
794   type_info->weak_field_map_offset = -1;
795 
796   // Align the final size to make sure no clever allocators think that
797   // alignment is not necessary.
798   type_info->size = size;
799 
800   // Construct the reflection object.
801 
802   // Compute the size of default oneof instance and offsets of default
803   // oneof fields.
804   for (int i = 0; i < type->oneof_decl_count(); i++) {
805     if (type->oneof_decl(i)->is_synthetic()) continue;
806     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
807       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
808       int field_size = OneofFieldSpaceUsed(field);
809       size = AlignTo(size, std::min(kSafeAlignment, field_size));
810       offsets[field->index()] = size;
811       size += field_size;
812     }
813   }
814   size = AlignOffset(size);
815   // Allocate the prototype + oneof fields.
816   void* base = operator new(size);
817   memset(base, 0, size);
818 
819   // We have already locked the factory so we should not lock in the constructor
820   // of dynamic message to avoid dead lock.
821   DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
822 
823   if (real_oneof_count > 0 || num_weak_fields > 0) {
824     // Construct default oneof instance.
825     ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
826                                   prototype);
827   }
828 
829   internal::ReflectionSchema schema = {
830       type_info->prototype,
831       type_info->offsets.get(),
832       type_info->has_bits_indices.get(),
833       type_info->has_bits_offset,
834       PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_),
835       type_info->extensions_offset,
836       type_info->oneof_case_offset,
837       type_info->size,
838       type_info->weak_field_map_offset};
839 
840   type_info->reflection.reset(
841       new Reflection(type_info->type, schema, type_info->pool, this));
842 
843   // Cross link prototypes.
844   prototype->CrossLinkPrototypes();
845 
846   return prototype;
847 }
848 
ConstructDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],void * default_oneof_or_weak_instance)849 void DynamicMessageFactory::ConstructDefaultOneofInstance(
850     const Descriptor* type, const uint32 offsets[],
851     void* default_oneof_or_weak_instance) {
852   for (int i = 0; i < type->oneof_decl_count(); i++) {
853     if (type->oneof_decl(i)->is_synthetic()) continue;
854     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
855       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
856       void* field_ptr =
857           reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
858           offsets[field->index()];
859       switch (field->cpp_type()) {
860 #define HANDLE_TYPE(CPPTYPE, TYPE)                       \
861   case FieldDescriptor::CPPTYPE_##CPPTYPE:               \
862     new (field_ptr) TYPE(field->default_value_##TYPE()); \
863     break;
864 
865         HANDLE_TYPE(INT32, int32);
866         HANDLE_TYPE(INT64, int64);
867         HANDLE_TYPE(UINT32, uint32);
868         HANDLE_TYPE(UINT64, uint64);
869         HANDLE_TYPE(DOUBLE, double);
870         HANDLE_TYPE(FLOAT, float);
871         HANDLE_TYPE(BOOL, bool);
872 #undef HANDLE_TYPE
873 
874         case FieldDescriptor::CPPTYPE_ENUM:
875           new (field_ptr) int(field->default_value_enum()->number());
876           break;
877         case FieldDescriptor::CPPTYPE_STRING:
878           switch (field->options().ctype()) {
879             default:
880             case FieldOptions::STRING:
881               ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
882               asp->UnsafeSetDefault(&field->default_value_string());
883               break;
884           }
885           break;
886 
887         case FieldDescriptor::CPPTYPE_MESSAGE: {
888           new (field_ptr) Message*(NULL);
889           break;
890         }
891       }
892     }
893   }
894 }
895 
DeleteDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],const void * default_oneof_instance)896 void DynamicMessageFactory::DeleteDefaultOneofInstance(
897     const Descriptor* type, const uint32 offsets[],
898     const void* default_oneof_instance) {
899   for (int i = 0; i < type->oneof_decl_count(); i++) {
900     if (type->oneof_decl(i)->is_synthetic()) continue;
901     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
902       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
903       if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
904         switch (field->options().ctype()) {
905           default:
906           case FieldOptions::STRING:
907             break;
908         }
909       }
910     }
911   }
912 }
913 
914 }  // namespace protobuf
915 }  // namespace google
916 
917 #include <google/protobuf/port_undef.inc>  // NOLINT
918