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 #include "google/protobuf/message.h"
13
14 #include <atomic>
15 #include <cstddef>
16 #include <cstdint>
17 #include <cstring>
18 #include <new> // IWYU pragma: keep for operator new().
19 #include <queue>
20 #include <string>
21 #include <vector>
22
23 #include "absl/base/call_once.h"
24 #include "absl/base/optimization.h"
25 #include "absl/container/flat_hash_map.h"
26 #include "absl/container/flat_hash_set.h"
27 #include "absl/hash/hash.h"
28 #include "absl/log/absl_check.h"
29 #include "absl/log/absl_log.h"
30 #include "absl/strings/str_join.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/synchronization/mutex.h"
33 #include "absl/types/optional.h"
34 #include "google/protobuf/descriptor.h"
35 #include "google/protobuf/descriptor.pb.h"
36 #include "google/protobuf/dynamic_message.h"
37 #include "google/protobuf/generated_message_reflection.h"
38 #include "google/protobuf/generated_message_tctable_impl.h"
39 #include "google/protobuf/generated_message_util.h"
40 #include "google/protobuf/io/coded_stream.h"
41 #include "google/protobuf/map_field.h"
42 #include "google/protobuf/message_lite.h"
43 #include "google/protobuf/parse_context.h"
44 #include "google/protobuf/port.h"
45 #include "google/protobuf/reflection_internal.h"
46 #include "google/protobuf/reflection_ops.h"
47 #include "google/protobuf/reflection_visit_fields.h"
48 #include "google/protobuf/unknown_field_set.h"
49 #include "google/protobuf/wire_format.h"
50
51
52 // Must be included last.
53 #include "google/protobuf/port_def.inc"
54
55 namespace google {
56 namespace protobuf {
57 namespace internal {
58
59 // TODO make this factorized better. This should not have to hop
60 // to reflection. Currently uses GeneratedMessageReflection and thus is
61 // defined in generated_message_reflection.cc
62 void RegisterFileLevelMetadata(const DescriptorTable* descriptor_table);
63
64 } // namespace internal
65
66 using internal::ReflectionOps;
67 using internal::WireFormat;
68
MergeImpl(MessageLite & to,const MessageLite & from)69 void Message::MergeImpl(MessageLite& to, const MessageLite& from) {
70 ReflectionOps::Merge(DownCastMessage<Message>(from),
71 DownCastMessage<Message>(&to));
72 }
73
ClearImpl()74 void Message::ClearImpl() {
75 ReflectionOps::Clear(DownCastMessage<Message>(this));
76 }
77
ByteSizeLongImpl(const MessageLite & msg)78 size_t Message::ByteSizeLongImpl(const MessageLite& msg) {
79 auto& _this = DownCastMessage<Message>(msg);
80 size_t size = WireFormat::ByteSize(_this);
81 _this.AccessCachedSize().Set(internal::ToCachedSize(size));
82 return size;
83 }
84
_InternalSerializeImpl(const MessageLite & msg,uint8_t * target,io::EpsCopyOutputStream * stream)85 uint8_t* Message::_InternalSerializeImpl(const MessageLite& msg,
86 uint8_t* target,
87 io::EpsCopyOutputStream* stream) {
88 return WireFormat::_InternalSerialize(DownCastMessage<Message>(msg), target,
89 stream);
90 }
91
MergeFrom(const Message & from)92 void Message::MergeFrom(const Message& from) {
93 auto* class_to = GetClassData();
94 auto* class_from = from.GetClassData();
95 if (class_to == nullptr || class_to != class_from) {
96 ReflectionOps::Merge(from, this);
97 } else {
98 class_to->full().merge_to_from(*this, from);
99 }
100 }
101
CopyFrom(const Message & from)102 void Message::CopyFrom(const Message& from) {
103 if (&from == this) return;
104
105 auto* class_to = GetClassData();
106 auto* class_from = from.GetClassData();
107
108 if (class_from != nullptr && class_from == class_to) {
109 // Fail if "from" is a descendant of "to" as such copy is not allowed.
110 ABSL_DCHECK(!internal::IsDescendant(*this, from))
111 << "Source of CopyFrom cannot be a descendant of the target.";
112 Clear();
113 class_to->full().merge_to_from(*this, from);
114 } else {
115 const Descriptor* descriptor = GetDescriptor();
116 ABSL_CHECK_EQ(from.GetDescriptor(), descriptor)
117 << ": Tried to copy from a message with a different type. "
118 "to: "
119 << descriptor->full_name()
120 << ", "
121 "from: "
122 << from.GetDescriptor()->full_name();
123 ReflectionOps::Copy(from, this);
124 }
125 }
126
127 #if !defined(PROTOBUF_CUSTOM_VTABLE)
Clear()128 void Message::Clear() { ReflectionOps::Clear(this); }
129 #endif // !PROTOBUF_CUSTOM_VTABLE
130
IsInitializedImpl(const MessageLite & msg)131 bool Message::IsInitializedImpl(const MessageLite& msg) {
132 return ReflectionOps::IsInitialized(DownCastMessage<Message>(msg));
133 }
134
FindInitializationErrors(std::vector<std::string> * errors) const135 void Message::FindInitializationErrors(std::vector<std::string>* errors) const {
136 return ReflectionOps::FindInitializationErrors(*this, "", errors);
137 }
138
InitializationErrorString() const139 std::string Message::InitializationErrorString() const {
140 std::vector<std::string> errors;
141 FindInitializationErrors(&errors);
142 return absl::StrJoin(errors, ", ");
143 }
144
CheckInitialized() const145 void Message::CheckInitialized() const {
146 ABSL_CHECK(IsInitialized())
147 << "Message of type \"" << GetDescriptor()->full_name()
148 << "\" is missing required fields: " << InitializationErrorString();
149 }
150
DiscardUnknownFields()151 void Message::DiscardUnknownFields() {
152 return ReflectionOps::DiscardUnknownFields(this);
153 }
154
GetMetadata() const155 Metadata Message::GetMetadata() const {
156 return GetMetadataImpl(GetClassData()->full());
157 }
158
GetMetadataImpl(const internal::ClassDataFull & data)159 Metadata Message::GetMetadataImpl(const internal::ClassDataFull& data) {
160 auto* table = data.descriptor_table;
161 // Only codegen types provide a table. DynamicMessage does not provide a table
162 // and instead eagerly initializes the descriptor/reflection members.
163 if (ABSL_PREDICT_TRUE(table != nullptr)) {
164 if (ABSL_PREDICT_FALSE(data.get_metadata_tracker != nullptr)) {
165 data.get_metadata_tracker();
166 }
167 absl::call_once(*table->once, [table] {
168 internal::AssignDescriptorsOnceInnerCall(table);
169 });
170 }
171 return {data.descriptor, data.reflection};
172 }
173
174 #if !defined(PROTOBUF_CUSTOM_VTABLE)
_InternalSerialize(uint8_t * target,io::EpsCopyOutputStream * stream) const175 uint8_t* Message::_InternalSerialize(uint8_t* target,
176 io::EpsCopyOutputStream* stream) const {
177 return WireFormat::_InternalSerialize(*this, target, stream);
178 }
179
ByteSizeLong() const180 size_t Message::ByteSizeLong() const {
181 size_t size = WireFormat::ByteSize(*this);
182 AccessCachedSize().Set(internal::ToCachedSize(size));
183 return size;
184 }
185 #endif // !PROTOBUF_CUSTOM_VTABLE
186
ComputeUnknownFieldsSize(size_t total_size,const internal::CachedSize * cached_size) const187 size_t Message::ComputeUnknownFieldsSize(
188 size_t total_size, const internal::CachedSize* cached_size) const {
189 total_size += WireFormat::ComputeUnknownFieldsSize(
190 _internal_metadata_.unknown_fields<UnknownFieldSet>(
191 UnknownFieldSet::default_instance));
192 cached_size->Set(internal::ToCachedSize(total_size));
193 return total_size;
194 }
195
MaybeComputeUnknownFieldsSize(size_t total_size,const internal::CachedSize * cached_size) const196 size_t Message::MaybeComputeUnknownFieldsSize(
197 size_t total_size, const internal::CachedSize* cached_size) const {
198 if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
199 return ComputeUnknownFieldsSize(total_size, cached_size);
200 }
201 cached_size->Set(internal::ToCachedSize(total_size));
202 return total_size;
203 }
204
SpaceUsedLong() const205 size_t Message::SpaceUsedLong() const {
206 return GetClassData()->full().descriptor_methods->space_used_long(*this);
207 }
208
GetTypeNameImpl(const internal::ClassData * data)209 absl::string_view Message::GetTypeNameImpl(const internal::ClassData* data) {
210 return GetMetadataImpl(data->full()).descriptor->full_name();
211 }
212
InitializationErrorStringImpl(const MessageLite & msg)213 static std::string InitializationErrorStringImpl(const MessageLite& msg) {
214 return DownCastMessage<Message>(msg).InitializationErrorString();
215 }
216
GetTcParseTableImpl(const MessageLite & msg)217 const internal::TcParseTableBase* Message::GetTcParseTableImpl(
218 const MessageLite& msg) {
219 return DownCastMessage<Message>(msg).GetReflection()->GetTcParseTable();
220 }
221
SpaceUsedLongImpl(const MessageLite & msg_lite)222 size_t Message::SpaceUsedLongImpl(const MessageLite& msg_lite) {
223 auto& msg = DownCastMessage<Message>(msg_lite);
224 return msg.GetReflection()->SpaceUsedLong(msg);
225 }
226
DebugStringImpl(const MessageLite & msg)227 static std::string DebugStringImpl(const MessageLite& msg) {
228 return DownCastMessage<Message>(msg).DebugString();
229 }
230
231 PROTOBUF_CONSTINIT const internal::DescriptorMethods
232 Message::kDescriptorMethods = {
233 GetTypeNameImpl, InitializationErrorStringImpl,
234 GetTcParseTableImpl, SpaceUsedLongImpl,
235 DebugStringImpl,
236 };
237
238 namespace internal {
CreateSplitMessageGeneric(Arena * arena,const void * default_split,size_t size,const void * message,const void * default_message)239 void* CreateSplitMessageGeneric(Arena* arena, const void* default_split,
240 size_t size, const void* message,
241 const void* default_message) {
242 ABSL_DCHECK_NE(message, default_message);
243 void* split =
244 (arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size);
245 memcpy(split, default_split, size);
246 return split;
247 }
248 } // namespace internal
249
250 // =============================================================================
251 // MessageFactory
252
253 MessageFactory::~MessageFactory() = default;
254
255 namespace {
256
257 class GeneratedMessageFactory final : public MessageFactory {
258 public:
259 static GeneratedMessageFactory* singleton();
260
261 void RegisterFile(const google::protobuf::internal::DescriptorTable* table);
262 void RegisterType(const Descriptor* descriptor, const Message* prototype);
263
264 const Message* TryGetPrototype(const Descriptor* type);
265
266 // implements MessageFactory ---------------------------------------
267 const Message* GetPrototype(const Descriptor* type) override;
268
269 private:
GeneratedMessageFactory()270 GeneratedMessageFactory() {
271 dropped_defaults_factory_.SetDelegateToGeneratedFactory(true);
272 }
273
FindInTypeMap(const Descriptor * type)274 absl::optional<const Message*> FindInTypeMap(const Descriptor* type)
275 ABSL_SHARED_LOCKS_REQUIRED(mutex_)
276 {
277 auto it = type_map_.find(type);
278 if (it == type_map_.end()) return absl::nullopt;
279 return it->second.get();
280 }
281
FindInFileMap(absl::string_view name)282 const google::protobuf::internal::DescriptorTable* FindInFileMap(
283 absl::string_view name) {
284 auto it = files_.find(name);
285 if (it == files_.end()) return nullptr;
286 return *it;
287 }
288
289 struct DescriptorByNameHash {
290 using is_transparent = void;
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameHash291 size_t operator()(const google::protobuf::internal::DescriptorTable* t) const {
292 return absl::HashOf(absl::string_view{t->filename});
293 }
294
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameHash295 size_t operator()(absl::string_view name) const {
296 return absl::HashOf(name);
297 }
298 };
299 struct DescriptorByNameEq {
300 using is_transparent = void;
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameEq301 bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
302 const google::protobuf::internal::DescriptorTable* rhs) const {
303 return lhs == rhs || (*this)(lhs->filename, rhs->filename);
304 }
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameEq305 bool operator()(absl::string_view lhs,
306 const google::protobuf::internal::DescriptorTable* rhs) const {
307 return (*this)(lhs, rhs->filename);
308 }
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameEq309 bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
310 absl::string_view rhs) const {
311 return (*this)(lhs->filename, rhs);
312 }
operator ()google::protobuf::__anon5d6256a00211::GeneratedMessageFactory::DescriptorByNameEq313 bool operator()(absl::string_view lhs, absl::string_view rhs) const {
314 return lhs == rhs;
315 }
316 };
317
318 // Only written at static init time, so does not require locking.
319 absl::flat_hash_set<const google::protobuf::internal::DescriptorTable*,
320 DescriptorByNameHash, DescriptorByNameEq>
321 files_;
322 DynamicMessageFactory dropped_defaults_factory_;
323
324 absl::Mutex mutex_;
325 class MessagePtr {
326 public:
MessagePtr()327 MessagePtr() : value_() {}
MessagePtr(const Message * msg)328 explicit MessagePtr(const Message* msg) : value_(msg) {}
get() const329 const Message* get() const { return value_; }
set(const Message * msg)330 void set(const Message* msg) { value_ = msg; }
331
332 private:
333 const Message* value_;
334 };
335 absl::flat_hash_map<const Descriptor*, MessagePtr> type_map_
336 ABSL_GUARDED_BY(mutex_);
337 };
338
singleton()339 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
340 static auto instance =
341 internal::OnShutdownDelete(new GeneratedMessageFactory);
342 return instance;
343 }
344
RegisterFile(const google::protobuf::internal::DescriptorTable * table)345 void GeneratedMessageFactory::RegisterFile(
346 const google::protobuf::internal::DescriptorTable* table) {
347 if (!files_.insert(table).second) {
348 ABSL_LOG(FATAL) << "File is already registered: " << table->filename;
349 }
350 }
351
RegisterType(const Descriptor * descriptor,const Message * prototype)352 void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
353 const Message* prototype) {
354 ABSL_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
355 << "Tried to register a non-generated type with the generated "
356 "type registry.";
357
358 // This should only be called as a result of calling a file registration
359 // function during GetPrototype(), in which case we already have locked
360 // the mutex.
361 mutex_.AssertHeld();
362 if (!type_map_.try_emplace(descriptor, prototype).second) {
363 ABSL_DLOG(FATAL) << "Type is already registered: "
364 << descriptor->full_name();
365 }
366 }
367
368
GetPrototype(const Descriptor * type)369 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
370 const Message* result = TryGetPrototype(type);
371 if (result == nullptr &&
372 type->file()->pool() == DescriptorPool::generated_pool()) {
373 // We registered this descriptor with a null pointer.
374 // In this case we need to create the prototype from the dynamic factory.
375 // We _must_ do this outside the lock because the dynamic factory will call
376 // back into the generated factory for cross linking.
377 result = dropped_defaults_factory_.GetPrototype(type);
378
379 {
380 absl::WriterMutexLock lock(&mutex_);
381 // And update the main map to make the next lookup faster.
382 // We don't need to recheck here. Even if someone raced us here the result
383 // is the same, so we can just write it.
384 type_map_[type].set(result);
385 }
386 }
387
388 return result;
389 }
390
TryGetPrototype(const Descriptor * type)391 const Message* GeneratedMessageFactory::TryGetPrototype(
392 const Descriptor* type) {
393 absl::optional<const Message*> result;
394 {
395 absl::ReaderMutexLock lock(&mutex_);
396 result = FindInTypeMap(type);
397 if (result.has_value() && *result != nullptr) {
398 return *result;
399 }
400 }
401
402 // If the type is not in the generated pool, then we can't possibly handle
403 // it.
404 if (type->file()->pool() != DescriptorPool::generated_pool()) return nullptr;
405
406 // Apparently the file hasn't been registered yet. Let's do that now.
407 const internal::DescriptorTable* registration_data =
408 FindInFileMap(type->file()->name());
409 if (registration_data == nullptr) {
410 ABSL_DLOG(FATAL) << "File appears to be in generated pool but wasn't "
411 "registered: "
412 << type->file()->name();
413 return nullptr;
414 }
415
416 {
417 absl::WriterMutexLock lock(&mutex_);
418
419 // Check if another thread preempted us.
420 result = FindInTypeMap(type);
421 if (!result.has_value()) {
422 // Nope. OK, register everything.
423 internal::RegisterFileLevelMetadata(registration_data);
424 // Should be here now.
425 result = FindInTypeMap(type);
426 ABSL_DCHECK(result.has_value());
427 }
428 }
429
430 return *result;
431 }
432
433 } // namespace
434
TryGetGeneratedPrototype(const Descriptor * type)435 const Message* MessageFactory::TryGetGeneratedPrototype(
436 const Descriptor* type) {
437 return GeneratedMessageFactory::singleton()->TryGetPrototype(type);
438 }
439
generated_factory()440 MessageFactory* MessageFactory::generated_factory() {
441 return GeneratedMessageFactory::singleton();
442 }
443
InternalRegisterGeneratedFile(const google::protobuf::internal::DescriptorTable * table)444 void MessageFactory::InternalRegisterGeneratedFile(
445 const google::protobuf::internal::DescriptorTable* table) {
446 GeneratedMessageFactory::singleton()->RegisterFile(table);
447 }
448
InternalRegisterGeneratedMessage(const Descriptor * descriptor,const Message * prototype)449 void MessageFactory::InternalRegisterGeneratedMessage(
450 const Descriptor* descriptor, const Message* prototype) {
451 GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
452 }
453
454
455 namespace {
456 template <typename T>
GetSingleton()457 T* GetSingleton() {
458 static T singleton;
459 return &singleton;
460 }
461 } // namespace
462
RepeatedFieldAccessor(const FieldDescriptor * field) const463 const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
464 const FieldDescriptor* field) const {
465 ABSL_CHECK(field->is_repeated());
466 switch (field->cpp_type()) {
467 #define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
468 case FieldDescriptor::CPPTYPE_##TYPE: \
469 return GetSingleton<internal::RepeatedFieldPrimitiveAccessor<type> >();
470 HANDLE_PRIMITIVE_TYPE(INT32, int32_t)
471 HANDLE_PRIMITIVE_TYPE(UINT32, uint32_t)
472 HANDLE_PRIMITIVE_TYPE(INT64, int64_t)
473 HANDLE_PRIMITIVE_TYPE(UINT64, uint64_t)
474 HANDLE_PRIMITIVE_TYPE(FLOAT, float)
475 HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
476 HANDLE_PRIMITIVE_TYPE(BOOL, bool)
477 HANDLE_PRIMITIVE_TYPE(ENUM, int32_t)
478 #undef HANDLE_PRIMITIVE_TYPE
479 case FieldDescriptor::CPPTYPE_STRING:
480 switch (field->cpp_string_type()) {
481 case FieldDescriptor::CppStringType::kCord:
482 ABSL_LOG(FATAL) << "Repeated cords are not supported.";
483 case FieldDescriptor::CppStringType::kView:
484 case FieldDescriptor::CppStringType::kString:
485 return GetSingleton<internal::RepeatedPtrFieldStringAccessor>();
486 }
487 break;
488 case FieldDescriptor::CPPTYPE_MESSAGE:
489 if (field->is_map()) {
490 return GetSingleton<internal::MapFieldAccessor>();
491 } else {
492 return GetSingleton<internal::RepeatedPtrFieldMessageAccessor>();
493 }
494 }
495 ABSL_LOG(FATAL) << "Should not reach here.";
496 return nullptr;
497 }
498
499 namespace internal {
500 template <>
501 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
502 // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
503 // #240
504 PROTOBUF_NOINLINE
505 #endif
506 Message*
NewFromPrototype(const Message * prototype,Arena * arena)507 GenericTypeHandler<Message>::NewFromPrototype(const Message* prototype,
508 Arena* arena) {
509 return prototype->New(arena);
510 }
511 template <>
512 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
513 // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
514 // #240
515 PROTOBUF_NOINLINE
516 #endif
517 Arena*
GetArena(Message * value)518 GenericTypeHandler<Message>::GetArena(Message* value) {
519 return value->GetArena();
520 }
521
522 template void InternalMetadata::DoClear<UnknownFieldSet>();
523 template void InternalMetadata::DoMergeFrom<UnknownFieldSet>(
524 const UnknownFieldSet& other);
525 template void InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other);
526 template void InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>();
527 template UnknownFieldSet*
528 InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>();
529 } // namespace internal
530
531
532 } // namespace protobuf
533 } // namespace google
534
535 #include "google/protobuf/port_undef.inc"
536