OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 15 matching lines...) Expand all Loading... |
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 // Authors: wink@google.com (Wink Saville), | 31 // Authors: wink@google.com (Wink Saville), |
32 // kenton@google.com (Kenton Varda) | 32 // kenton@google.com (Kenton Varda) |
33 // Based on original Protocol Buffers design by | 33 // Based on original Protocol Buffers design by |
34 // Sanjay Ghemawat, Jeff Dean, and others. | 34 // Sanjay Ghemawat, Jeff Dean, and others. |
35 | 35 |
36 #include <climits> | 36 #include <google/protobuf/message_lite.h> |
37 | |
38 #include <google/protobuf/arena.h> | 37 #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> | 38 #include <google/protobuf/repeated_field.h> |
42 #include <string> | 39 #include <string> |
43 #include <google/protobuf/stubs/logging.h> | 40 #include <google/protobuf/stubs/logging.h> |
44 #include <google/protobuf/stubs/common.h> | 41 #include <google/protobuf/stubs/common.h> |
45 #include <google/protobuf/io/coded_stream.h> | 42 #include <google/protobuf/io/coded_stream.h> |
46 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> | 43 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
47 #include <google/protobuf/stubs/stl_util.h> | 44 #include <google/protobuf/stubs/stl_util.h> |
48 | 45 |
49 namespace google { | 46 namespace google { |
50 namespace protobuf { | 47 namespace protobuf { |
51 | 48 |
| 49 MessageLite::~MessageLite() {} |
| 50 |
52 string MessageLite::InitializationErrorString() const { | 51 string MessageLite::InitializationErrorString() const { |
53 return "(cannot determine missing fields for lite message)"; | 52 return "(cannot determine missing fields for lite message)"; |
54 } | 53 } |
55 | 54 |
56 namespace { | 55 namespace { |
57 | 56 |
58 // When serializing, we first compute the byte size, then serialize the message. | 57 // When serializing, we first compute the byte size, then serialize the message. |
59 // If serialization produces a different number of bytes than expected, we | 58 // 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 | 59 // 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 | 60 // protobuf implementation but is more likely caused by concurrent modification |
62 // of the message. This function attempts to distinguish between the two and | 61 // of the message. This function attempts to distinguish between the two and |
63 // provide a useful error message. | 62 // provide a useful error message. |
64 void ByteSizeConsistencyError(size_t byte_size_before_serialization, | 63 void ByteSizeConsistencyError(int byte_size_before_serialization, |
65 size_t byte_size_after_serialization, | 64 int byte_size_after_serialization, |
66 size_t bytes_produced_by_serialization, | 65 int bytes_produced_by_serialization, |
67 const MessageLite& message) { | 66 const MessageLite& message) { |
68 GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) | 67 GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) |
69 << message.GetTypeName() | 68 << message.GetTypeName() |
70 << " was modified concurrently during serialization."; | 69 << " was modified concurrently during serialization."; |
71 GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serializatio
n) | 70 GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serializatio
n) |
72 << "Byte size calculation and serialization were inconsistent. This " | 71 << "Byte size calculation and serialization were inconsistent. This " |
73 "may indicate a bug in protocol buffers or it may be caused by " | 72 "may indicate a bug in protocol buffers or it may be caused by " |
74 "concurrent modification of " << message.GetTypeName() << "."; | 73 "concurrent modification of " << message.GetTypeName() << "."; |
75 GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; | 74 GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; |
76 } | 75 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 return InlineParseFromArray(data, size, this); | 214 return InlineParseFromArray(data, size, this); |
216 } | 215 } |
217 | 216 |
218 bool MessageLite::ParsePartialFromArray(const void* data, int size) { | 217 bool MessageLite::ParsePartialFromArray(const void* data, int size) { |
219 return InlineParsePartialFromArray(data, size, this); | 218 return InlineParsePartialFromArray(data, size, this); |
220 } | 219 } |
221 | 220 |
222 | 221 |
223 // =================================================================== | 222 // =================================================================== |
224 | 223 |
225 uint8* MessageLite::InternalSerializeWithCachedSizesToArray( | 224 uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const { |
226 bool deterministic, uint8* target) const { | |
227 // We only optimize this when using optimize_for = SPEED. In other cases | 225 // We only optimize this when using optimize_for = SPEED. In other cases |
228 // we just use the CodedOutputStream path. | 226 // we just use the CodedOutputStream path. |
229 int size = GetCachedSize(); | 227 int size = GetCachedSize(); |
230 io::ArrayOutputStream out(target, size); | 228 io::ArrayOutputStream out(target, size); |
231 io::CodedOutputStream coded_out(&out); | 229 io::CodedOutputStream coded_out(&out); |
232 SerializeWithCachedSizes(&coded_out); | 230 SerializeWithCachedSizes(&coded_out); |
233 GOOGLE_CHECK(!coded_out.HadError()); | 231 GOOGLE_CHECK(!coded_out.HadError()); |
234 return target + size; | 232 return target + size; |
235 } | 233 } |
236 | 234 |
237 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { | 235 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { |
238 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); | 236 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); |
239 return SerializePartialToCodedStream(output); | 237 return SerializePartialToCodedStream(output); |
240 } | 238 } |
241 | 239 |
242 bool MessageLite::SerializePartialToCodedStream( | 240 bool MessageLite::SerializePartialToCodedStream( |
243 io::CodedOutputStream* output) const { | 241 io::CodedOutputStream* output) const { |
244 const size_t size = ByteSizeLong(); // Force size to be cached. | 242 const int size = ByteSize(); // Force size to be cached. |
245 if (size > INT_MAX) { | 243 if (size < 0) { |
246 GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size; | 244 // Messages >2G cannot be serialized due to overflow computing ByteSize. |
| 245 GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?)."; |
247 return false; | 246 return false; |
248 } | 247 } |
249 | 248 |
250 uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); | 249 uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); |
251 if (buffer != NULL) { | 250 if (buffer != NULL) { |
252 uint8* end = InternalSerializeWithCachedSizesToArray( | 251 uint8* end = SerializeWithCachedSizesToArray(buffer); |
253 output->IsSerializationDeterministic(), buffer); | |
254 if (end - buffer != size) { | 252 if (end - buffer != size) { |
255 ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this); | 253 ByteSizeConsistencyError(size, ByteSize(), end - buffer, *this); |
256 } | 254 } |
257 return true; | 255 return true; |
258 } else { | 256 } else { |
259 int original_byte_count = output->ByteCount(); | 257 int original_byte_count = output->ByteCount(); |
260 SerializeWithCachedSizes(output); | 258 SerializeWithCachedSizes(output); |
261 if (output->HadError()) { | 259 if (output->HadError()) { |
262 return false; | 260 return false; |
263 } | 261 } |
264 int final_byte_count = output->ByteCount(); | 262 int final_byte_count = output->ByteCount(); |
265 | 263 |
266 if (final_byte_count - original_byte_count != size) { | 264 if (final_byte_count - original_byte_count != size) { |
267 ByteSizeConsistencyError(size, ByteSizeLong(), | 265 ByteSizeConsistencyError(size, ByteSize(), |
268 final_byte_count - original_byte_count, *this); | 266 final_byte_count - original_byte_count, *this); |
269 } | 267 } |
270 | 268 |
271 return true; | 269 return true; |
272 } | 270 } |
273 } | 271 } |
274 | 272 |
275 bool MessageLite::SerializeToZeroCopyStream( | 273 bool MessageLite::SerializeToZeroCopyStream( |
276 io::ZeroCopyOutputStream* output) const { | 274 io::ZeroCopyOutputStream* output) const { |
277 io::CodedOutputStream encoder(output); | 275 io::CodedOutputStream encoder(output); |
278 return SerializeToCodedStream(&encoder); | 276 return SerializeToCodedStream(&encoder); |
279 } | 277 } |
280 | 278 |
281 bool MessageLite::SerializePartialToZeroCopyStream( | 279 bool MessageLite::SerializePartialToZeroCopyStream( |
282 io::ZeroCopyOutputStream* output) const { | 280 io::ZeroCopyOutputStream* output) const { |
283 io::CodedOutputStream encoder(output); | 281 io::CodedOutputStream encoder(output); |
284 return SerializePartialToCodedStream(&encoder); | 282 return SerializePartialToCodedStream(&encoder); |
285 } | 283 } |
286 | 284 |
287 bool MessageLite::AppendToString(string* output) const { | 285 bool MessageLite::AppendToString(string* output) const { |
288 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); | 286 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); |
289 return AppendPartialToString(output); | 287 return AppendPartialToString(output); |
290 } | 288 } |
291 | 289 |
292 bool MessageLite::AppendPartialToString(string* output) const { | 290 bool MessageLite::AppendPartialToString(string* output) const { |
293 size_t old_size = output->size(); | 291 int old_size = output->size(); |
294 size_t byte_size = ByteSizeLong(); | 292 int byte_size = ByteSize(); |
295 if (byte_size > INT_MAX) { | 293 if (byte_size < 0) { |
296 GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << byte_size; | 294 // Messages >2G cannot be serialized due to overflow computing ByteSize. |
| 295 GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?)."; |
297 return false; | 296 return false; |
298 } | 297 } |
299 | 298 |
300 STLStringResizeUninitialized(output, old_size + byte_size); | 299 STLStringResizeUninitialized(output, old_size + byte_size); |
301 uint8* start = | 300 uint8* start = |
302 reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size); | 301 reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size); |
303 uint8* end = SerializeWithCachedSizesToArray(start); | 302 uint8* end = SerializeWithCachedSizesToArray(start); |
304 if (end - start != byte_size) { | 303 if (end - start != byte_size) { |
305 ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this); | 304 ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this); |
306 } | 305 } |
307 return true; | 306 return true; |
308 } | 307 } |
309 | 308 |
310 bool MessageLite::SerializeToString(string* output) const { | 309 bool MessageLite::SerializeToString(string* output) const { |
311 output->clear(); | 310 output->clear(); |
312 return AppendToString(output); | 311 return AppendToString(output); |
313 } | 312 } |
314 | 313 |
315 bool MessageLite::SerializePartialToString(string* output) const { | 314 bool MessageLite::SerializePartialToString(string* output) const { |
316 output->clear(); | 315 output->clear(); |
317 return AppendPartialToString(output); | 316 return AppendPartialToString(output); |
318 } | 317 } |
319 | 318 |
320 bool MessageLite::SerializeToArray(void* data, int size) const { | 319 bool MessageLite::SerializeToArray(void* data, int size) const { |
321 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); | 320 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *thi
s); |
322 return SerializePartialToArray(data, size); | 321 return SerializePartialToArray(data, size); |
323 } | 322 } |
324 | 323 |
325 bool MessageLite::SerializePartialToArray(void* data, int size) const { | 324 bool MessageLite::SerializePartialToArray(void* data, int size) const { |
326 int byte_size = ByteSizeLong(); | 325 int byte_size = ByteSize(); |
327 if (size < byte_size) return false; | 326 if (size < byte_size) return false; |
328 uint8* start = reinterpret_cast<uint8*>(data); | 327 uint8* start = reinterpret_cast<uint8*>(data); |
329 uint8* end = SerializeWithCachedSizesToArray(start); | 328 uint8* end = SerializeWithCachedSizesToArray(start); |
330 if (end - start != byte_size) { | 329 if (end - start != byte_size) { |
331 ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this); | 330 ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this); |
332 } | 331 } |
333 return true; | 332 return true; |
334 } | 333 } |
335 | 334 |
336 string MessageLite::SerializeAsString() const { | 335 string MessageLite::SerializeAsString() const { |
337 // If the compiler implements the (Named) Return Value Optimization, | 336 // If the compiler implements the (Named) Return Value Optimization, |
338 // the local variable 'output' will not actually reside on the stack | 337 // the local variable 'output' will not actually reside on the stack |
339 // of this function, but will be overlaid with the object that the | 338 // of this function, but will be overlaid with the object that the |
340 // caller supplied for the return value to be constructed in. | 339 // caller supplied for the return value to be constructed in. |
341 string output; | 340 string output; |
(...skipping 22 matching lines...) Expand all Loading... |
364 } | 363 } |
365 template<> | 364 template<> |
366 void GenericTypeHandler<string>::Merge(const string& from, | 365 void GenericTypeHandler<string>::Merge(const string& from, |
367 string* to) { | 366 string* to) { |
368 *to = from; | 367 *to = from; |
369 } | 368 } |
370 } // namespace internal | 369 } // namespace internal |
371 | 370 |
372 } // namespace protobuf | 371 } // namespace protobuf |
373 } // namespace google | 372 } // namespace google |
OLD | NEW |