• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/generated_message_util.h"
13 
14 #include <atomic>
15 #include <cstdint>
16 #include <limits>
17 
18 #include "google/protobuf/arenastring.h"
19 #include "google/protobuf/extension_set.h"
20 #include "google/protobuf/io/coded_stream.h"
21 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
22 #include "google/protobuf/message_lite.h"
23 #include "google/protobuf/metadata_lite.h"
24 #include "google/protobuf/port.h"
25 #include "google/protobuf/repeated_field.h"
26 #include "google/protobuf/wire_format_lite.h"
27 
28 // Must be included last
29 #include "google/protobuf/port_def.inc"
30 
31 #ifndef PROTOBUF_PRAGMA_INIT_SEG_DONE
32 PROTOBUF_PRAGMA_INIT_SEG
33 #define PROTOBUF_PRAGMA_INIT_SEG_DONE
34 #endif
35 
36 
37 namespace google {
38 namespace protobuf {
39 namespace internal {
40 
DestroyString(const void * s)41 void DestroyString(const void* s) {
42   static_cast<const std::string*>(s)->~basic_string();
43 }
44 
45 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
46     PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExplicitlyConstructedArenaString
47         fixed_address_empty_string{};  // NOLINT
48 
49 
50 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT const EmptyCord empty_cord_;
51 
52 #if defined(PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED)
53 
54 // We add a single dummy entry to guarantee the section is never empty.
55 struct DummyWeakDefault {
56   const Message* m;
57   WeakDescriptorDefaultTail tail;
58 };
59 DummyWeakDefault dummy_weak_default __attribute__((section("pb_defaults"))) = {
60     nullptr, {&dummy_weak_default.m, sizeof(dummy_weak_default)}};
61 
62 extern "C" {
63 // When using --descriptor_implicit_weak_messages we expect the default instance
64 // objects to live in the `pb_defaults` section. We load them all using the
65 // __start/__end symbols provided by the linker.
66 // Each object is its own type and size, so we use a `char` to load them
67 // appropriately.
68 extern const char __start_pb_defaults;
69 extern const char __stop_pb_defaults;
70 }
InitWeakDefaults()71 static void InitWeakDefaults() {
72   // force link the dummy entry.
73   StrongPointer<DummyWeakDefault*, &dummy_weak_default>();
74   // We don't know the size of each object, but we know the layout of the tail.
75   // It contains a WeakDescriptorDefaultTail object.
76   // As such, we iterate the section backwards.
77   const char* start = &__start_pb_defaults;
78   const char* end = &__stop_pb_defaults;
79   while (start != end) {
80     auto* tail = reinterpret_cast<const WeakDescriptorDefaultTail*>(end) - 1;
81     end -= tail->size;
82     const Message* instance = reinterpret_cast<const Message*>(end);
83     *tail->target = instance;
84   }
85 }
86 #else
InitWeakDefaults()87 void InitWeakDefaults() {}
88 #endif
89 
90 PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false};
InitProtobufDefaultsImpl()91 static bool InitProtobufDefaultsImpl() {
92   fixed_address_empty_string.DefaultConstruct();
93   OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
94   InitWeakDefaults();
95 
96 
97   init_protobuf_defaults_state.store(true, std::memory_order_release);
98   return true;
99 }
100 
InitProtobufDefaultsSlow()101 void InitProtobufDefaultsSlow() {
102   static bool is_inited = InitProtobufDefaultsImpl();
103   (void)is_inited;
104 }
105 // Force the initialization of the empty string.
106 // Normally, registration would do it, but we don't have any guarantee that
107 // there is any object with reflection.
108 PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 static std::true_type init_empty_string =
109     (InitProtobufDefaultsSlow(), std::true_type{});
110 
StringSpaceUsedExcludingSelfLong(const std::string & str)111 size_t StringSpaceUsedExcludingSelfLong(const std::string& str) {
112   const void* start = &str;
113   const void* end = &str + 1;
114   if (start <= str.data() && str.data() < end) {
115     // The string's data is stored inside the string object itself.
116     return 0;
117   } else {
118     return str.capacity();
119   }
120 }
121 
122 template <typename T>
Get(const void * ptr)123 const T& Get(const void* ptr) {
124   return *static_cast<const T*>(ptr);
125 }
126 
127 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
128 // WireFormatLite has a very inconvenient interface with respect to template
129 // meta-programming. This class wraps the different named functions into
130 // a single Serialize / SerializeToArray interface.
131 template <int type>
132 struct PrimitiveTypeHelper;
133 
134 template <>
135 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
136   typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper137   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
138     WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
139   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper140   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
141     return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
142   }
143 };
144 
145 template <>
146 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
147   typedef int32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper148   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
149     WireFormatLite::WriteInt32NoTag(Get<int32_t>(ptr), output);
150   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper151   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
152     return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
153   }
154 };
155 
156 template <>
157 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
158   typedef int32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper159   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
160     WireFormatLite::WriteSInt32NoTag(Get<int32_t>(ptr), output);
161   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper162   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
163     return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
164   }
165 };
166 
167 template <>
168 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
169   typedef uint32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper170   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
171     WireFormatLite::WriteUInt32NoTag(Get<uint32_t>(ptr), output);
172   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper173   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
174     return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
175   }
176 };
177 template <>
178 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
179   typedef int64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper180   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
181     WireFormatLite::WriteInt64NoTag(Get<int64_t>(ptr), output);
182   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper183   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
184     return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
185   }
186 };
187 
188 template <>
189 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
190   typedef int64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper191   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
192     WireFormatLite::WriteSInt64NoTag(Get<int64_t>(ptr), output);
193   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper194   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
195     return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
196   }
197 };
198 template <>
199 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
200   typedef uint64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper201   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
202     WireFormatLite::WriteUInt64NoTag(Get<uint64_t>(ptr), output);
203   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper204   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
205     return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
206   }
207 };
208 
209 template <>
210 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
211   typedef uint32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper212   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
213     WireFormatLite::WriteFixed32NoTag(Get<uint32_t>(ptr), output);
214   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper215   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
216     return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
217   }
218 };
219 
220 template <>
221 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
222   typedef uint64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper223   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
224     WireFormatLite::WriteFixed64NoTag(Get<uint64_t>(ptr), output);
225   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper226   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
227     return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
228   }
229 };
230 
231 template <>
232 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
233     : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
234 
235 template <>
236 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
237     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
238   typedef int32_t Type;
239 };
240 template <>
241 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
242     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
243   typedef int64_t Type;
244 };
245 template <>
246 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
247     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
248   typedef float Type;
249 };
250 template <>
251 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
252     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
253   typedef double Type;
254 };
255 
256 template <>
257 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
258   typedef std::string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper259   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
260     const Type& value = *static_cast<const Type*>(ptr);
261     output->WriteVarint32(value.size());
262     output->WriteRawMaybeAliased(value.data(), value.size());
263   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper264   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
265     const Type& value = *static_cast<const Type*>(ptr);
266     return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
267   }
268 };
269 
270 template <>
271 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
272     : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
273 
274 // We want to serialize to both CodedOutputStream and directly into byte arrays
275 // without duplicating the code. In fact we might want extra output channels in
276 // the future.
277 template <typename O, int type>
278 struct OutputHelper;
279 
280 template <int type, typename O>
SerializeTo(const void * ptr,O * output)281 void SerializeTo(const void* ptr, O* output) {
282   OutputHelper<O, type>::Serialize(ptr, output);
283 }
284 
285 template <typename O>
WriteTagTo(uint32_t tag,O * output)286 void WriteTagTo(uint32_t tag, O* output) {
287   SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
288 }
289 
290 template <typename O>
WriteLengthTo(uint32_t length,O * output)291 void WriteLengthTo(uint32_t length, O* output) {
292   SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
293 }
294 
295 // Specialization for coded output stream
296 template <int type>
297 struct OutputHelper<io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper298   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
299     PrimitiveTypeHelper<type>::Serialize(ptr, output);
300   }
301 };
302 
303 // Specialization for writing into a plain array
304 struct ArrayOutput {
305   uint8_t* ptr;
306   bool is_deterministic;
307 };
308 
309 template <int type>
310 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper311   static void Serialize(const void* ptr, ArrayOutput* output) {
312     output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
313   }
314 };
315 
SerializeMessageNoTable(const MessageLite * msg,io::CodedOutputStream * output)316 void SerializeMessageNoTable(const MessageLite* msg,
317                              io::CodedOutputStream* output) {
318   msg->SerializeWithCachedSizes(output);
319 }
320 
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)321 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
322   io::ArrayOutputStream array_stream(output->ptr, INT_MAX);
323   io::CodedOutputStream o(&array_stream);
324   o.SetSerializationDeterministic(output->is_deterministic);
325   msg->SerializeWithCachedSizes(&o);
326   output->ptr += o.ByteCount();
327 }
328 
329 // We need to use a helper class to get access to the private members
330 class AccessorHelper {
331  public:
Size(const RepeatedPtrFieldBase & x)332   static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)333   static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
334     return x.raw_data()[idx];
335   }
336 };
337 
SerializeNotImplemented(int field)338 void SerializeNotImplemented(int field) {
339   ABSL_LOG(FATAL) << "Not implemented field number " << field;
340 }
341 
342 // When switching to c++11 we should make these constexpr functions
343 #define SERIALIZE_TABLE_OP(type, type_class) \
344   ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
345 
346 template <int type>
IsNull(const void * ptr)347 bool IsNull(const void* ptr) {
348   return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
349          0;
350 }
351 
352 template <>
IsNull(const void * ptr)353 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
354   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
355 }
356 
357 template <>
IsNull(const void * ptr)358 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
359   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
360 }
361 
362 template <>
IsNull(const void * ptr)363 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
364   return Get<const MessageLite*>(ptr) == nullptr;
365 }
366 
367 template <>
IsNull(const void * ptr)368 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
369   return Get<const MessageLite*>(ptr) == nullptr;
370 }
371 
ExtensionSerializer(const MessageLite * extendee,const uint8_t * ptr,uint32_t offset,uint32_t tag,uint32_t has_offset,io::CodedOutputStream * output)372 void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr,
373                          uint32_t offset, uint32_t tag, uint32_t has_offset,
374                          io::CodedOutputStream* output) {
375   reinterpret_cast<const ExtensionSet*>(ptr + offset)
376       ->SerializeWithCachedSizes(extendee, tag, has_offset, output);
377 }
378 
UnknownFieldSerializerLite(const uint8_t * ptr,uint32_t offset,uint32_t,uint32_t,io::CodedOutputStream * output)379 void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset,
380                                 uint32_t /*tag*/, uint32_t /*has_offset*/,
381                                 io::CodedOutputStream* output) {
382   output->WriteString(
383       reinterpret_cast<const InternalMetadata*>(ptr + offset)
384           ->unknown_fields<std::string>(&internal::GetEmptyString));
385 }
386 
DuplicateIfNonNullInternal(MessageLite * message)387 MessageLite* DuplicateIfNonNullInternal(MessageLite* message) {
388   if (message) {
389     MessageLite* ret = message->New();
390     ret->CheckTypeAndMergeFrom(*message);
391     return ret;
392   } else {
393     return nullptr;
394   }
395 }
396 
GenericSwap(MessageLite * m1,MessageLite * m2)397 void GenericSwap(MessageLite* m1, MessageLite* m2) {
398   std::unique_ptr<MessageLite> tmp(m1->New());
399   tmp->CheckTypeAndMergeFrom(*m1);
400   m1->Clear();
401   m1->CheckTypeAndMergeFrom(*m2);
402   m2->Clear();
403   m2->CheckTypeAndMergeFrom(*tmp);
404 }
405 
406 // Returns a message owned by this Arena.  This may require Own()ing or
407 // duplicating the message.
GetOwnedMessageInternal(Arena * message_arena,MessageLite * submessage,Arena * submessage_arena)408 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
409                                      MessageLite* submessage,
410                                      Arena* submessage_arena) {
411   ABSL_DCHECK(submessage->GetArena() == submessage_arena);
412   ABSL_DCHECK(message_arena != submessage_arena);
413   ABSL_DCHECK_EQ(submessage_arena, nullptr);
414   if (message_arena != nullptr && submessage_arena == nullptr) {
415     message_arena->Own(submessage);
416     return submessage;
417   } else {
418     MessageLite* ret = submessage->New(message_arena);
419     ret->CheckTypeAndMergeFrom(*submessage);
420     return ret;
421   }
422 }
423 
424 }  // namespace internal
425 }  // namespace protobuf
426 }  // namespace google
427 
428 #include "google/protobuf/port_undef.inc"
429