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