1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Authors: wink@google.com (Wink Saville),
32 //          kenton@google.com (Kenton Varda)
33 //  Based on original Protocol Buffers design by
34 //  Sanjay Ghemawat, Jeff Dean, and others.
35 
36 #include <climits>
37 
38 #include <google/protobuf/arena.h>
39 #include <google/protobuf/generated_message_util.h>
40 #include <google/protobuf/message_lite.h>
41 #include <google/protobuf/repeated_field.h>
42 #include <string>
43 #include <google/protobuf/stubs/logging.h>
44 #include <google/protobuf/stubs/common.h>
45 #include <google/protobuf/io/coded_stream.h>
46 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
47 #include <google/protobuf/stubs/stl_util.h>
48 
49 namespace google {
50 namespace protobuf {
51 
InitializationErrorString() const52 string MessageLite::InitializationErrorString() const {
53   return "(cannot determine missing fields for lite message)";
54 }
55 
56 namespace {
57 
58 // When serializing, we first compute the byte size, then serialize the message.
59 // If serialization produces a different number of bytes than expected, we
60 // call this function, which crashes.  The problem could be due to a bug in the
61 // protobuf implementation but is more likely caused by concurrent modification
62 // of the message.  This function attempts to distinguish between the two and
63 // 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)64 void ByteSizeConsistencyError(size_t byte_size_before_serialization,
65                               size_t byte_size_after_serialization,
66                               size_t bytes_produced_by_serialization,
67                               const MessageLite& message) {
68   GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
69       << message.GetTypeName()
70       << " was modified concurrently during serialization.";
71   GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
72       << "Byte size calculation and serialization were inconsistent.  This "
73          "may indicate a bug in protocol buffers or it may be caused by "
74          "concurrent modification of " << message.GetTypeName() << ".";
75   GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
76 }
77 
InitializationErrorMessage(const char * action,const MessageLite & message)78 string InitializationErrorMessage(const char* action,
79                                   const MessageLite& message) {
80   // Note:  We want to avoid depending on strutil in the lite library, otherwise
81   //   we'd use:
82   //
83   // return strings::Substitute(
84   //   "Can't $0 message of type \"$1\" because it is missing required "
85   //   "fields: $2",
86   //   action, message.GetTypeName(),
87   //   message.InitializationErrorString());
88 
89   string result;
90   result += "Can't ";
91   result += action;
92   result += " message of type \"";
93   result += message.GetTypeName();
94   result += "\" because it is missing required fields: ";
95   result += message.InitializationErrorString();
96   return result;
97 }
98 
99 // Several of the Parse methods below just do one thing and then call another
100 // method.  In a naive implementation, we might have ParseFromString() call
101 // ParseFromArray() which would call ParseFromZeroCopyStream() which would call
102 // ParseFromCodedStream() which would call MergeFromCodedStream() which would
103 // call MergePartialFromCodedStream().  However, when parsing very small
104 // messages, every function call introduces significant overhead.  To avoid
105 // this without reproducing code, we use these forced-inline helpers.
106 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
107     io::CodedInputStream* input, MessageLite* message);
108 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
109     io::CodedInputStream* input, MessageLite* message);
110 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
111     io::CodedInputStream* input, MessageLite* message);
112 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
113     const void* data, int size, MessageLite* message);
114 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
115     const void* data, int size, MessageLite* message);
116 
InlineMergeFromCodedStream(io::CodedInputStream * input,MessageLite * message)117 inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
118                                        MessageLite* message) {
119   if (!message->MergePartialFromCodedStream(input)) return false;
120   if (!message->IsInitialized()) {
121     GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
122     return false;
123   }
124   return true;
125 }
126 
InlineParseFromCodedStream(io::CodedInputStream * input,MessageLite * message)127 inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
128                                        MessageLite* message) {
129   message->Clear();
130   return InlineMergeFromCodedStream(input, message);
131 }
132 
InlineParsePartialFromCodedStream(io::CodedInputStream * input,MessageLite * message)133 inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
134                                               MessageLite* message) {
135   message->Clear();
136   return message->MergePartialFromCodedStream(input);
137 }
138 
InlineParseFromArray(const void * data,int size,MessageLite * message)139 inline bool InlineParseFromArray(
140     const void* data, int size, MessageLite* message) {
141   io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
142   return InlineParseFromCodedStream(&input, message) &&
143          input.ConsumedEntireMessage();
144 }
145 
InlineParsePartialFromArray(const void * data,int size,MessageLite * message)146 inline bool InlineParsePartialFromArray(
147     const void* data, int size, MessageLite* message) {
148   io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
149   return InlineParsePartialFromCodedStream(&input, message) &&
150          input.ConsumedEntireMessage();
151 }
152 
153 }  // namespace
154 
155 
New(::google::protobuf::Arena * arena) const156 MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
157   MessageLite* message = New();
158   if (arena != NULL) {
159     arena->Own(message);
160   }
161   return message;
162 }
163 
MergeFromCodedStream(io::CodedInputStream * input)164 bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
165   return InlineMergeFromCodedStream(input, this);
166 }
167 
ParseFromCodedStream(io::CodedInputStream * input)168 bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
169   return InlineParseFromCodedStream(input, this);
170 }
171 
ParsePartialFromCodedStream(io::CodedInputStream * input)172 bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
173   return InlineParsePartialFromCodedStream(input, this);
174 }
175 
ParseFromZeroCopyStream(io::ZeroCopyInputStream * input)176 bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
177   io::CodedInputStream decoder(input);
178   return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
179 }
180 
ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream * input)181 bool MessageLite::ParsePartialFromZeroCopyStream(
182     io::ZeroCopyInputStream* input) {
183   io::CodedInputStream decoder(input);
184   return ParsePartialFromCodedStream(&decoder) &&
185          decoder.ConsumedEntireMessage();
186 }
187 
ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)188 bool MessageLite::ParseFromBoundedZeroCopyStream(
189     io::ZeroCopyInputStream* input, int size) {
190   io::CodedInputStream decoder(input);
191   decoder.PushLimit(size);
192   return ParseFromCodedStream(&decoder) &&
193          decoder.ConsumedEntireMessage() &&
194          decoder.BytesUntilLimit() == 0;
195 }
196 
ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream * input,int size)197 bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
198     io::ZeroCopyInputStream* input, int size) {
199   io::CodedInputStream decoder(input);
200   decoder.PushLimit(size);
201   return ParsePartialFromCodedStream(&decoder) &&
202          decoder.ConsumedEntireMessage() &&
203          decoder.BytesUntilLimit() == 0;
204 }
205 
ParseFromString(const string & data)206 bool MessageLite::ParseFromString(const string& data) {
207   return InlineParseFromArray(data.data(), data.size(), this);
208 }
209 
ParsePartialFromString(const string & data)210 bool MessageLite::ParsePartialFromString(const string& data) {
211   return InlineParsePartialFromArray(data.data(), data.size(), this);
212 }
213 
ParseFromArray(const void * data,int size)214 bool MessageLite::ParseFromArray(const void* data, int size) {
215   return InlineParseFromArray(data, size, this);
216 }
217 
ParsePartialFromArray(const void * data,int size)218 bool MessageLite::ParsePartialFromArray(const void* data, int size) {
219   return InlineParsePartialFromArray(data, size, this);
220 }
221 
222 
223 // ===================================================================
224 
SerializeWithCachedSizesToArray(uint8 * target) const225 uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
226   return InternalSerializeWithCachedSizesToArray(
227       io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
228 }
229 
SerializeToCodedStream(io::CodedOutputStream * output) const230 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
231   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
232   return SerializePartialToCodedStream(output);
233 }
234 
SerializePartialToCodedStream(io::CodedOutputStream * output) const235 bool MessageLite::SerializePartialToCodedStream(
236     io::CodedOutputStream* output) const {
237   const size_t size = ByteSizeLong();  // Force size to be cached.
238   if (size > INT_MAX) {
239     GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size;
240     return false;
241   }
242 
243   uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
244   if (buffer != NULL) {
245     uint8* end = InternalSerializeWithCachedSizesToArray(
246         output->IsSerializationDeterministic(), buffer);
247     if (end - buffer != size) {
248       ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this);
249     }
250     return true;
251   } else {
252     int original_byte_count = output->ByteCount();
253     SerializeWithCachedSizes(output);
254     if (output->HadError()) {
255       return false;
256     }
257     int final_byte_count = output->ByteCount();
258 
259     if (final_byte_count - original_byte_count != size) {
260       ByteSizeConsistencyError(size, ByteSizeLong(),
261                                final_byte_count - original_byte_count, *this);
262     }
263 
264     return true;
265   }
266 }
267 
SerializeToZeroCopyStream(io::ZeroCopyOutputStream * output) const268 bool MessageLite::SerializeToZeroCopyStream(
269     io::ZeroCopyOutputStream* output) const {
270   io::CodedOutputStream encoder(output);
271   return SerializeToCodedStream(&encoder);
272 }
273 
SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream * output) const274 bool MessageLite::SerializePartialToZeroCopyStream(
275     io::ZeroCopyOutputStream* output) const {
276   io::CodedOutputStream encoder(output);
277   return SerializePartialToCodedStream(&encoder);
278 }
279 
AppendToString(string * output) const280 bool MessageLite::AppendToString(string* output) const {
281   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
282   return AppendPartialToString(output);
283 }
284 
AppendPartialToString(string * output) const285 bool MessageLite::AppendPartialToString(string* output) const {
286   size_t old_size = output->size();
287   size_t byte_size = ByteSizeLong();
288   if (byte_size > INT_MAX) {
289     GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << byte_size;
290     return false;
291   }
292 
293   STLStringResizeUninitialized(output, old_size + byte_size);
294   uint8* start =
295       reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
296   uint8* end = SerializeWithCachedSizesToArray(start);
297   if (end - start != byte_size) {
298     ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this);
299   }
300   return true;
301 }
302 
SerializeToString(string * output) const303 bool MessageLite::SerializeToString(string* output) const {
304   output->clear();
305   return AppendToString(output);
306 }
307 
SerializePartialToString(string * output) const308 bool MessageLite::SerializePartialToString(string* output) const {
309   output->clear();
310   return AppendPartialToString(output);
311 }
312 
SerializeToArray(void * data,int size) const313 bool MessageLite::SerializeToArray(void* data, int size) const {
314   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
315   return SerializePartialToArray(data, size);
316 }
317 
SerializePartialToArray(void * data,int size) const318 bool MessageLite::SerializePartialToArray(void* data, int size) const {
319   int byte_size = ByteSizeLong();
320   if (size < byte_size) return false;
321   uint8* start = reinterpret_cast<uint8*>(data);
322   uint8* end = SerializeWithCachedSizesToArray(start);
323   if (end - start != byte_size) {
324     ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this);
325   }
326   return true;
327 }
328 
SerializeAsString() const329 string MessageLite::SerializeAsString() const {
330   // If the compiler implements the (Named) Return Value Optimization,
331   // the local variable 'output' will not actually reside on the stack
332   // of this function, but will be overlaid with the object that the
333   // caller supplied for the return value to be constructed in.
334   string output;
335   if (!AppendToString(&output))
336     output.clear();
337   return output;
338 }
339 
SerializePartialAsString() const340 string MessageLite::SerializePartialAsString() const {
341   string output;
342   if (!AppendPartialToString(&output))
343     output.clear();
344   return output;
345 }
346 
SerializeWithCachedSizes(io::CodedOutputStream * output) const347 void MessageLite::SerializeWithCachedSizes(io::CodedOutputStream* output) const
348     {
349   GOOGLE_DCHECK(InternalGetTable());
350   internal::TableSerialize(*this, static_cast<const internal::SerializationTable*>(InternalGetTable()), output);
351 }
352 
353 // The table driven code optimizes the case that the CodedOutputStream buffer
354 // is large enough to serialize into it directly.
355 // If the proto is optimized for speed, this method will be overridden by
356 // generated code for maximum speed. If the proto is optimized for size or
357 // is lite, then we need to specialize this to avoid infinite recursion.
InternalSerializeWithCachedSizesToArray(bool deterministic,uint8 * target) const358 uint8* MessageLite::InternalSerializeWithCachedSizesToArray(bool deterministic,
359                                                uint8* target) const {
360   const internal::SerializationTable* table =
361       static_cast<const internal::SerializationTable*>(InternalGetTable());
362   if (table == NULL) {
363     // We only optimize this when using optimize_for = SPEED.  In other cases
364   // we just use the CodedOutputStream path.
365   int size = GetCachedSize();
366   io::ArrayOutputStream out(target, size);
367   io::CodedOutputStream coded_out(&out);
368   coded_out.SetSerializationDeterministic(deterministic);
369   SerializeWithCachedSizes(&coded_out);
370   GOOGLE_CHECK(!coded_out.HadError());
371   return target + size;
372   } else {
373     return internal::TableSerializeToArray(*this, table, deterministic, target);
374   }
375 }
376 
377 namespace internal {
378 template<>
NewFromPrototype(const MessageLite * prototype,google::protobuf::Arena * arena)379 MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
380     const MessageLite* prototype, google::protobuf::Arena* arena) {
381   return prototype->New(arena);
382 }
383 template <>
Merge(const MessageLite & from,MessageLite * to)384 void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
385                                             MessageLite* to) {
386   to->CheckTypeAndMergeFrom(from);
387 }
388 template<>
Merge(const string & from,string * to)389 void GenericTypeHandler<string>::Merge(const string& from,
390                                               string* to) {
391   *to = from;
392 }
393 
394 bool proto3_preserve_unknown_ = false;
SetProto3PreserveUnknownsDefault(bool preserve)395 void SetProto3PreserveUnknownsDefault(bool preserve) {
396   proto3_preserve_unknown_ = preserve;
397 }
398 
399 
400 }  // namespace internal
401 
402 }  // namespace protobuf
403 }  // namespace google
404