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