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