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