• 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 // Authors: wink@google.com (Wink Saville),
9 //          kenton@google.com (Kenton Varda)
10 //  Based on original Protocol Buffers design by
11 //  Sanjay Ghemawat, Jeff Dean, and others.
12 
13 #include "google/protobuf/message_lite.h"
14 
15 #include <climits>
16 #include <cstddef>
17 #include <cstdint>
18 #include <cstring>
19 #include <istream>
20 #include <ostream>
21 #include <string>
22 #include <utility>
23 
24 #include "absl/log/absl_check.h"
25 #include "absl/log/absl_log.h"
26 #include "absl/log/log.h"
27 #include "absl/strings/cord.h"
28 #include "absl/strings/cord_buffer.h"
29 #include "absl/strings/internal/resize_uninitialized.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/types/optional.h"
33 #include "absl/types/span.h"
34 #include "google/protobuf/arena.h"
35 #include "google/protobuf/generated_message_tctable_impl.h"
36 #include "google/protobuf/io/coded_stream.h"
37 #include "google/protobuf/io/zero_copy_stream.h"
38 #include "google/protobuf/io/zero_copy_stream_impl.h"
39 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
40 #include "google/protobuf/metadata_lite.h"
41 #include "google/protobuf/parse_context.h"
42 
43 
44 // Must be included last.
45 #include "google/protobuf/port_def.inc"
46 
47 namespace google {
48 namespace protobuf {
49 
DestroyInstance()50 void MessageLite::DestroyInstance() {
51 #if defined(PROTOBUF_CUSTOM_VTABLE)
52   _class_data_->destroy_message(*this);
53 #else   // PROTOBUF_CUSTOM_VTABLE
54   this->~MessageLite();
55 #endif  // PROTOBUF_CUSTOM_VTABLE
56 }
57 
DeleteInstance()58 void MessageLite::DeleteInstance() {
59   // Cache the size and pointer because we can't access them after the
60   // destruction.
61   const size_t size = GetClassData()->allocation_size();
62   void* const ptr = this;
63   DestroyInstance();
64   internal::SizedDelete(ptr, size);
65 }
66 
CheckTypeAndMergeFrom(const MessageLite & other)67 void MessageLite::CheckTypeAndMergeFrom(const MessageLite& other) {
68   auto* data = GetClassData();
69   auto* other_data = other.GetClassData();
70 
71   ABSL_CHECK_EQ(data, other_data)
72       << "Invalid call to CheckTypeAndMergeFrom between types " << GetTypeName()
73       << " and " << other.GetTypeName();
74   data->merge_to_from(*this, other);
75 }
76 
New(Arena * arena) const77 MessageLite* MessageLite::New(Arena* arena) const {
78   auto* data = GetClassData();
79   // The `instance->New()` expression requires using the actual instance
80   // instead of the prototype for the inner function call.
81   // Certain custom instances have special per-instance state that needs to be
82   // copied.
83   return data->message_creator.New(this, data->prototype, arena);
84 }
85 
IsInitialized() const86 bool MessageLite::IsInitialized() const {
87   auto* data = GetClassData();
88   return data->is_initialized != nullptr ? data->is_initialized(*this) : true;
89 }
90 
_InternalParse(const char * ptr,internal::ParseContext * ctx)91 const char* MessageLite::_InternalParse(const char* ptr,
92                                         internal::ParseContext* ctx) {
93   return internal::TcParser::ParseLoop(this, ptr, ctx, GetTcParseTable());
94 }
95 
GetTypeName() const96 internal::GetTypeNameReturnType MessageLite::GetTypeName() const {
97   return internal::GetTypeNameReturnType(TypeId::Get(*this).name());
98 }
99 
name() const100 absl::string_view TypeId::name() const {
101   if (!data_->is_lite) {
102     // For !LITE messages, we use the descriptor method function.
103     return data_->full().descriptor_methods->get_type_name(data_);
104   }
105 
106   // For LITE messages, the type name is a char[] just beyond ClassData.
107   return reinterpret_cast<const char*>(data_) + sizeof(internal::ClassData);
108 }
109 
OnDemandRegisterArenaDtor(Arena * arena)110 void MessageLite::OnDemandRegisterArenaDtor(Arena* arena) {
111   if (arena == nullptr) return;
112   auto* data = GetClassData();
113   ABSL_DCHECK(data != nullptr);
114 
115   if (data->on_demand_register_arena_dtor != nullptr) {
116     data->on_demand_register_arena_dtor(*this, *arena);
117   }
118 }
119 
InitializationErrorString() const120 std::string MessageLite::InitializationErrorString() const {
121   auto* data = GetClassData();
122   ABSL_DCHECK(data != nullptr);
123 
124   if (!data->is_lite) {
125     // For !LITE messages, we use the descriptor method function.
126     return data->full().descriptor_methods->initialization_error_string(*this);
127   }
128 
129   return "(cannot determine missing fields for lite message)";
130 }
131 
DebugString() const132 std::string MessageLite::DebugString() const {
133   auto* data = GetClassData();
134   ABSL_DCHECK(data != nullptr);
135   if (!data->is_lite) {
136     return data->full().descriptor_methods->debug_string(*this);
137   }
138 
139   return absl::StrCat("MessageLite at 0x", absl::Hex(this));
140 }
141 
142 #if !defined(PROTOBUF_CUSTOM_VTABLE)
GetCachedSize() const143 int MessageLite::GetCachedSize() const { return AccessCachedSize().Get(); }
144 #endif
145 
146 namespace {
147 
148 // When serializing, we first compute the byte size, then serialize the message.
149 // If serialization produces a different number of bytes than expected, we
150 // call this function, which crashes.  The problem could be due to a bug in the
151 // protobuf implementation but is more likely caused by concurrent modification
152 // of the message.  This function attempts to distinguish between the two and
153 // provide a useful error message.
ByteSizeConsistencyError(size_t byte_size_before_serialization,size_t byte_size_after_serialization,size_t bytes_produced_by_serialization,const MessageLite & message)154 void ByteSizeConsistencyError(size_t byte_size_before_serialization,
155                               size_t byte_size_after_serialization,
156                               size_t bytes_produced_by_serialization,
157                               const MessageLite& message) {
158   ABSL_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
159       << message.GetTypeName()
160       << " was modified concurrently during serialization.";
161   ABSL_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
162       << "Byte size calculation and serialization were inconsistent.  This "
163          "may indicate a bug in protocol buffers or it may be caused by "
164          "concurrent modification of "
165       << message.GetTypeName() << ".";
166   ABSL_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
167 }
168 
InitializationErrorMessage(absl::string_view action,const MessageLite & message)169 std::string InitializationErrorMessage(absl::string_view action,
170                                        const MessageLite& message) {
171   return absl::StrCat("Can't ", action, " message of type \"",
172                       message.GetTypeName(),
173                       "\" because it is missing required fields: ",
174                       message.InitializationErrorString());
175 }
176 
as_string_view(const void * data,int size)177 inline absl::string_view as_string_view(const void* data, int size) {
178   return absl::string_view(static_cast<const char*>(data), size);
179 }
180 
181 // Returns true if all required fields are present / have values.
CheckFieldPresence(const internal::ParseContext & ctx,const MessageLite & msg,MessageLite::ParseFlags parse_flags)182 inline bool CheckFieldPresence(const internal::ParseContext& ctx,
183                                const MessageLite& msg,
184                                MessageLite::ParseFlags parse_flags) {
185   (void)ctx;  // Parameter is used by Google-internal code.
186   if (PROTOBUF_PREDICT_FALSE((parse_flags & MessageLite::kMergePartial) != 0)) {
187     return true;
188   }
189   return msg.IsInitializedWithErrors();
190 }
191 
192 }  // namespace
193 
LogInitializationErrorMessage() const194 void MessageLite::LogInitializationErrorMessage() const {
195   ABSL_LOG(ERROR) << InitializationErrorMessage("parse", *this);
196 }
197 
198 namespace internal {
199 
FailDynamicCast(const MessageLite & from,const MessageLite & to)200 void FailDynamicCast(const MessageLite& from, const MessageLite& to) {
201   const auto to_name = to.GetTypeName();
202   if (internal::GetClassData(from)->is_dynamic) {
203     ABSL_LOG(FATAL)
204         << "Cannot downcast from a DynamicMessage to generated type "
205         << to_name;
206   }
207   const auto from_name = from.GetTypeName();
208   ABSL_LOG(FATAL) << "Cannot downcast " << from_name << " to " << to_name;
209 }
210 
211 template <bool aliasing>
MergeFromImpl(absl::string_view input,MessageLite * msg,const internal::TcParseTableBase * tc_table,MessageLite::ParseFlags parse_flags)212 bool MergeFromImpl(absl::string_view input, MessageLite* msg,
213                    const internal::TcParseTableBase* tc_table,
214                    MessageLite::ParseFlags parse_flags) {
215   const char* ptr;
216   internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
217                              aliasing, &ptr, input);
218   ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table);
219   // ctx has an explicit limit set (length of string_view).
220   if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtLimit())) {
221     return CheckFieldPresence(ctx, *msg, parse_flags);
222   }
223   return false;
224 }
225 
226 template <bool aliasing>
MergeFromImpl(io::ZeroCopyInputStream * input,MessageLite * msg,const internal::TcParseTableBase * tc_table,MessageLite::ParseFlags parse_flags)227 bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg,
228                    const internal::TcParseTableBase* tc_table,
229                    MessageLite::ParseFlags parse_flags) {
230   const char* ptr;
231   internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
232                              aliasing, &ptr, input);
233   ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table);
234   // ctx has no explicit limit (hence we end on end of stream)
235   if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtEndOfStream())) {
236     return CheckFieldPresence(ctx, *msg, parse_flags);
237   }
238   return false;
239 }
240 
241 template <bool aliasing>
MergeFromImpl(BoundedZCIS input,MessageLite * msg,const internal::TcParseTableBase * tc_table,MessageLite::ParseFlags parse_flags)242 bool MergeFromImpl(BoundedZCIS input, MessageLite* msg,
243                    const internal::TcParseTableBase* tc_table,
244                    MessageLite::ParseFlags parse_flags) {
245   const char* ptr;
246   internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
247                              aliasing, &ptr, input.zcis, input.limit);
248   ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table);
249   if (PROTOBUF_PREDICT_FALSE(!ptr)) return false;
250   ctx.BackUp(ptr);
251   if (PROTOBUF_PREDICT_TRUE(ctx.EndedAtLimit())) {
252     return CheckFieldPresence(ctx, *msg, parse_flags);
253   }
254   return false;
255 }
256 
257 template bool MergeFromImpl<false>(absl::string_view input, MessageLite* msg,
258                                    const internal::TcParseTableBase* tc_table,
259                                    MessageLite::ParseFlags parse_flags);
260 template bool MergeFromImpl<true>(absl::string_view input, MessageLite* msg,
261                                   const internal::TcParseTableBase* tc_table,
262                                   MessageLite::ParseFlags parse_flags);
263 template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input,
264                                    MessageLite* msg,
265                                    const internal::TcParseTableBase* tc_table,
266                                    MessageLite::ParseFlags parse_flags);
267 template bool MergeFromImpl<true>(io::ZeroCopyInputStream* input,
268                                   MessageLite* msg,
269                                   const internal::TcParseTableBase* tc_table,
270                                   MessageLite::ParseFlags parse_flags);
271 template bool MergeFromImpl<false>(BoundedZCIS input, MessageLite* msg,
272                                    const internal::TcParseTableBase* tc_table,
273                                    MessageLite::ParseFlags parse_flags);
274 template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg,
275                                   const internal::TcParseTableBase* tc_table,
276                                   MessageLite::ParseFlags parse_flags);
277 
278 }  // namespace internal
279 
280 class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream {
281  public:
ZeroCopyCodedInputStream(io::CodedInputStream * cis)282   explicit ZeroCopyCodedInputStream(io::CodedInputStream* cis) : cis_(cis) {}
Next(const void ** data,int * size)283   bool Next(const void** data, int* size) final {
284     if (!cis_->GetDirectBufferPointer(data, size)) return false;
285     cis_->Skip(*size);
286     return true;
287   }
BackUp(int count)288   void BackUp(int count) final { cis_->Advance(-count); }
Skip(int count)289   bool Skip(int count) final { return cis_->Skip(count); }
ByteCount() const290   int64_t ByteCount() const final { return 0; }
291 
aliasing_enabled()292   bool aliasing_enabled() { return cis_->aliasing_enabled_; }
293 
ReadCord(absl::Cord * cord,int count)294   bool ReadCord(absl::Cord* cord, int count) final {
295     // Fast path: tail call into ReadCord reading new value.
296     if (PROTOBUF_PREDICT_TRUE(cord->empty())) {
297       return cis_->ReadCord(cord, count);
298     }
299     absl::Cord tmp;
300     bool res = cis_->ReadCord(&tmp, count);
301     cord->Append(std::move(tmp));
302     return res;
303   }
304  private:
305   io::CodedInputStream* cis_;
306 };
307 
MergeFromImpl(io::CodedInputStream * input,MessageLite::ParseFlags parse_flags)308 bool MessageLite::MergeFromImpl(io::CodedInputStream* input,
309                                 MessageLite::ParseFlags parse_flags) {
310   ZeroCopyCodedInputStream zcis(input);
311   const char* ptr;
312   internal::ParseContext ctx(input->RecursionBudget(), zcis.aliasing_enabled(),
313                              &ptr, &zcis);
314   // MergePartialFromCodedStream allows terminating the wireformat by 0 or
315   // end-group tag. Leaving it up to the caller to verify correct ending by
316   // calling LastTagWas on input. We need to maintain this behavior.
317   ctx.TrackCorrectEnding();
318   ctx.data().pool = input->GetExtensionPool();
319   ctx.data().factory = input->GetExtensionFactory();
320   ptr = internal::TcParser::ParseLoop(this, ptr, &ctx, GetTcParseTable());
321   if (PROTOBUF_PREDICT_FALSE(!ptr)) return false;
322   ctx.BackUp(ptr);
323   if (!ctx.EndedAtEndOfStream()) {
324     ABSL_DCHECK_NE(ctx.LastTag(), 1u);  // We can't end on a pushed limit.
325     if (ctx.IsExceedingLimit(ptr)) return false;
326     input->SetLastTag(ctx.LastTag());
327   } else {
328     input->SetConsumed();
329   }
330   return CheckFieldPresence(ctx, *this, parse_flags);
331 }
332 
MergePartialFromCodedStream(io::CodedInputStream * input)333 bool MessageLite::MergePartialFromCodedStream(io::CodedInputStream* input) {
334   return MergeFromImpl(input, kMergePartial);
335 }
336 
MergeFromCodedStream(io::CodedInputStream * input)337 bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
338   return MergeFromImpl(input, kMerge);
339 }
340 
ParseFromCodedStream(io::CodedInputStream * input)341 bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
342   Clear();
343   return MergeFromImpl(input, kParse);
344 }
345 
ParsePartialFromCodedStream(io::CodedInputStream * input)346 bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
347   Clear();
348   return MergeFromImpl(input, kParsePartial);
349 }
350 
ParseFromZeroCopyStream(io::ZeroCopyInputStream * input)351 bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
352   return ParseFrom<kParse>(input);
353 }
354 
ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream * input)355 bool MessageLite::ParsePartialFromZeroCopyStream(
356     io::ZeroCopyInputStream* input) {
357   return ParseFrom<kParsePartial>(input);
358 }
359 
ParseFromFileDescriptor(int file_descriptor)360 bool MessageLite::ParseFromFileDescriptor(int file_descriptor) {
361   io::FileInputStream input(file_descriptor);
362   return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
363 }
364 
ParsePartialFromFileDescriptor(int file_descriptor)365 bool MessageLite::ParsePartialFromFileDescriptor(int file_descriptor) {
366   io::FileInputStream input(file_descriptor);
367   return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
368 }
369 
ParseFromIstream(std::istream * input)370 bool MessageLite::ParseFromIstream(std::istream* input) {
371   io::IstreamInputStream zero_copy_input(input);
372   return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
373 }
374 
ParsePartialFromIstream(std::istream * input)375 bool MessageLite::ParsePartialFromIstream(std::istream* input) {
376   io::IstreamInputStream zero_copy_input(input);
377   return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
378 }
379 
MergePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)380 bool MessageLite::MergePartialFromBoundedZeroCopyStream(
381     io::ZeroCopyInputStream* input, int size) {
382   return ParseFrom<kMergePartial>(internal::BoundedZCIS{input, size});
383 }
384 
MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)385 bool MessageLite::MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
386                                                  int size) {
387   return ParseFrom<kMerge>(internal::BoundedZCIS{input, size});
388 }
389 
ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)390 bool MessageLite::ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
391                                                  int size) {
392   return ParseFrom<kParse>(internal::BoundedZCIS{input, size});
393 }
394 
ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)395 bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
396     io::ZeroCopyInputStream* input, int size) {
397   return ParseFrom<kParsePartial>(internal::BoundedZCIS{input, size});
398 }
399 
ParseFromString(absl::string_view data)400 bool MessageLite::ParseFromString(absl::string_view data) {
401   return ParseFrom<kParse>(data);
402 }
403 
ParsePartialFromString(absl::string_view data)404 bool MessageLite::ParsePartialFromString(absl::string_view data) {
405   return ParseFrom<kParsePartial>(data);
406 }
407 
ParseFromArray(const void * data,int size)408 bool MessageLite::ParseFromArray(const void* data, int size) {
409   return ParseFrom<kParse>(as_string_view(data, size));
410 }
411 
ParsePartialFromArray(const void * data,int size)412 bool MessageLite::ParsePartialFromArray(const void* data, int size) {
413   return ParseFrom<kParsePartial>(as_string_view(data, size));
414 }
415 
MergeFromString(absl::string_view data)416 bool MessageLite::MergeFromString(absl::string_view data) {
417   return ParseFrom<kMerge>(data);
418 }
419 
420 
421 namespace internal {
422 
423 template <>
424 struct SourceWrapper<absl::Cord> {
SourceWrappergoogle::protobuf::internal::SourceWrapper425   explicit SourceWrapper(const absl::Cord* c) : cord(c) {}
426   template <bool alias>
MergeIntogoogle::protobuf::internal::SourceWrapper427   bool MergeInto(MessageLite* msg, const internal::TcParseTableBase* tc_table,
428                  MessageLite::ParseFlags parse_flags) const {
429     absl::optional<absl::string_view> flat = cord->TryFlat();
430     if (flat && flat->size() <= ParseContext::kMaxCordBytesToCopy) {
431       return MergeFromImpl<alias>(*flat, msg, tc_table, parse_flags);
432     } else {
433       io::CordInputStream input(cord);
434       return MergeFromImpl<alias>(&input, msg, tc_table, parse_flags);
435     }
436   }
437 
438   const absl::Cord* const cord;
439 };
440 
441 }  // namespace internal
442 
MergeFromCord(const absl::Cord & cord)443 bool MessageLite::MergeFromCord(const absl::Cord& cord) {
444   return ParseFrom<kMerge>(internal::SourceWrapper<absl::Cord>(&cord));
445 }
446 
MergePartialFromCord(const absl::Cord & cord)447 bool MessageLite::MergePartialFromCord(const absl::Cord& cord) {
448   return ParseFrom<kMergePartial>(internal::SourceWrapper<absl::Cord>(&cord));
449 }
450 
ParseFromCord(const absl::Cord & cord)451 bool MessageLite::ParseFromCord(const absl::Cord& cord) {
452   return ParseFrom<kParse>(internal::SourceWrapper<absl::Cord>(&cord));
453 }
454 
ParsePartialFromCord(const absl::Cord & cord)455 bool MessageLite::ParsePartialFromCord(const absl::Cord& cord) {
456   return ParseFrom<kParsePartial>(internal::SourceWrapper<absl::Cord>(&cord));
457 }
458 
459 // ===================================================================
460 
SerializeToArrayImpl(const MessageLite & msg,uint8_t * target,int size)461 inline uint8_t* SerializeToArrayImpl(const MessageLite& msg, uint8_t* target,
462                                      int size) {
463   constexpr bool debug = false;
464   if (debug) {
465     // Force serialization to a stream with a block size of 1, which forces
466     // all writes to the stream to cross buffers triggering all fallback paths
467     // in the unittests when serializing to string / array.
468     io::ArrayOutputStream stream(target, size, 1);
469     uint8_t* ptr;
470     io::EpsCopyOutputStream out(
471         &stream, io::CodedOutputStream::IsDefaultSerializationDeterministic(),
472         &ptr);
473     ptr = msg._InternalSerialize(ptr, &out);
474     out.Trim(ptr);
475     ABSL_DCHECK(!out.HadError() && stream.ByteCount() == size);
476     return target + size;
477   } else {
478     io::EpsCopyOutputStream out(
479         target, size,
480         io::CodedOutputStream::IsDefaultSerializationDeterministic());
481     uint8_t* res = msg._InternalSerialize(target, &out);
482     ABSL_DCHECK(target + size == res);
483     return res;
484   }
485 }
486 
SerializeWithCachedSizesToArray(uint8_t * target) const487 uint8_t* MessageLite::SerializeWithCachedSizesToArray(uint8_t* target) const {
488   // We only optimize this when using optimize_for = SPEED.  In other cases
489   // we just use the CodedOutputStream path.
490   return SerializeToArrayImpl(*this, target, GetCachedSize());
491 }
492 
SerializeToCodedStream(io::CodedOutputStream * output) const493 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
494   ABSL_DCHECK(IsInitialized())
495       << InitializationErrorMessage("serialize", *this);
496   return SerializePartialToCodedStream(output);
497 }
498 
SerializePartialToCodedStream(io::CodedOutputStream * output) const499 bool MessageLite::SerializePartialToCodedStream(
500     io::CodedOutputStream* output) const {
501   const size_t size = ByteSizeLong();  // Force size to be cached.
502   if (size > INT_MAX) {
503     ABSL_LOG(ERROR) << GetTypeName()
504                     << " exceeded maximum protobuf size of 2GB: " << size;
505     return false;
506   }
507 
508   int original_byte_count = output->ByteCount();
509   SerializeWithCachedSizes(output);
510   if (output->HadError()) {
511     return false;
512   }
513   int final_byte_count = output->ByteCount();
514 
515   if (final_byte_count - original_byte_count != static_cast<int64_t>(size)) {
516     ByteSizeConsistencyError(size, ByteSizeLong(),
517                              final_byte_count - original_byte_count, *this);
518   }
519 
520   return true;
521 }
522 
SerializeToZeroCopyStream(io::ZeroCopyOutputStream * output) const523 bool MessageLite::SerializeToZeroCopyStream(
524     io::ZeroCopyOutputStream* output) const {
525   ABSL_DCHECK(IsInitialized())
526       << InitializationErrorMessage("serialize", *this);
527   return SerializePartialToZeroCopyStream(output);
528 }
529 
SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream * output) const530 bool MessageLite::SerializePartialToZeroCopyStream(
531     io::ZeroCopyOutputStream* output) const {
532   const size_t size = ByteSizeLong();  // Force size to be cached.
533   if (size > INT_MAX) {
534     ABSL_LOG(ERROR) << GetTypeName()
535                     << " exceeded maximum protobuf size of 2GB: " << size;
536     return false;
537   }
538 
539   uint8_t* target;
540   io::EpsCopyOutputStream stream(
541       output, io::CodedOutputStream::IsDefaultSerializationDeterministic(),
542       &target);
543   target = _InternalSerialize(target, &stream);
544   stream.Trim(target);
545   if (stream.HadError()) return false;
546   return true;
547 }
548 
SerializeToFileDescriptor(int file_descriptor) const549 bool MessageLite::SerializeToFileDescriptor(int file_descriptor) const {
550   io::FileOutputStream output(file_descriptor);
551   return SerializeToZeroCopyStream(&output) && output.Flush();
552 }
553 
SerializePartialToFileDescriptor(int file_descriptor) const554 bool MessageLite::SerializePartialToFileDescriptor(int file_descriptor) const {
555   io::FileOutputStream output(file_descriptor);
556   return SerializePartialToZeroCopyStream(&output) && output.Flush();
557 }
558 
SerializeToOstream(std::ostream * output) const559 bool MessageLite::SerializeToOstream(std::ostream* output) const {
560   {
561     io::OstreamOutputStream zero_copy_output(output);
562     if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
563   }
564   return output->good();
565 }
566 
SerializePartialToOstream(std::ostream * output) const567 bool MessageLite::SerializePartialToOstream(std::ostream* output) const {
568   io::OstreamOutputStream zero_copy_output(output);
569   return SerializePartialToZeroCopyStream(&zero_copy_output);
570 }
571 
AppendToString(std::string * output) const572 bool MessageLite::AppendToString(std::string* output) const {
573   ABSL_DCHECK(IsInitialized())
574       << InitializationErrorMessage("serialize", *this);
575   return AppendPartialToString(output);
576 }
577 
AppendPartialToString(std::string * output) const578 bool MessageLite::AppendPartialToString(std::string* output) const {
579   size_t old_size = output->size();
580   size_t byte_size = ByteSizeLong();
581   if (byte_size > INT_MAX) {
582     ABSL_LOG(ERROR) << GetTypeName()
583                     << " exceeded maximum protobuf size of 2GB: " << byte_size;
584     return false;
585   }
586 
587   absl::strings_internal::STLStringResizeUninitializedAmortized(
588       output, old_size + byte_size);
589   uint8_t* start =
590       reinterpret_cast<uint8_t*>(io::mutable_string_data(output) + old_size);
591   SerializeToArrayImpl(*this, start, byte_size);
592   return true;
593 }
594 
SerializeToString(std::string * output) const595 bool MessageLite::SerializeToString(std::string* output) const {
596   output->clear();
597   return AppendToString(output);
598 }
599 
SerializePartialToString(std::string * output) const600 bool MessageLite::SerializePartialToString(std::string* output) const {
601   output->clear();
602   return AppendPartialToString(output);
603 }
604 
SerializeToArray(void * data,int size) const605 bool MessageLite::SerializeToArray(void* data, int size) const {
606   ABSL_DCHECK(IsInitialized())
607       << InitializationErrorMessage("serialize", *this);
608   return SerializePartialToArray(data, size);
609 }
610 
SerializePartialToArray(void * data,int size) const611 bool MessageLite::SerializePartialToArray(void* data, int size) const {
612   const size_t byte_size = ByteSizeLong();
613   if (byte_size > INT_MAX) {
614     ABSL_LOG(ERROR) << GetTypeName()
615                     << " exceeded maximum protobuf size of 2GB: " << byte_size;
616     return false;
617   }
618   if (size < static_cast<int64_t>(byte_size)) return false;
619   uint8_t* start = reinterpret_cast<uint8_t*>(data);
620   SerializeToArrayImpl(*this, start, byte_size);
621   return true;
622 }
623 
SerializeAsString() const624 std::string MessageLite::SerializeAsString() const {
625   // If the compiler implements the (Named) Return Value Optimization,
626   // the local variable 'output' will not actually reside on the stack
627   // of this function, but will be overlaid with the object that the
628   // caller supplied for the return value to be constructed in.
629   std::string output;
630   if (!AppendToString(&output)) output.clear();
631   return output;
632 }
633 
SerializePartialAsString() const634 std::string MessageLite::SerializePartialAsString() const {
635   std::string output;
636   if (!AppendPartialToString(&output)) output.clear();
637   return output;
638 }
639 
AppendToCord(absl::Cord * output) const640 bool MessageLite::AppendToCord(absl::Cord* output) const {
641   ABSL_DCHECK(IsInitialized())
642       << InitializationErrorMessage("serialize", *this);
643   return AppendPartialToCord(output);
644 }
645 
AppendPartialToCord(absl::Cord * output) const646 bool MessageLite::AppendPartialToCord(absl::Cord* output) const {
647   // For efficiency, we'd like to pass a size hint to CordOutputStream with
648   // the exact total size expected.
649   const size_t size = ByteSizeLong();
650   const size_t total_size = size + output->size();
651   if (size > INT_MAX) {
652     ABSL_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size;
653     return false;
654   }
655 
656 
657   // Allocate a CordBuffer (which may utilize private capacity in 'output').
658   absl::CordBuffer buffer = output->GetAppendBuffer(size);
659   absl::Span<char> available = buffer.available();
660   auto target = reinterpret_cast<uint8_t*>(available.data());
661   if (available.size() >= size) {
662     // Use EpsCopyOutputStream with full available capacity, as serialization
663     // may in the future use the extra slop bytes if available.
664     io::EpsCopyOutputStream out(
665         target, static_cast<int>(available.size()),
666         io::CodedOutputStream::IsDefaultSerializationDeterministic());
667     auto res = _InternalSerialize(target, &out);
668     ABSL_DCHECK_EQ(static_cast<const void*>(res),
669                    static_cast<const void*>(target + size));
670     buffer.IncreaseLengthBy(size);
671     output->Append(std::move(buffer));
672     ABSL_DCHECK_EQ(output->size(), total_size);
673     return true;
674   }
675 
676   // Donate the buffer to the CordOutputStream with length := capacity.
677   // This follows the eager `EpsCopyOutputStream` initialization logic.
678   buffer.SetLength(buffer.capacity());
679   io::CordOutputStream output_stream(std::move(*output), std::move(buffer),
680                                      total_size);
681   io::EpsCopyOutputStream out(
682       target, static_cast<int>(available.size()), &output_stream,
683       io::CodedOutputStream::IsDefaultSerializationDeterministic(), &target);
684   target = _InternalSerialize(target, &out);
685   out.Trim(target);
686   if (out.HadError()) return false;
687   *output = output_stream.Consume();
688   ABSL_DCHECK_EQ(output->size(), total_size);
689   return true;
690 }
691 
SerializeToCord(absl::Cord * output) const692 bool MessageLite::SerializeToCord(absl::Cord* output) const {
693   output->Clear();
694   return AppendToCord(output);
695 }
696 
SerializePartialToCord(absl::Cord * output) const697 bool MessageLite::SerializePartialToCord(absl::Cord* output) const {
698   output->Clear();
699   return AppendPartialToCord(output);
700 }
701 
SerializeAsCord() const702 absl::Cord MessageLite::SerializeAsCord() const {
703   absl::Cord output;
704   if (!AppendToCord(&output)) output.Clear();
705   return output;
706 }
707 
SerializePartialAsCord() const708 absl::Cord MessageLite::SerializePartialAsCord() const {
709   absl::Cord output;
710   if (!AppendPartialToCord(&output)) output.Clear();
711   return output;
712 }
713 
714 namespace internal {
715 
NewFromPrototypeHelper(const MessageLite * prototype,Arena * arena)716 MessageLite* NewFromPrototypeHelper(const MessageLite* prototype,
717                                     Arena* arena) {
718   return prototype->New(arena);
719 }
720 template <>
Merge(const MessageLite & from,MessageLite * to)721 void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
722                                             MessageLite* to) {
723   to->CheckTypeAndMergeFrom(from);
724 }
725 
726 // Non-inline variants of std::string specializations for
727 // various InternalMetadata routines.
728 template <>
DoClear()729 void InternalMetadata::DoClear<std::string>() {
730   mutable_unknown_fields<std::string>()->clear();
731 }
732 
733 template <>
DoMergeFrom(const std::string & other)734 void InternalMetadata::DoMergeFrom<std::string>(const std::string& other) {
735   mutable_unknown_fields<std::string>()->append(other);
736 }
737 
738 template <>
DoSwap(std::string * other)739 void InternalMetadata::DoSwap<std::string>(std::string* other) {
740   mutable_unknown_fields<std::string>()->swap(*other);
741 }
742 
743 }  // namespace internal
744 
ShortFormat(const MessageLite & message_lite)745 std::string ShortFormat(const MessageLite& message_lite) {
746   return message_lite.DebugString();
747 }
748 
Utf8Format(const MessageLite & message_lite)749 std::string Utf8Format(const MessageLite& message_lite) {
750   return message_lite.DebugString();
751 }
752 
753 
754 // ===================================================================
755 // Shutdown support.
756 
757 namespace internal {
758 
759 struct ShutdownData {
~ShutdownDatagoogle::protobuf::internal::ShutdownData760   ~ShutdownData() {
761     std::reverse(functions.begin(), functions.end());
762     for (auto pair : functions) pair.first(pair.second);
763   }
764 
getgoogle::protobuf::internal::ShutdownData765   static ShutdownData* get() {
766     static auto* data = new ShutdownData;
767     return data;
768   }
769 
770   std::vector<std::pair<void (*)(const void*), const void*>> functions;
771   absl::Mutex mutex;
772 };
773 
RunZeroArgFunc(const void * arg)774 static void RunZeroArgFunc(const void* arg) {
775   void (*func)() = reinterpret_cast<void (*)()>(const_cast<void*>(arg));
776   func();
777 }
778 
OnShutdown(void (* func)())779 void OnShutdown(void (*func)()) {
780   OnShutdownRun(RunZeroArgFunc, reinterpret_cast<void*>(func));
781 }
782 
OnShutdownRun(void (* f)(const void *),const void * arg)783 void OnShutdownRun(void (*f)(const void*), const void* arg) {
784   auto shutdown_data = ShutdownData::get();
785   absl::MutexLock lock(&shutdown_data->mutex);
786   shutdown_data->functions.push_back(std::make_pair(f, arg));
787 }
788 
789 }  // namespace internal
790 
ShutdownProtobufLibrary()791 void ShutdownProtobufLibrary() {
792   // This function should be called only once, but accepts multiple calls.
793   static bool is_shutdown = false;
794   if (!is_shutdown) {
795     delete internal::ShutdownData::get();
796     is_shutdown = true;
797   }
798 }
799 
800 
801 }  // namespace protobuf
802 }  // namespace google
803 
804 #include "google/protobuf/port_undef.inc"
805