diff options
author | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-12-18 02:11:36 +0000 |
---|---|---|
committer | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-12-18 02:11:36 +0000 |
commit | fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 (patch) | |
tree | 9f2d9fe0267d96a54e541377ffeada3d0bff0d1d /src/google/protobuf/message_lite.cc | |
parent | d5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff) | |
download | protobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.tar.gz protobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.tar.bz2 protobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.zip |
Massive roll-up of changes. See CHANGES.txt.
Diffstat (limited to 'src/google/protobuf/message_lite.cc')
-rw-r--r-- | src/google/protobuf/message_lite.cc | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index a53740ad..7c8f37dc 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -33,9 +33,8 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. - #include <google/protobuf/message_lite.h> - +#include <string> #include <google/protobuf/stubs/common.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> @@ -52,6 +51,24 @@ string MessageLite::InitializationErrorString() const { namespace { +// When serializing, we first compute the byte size, then serialize the message. +// If serialization produces a different number of bytes than expected, we +// call this function, which crashes. The problem could be due to a bug in the +// protobuf implementation but is more likely caused by concurrent modification +// of the message. This function attempts to distinguish between the two and +// provide a useful error message. +void ByteSizeConsistencyError(int byte_size_before_serialization, + int byte_size_after_serialization, + int bytes_produced_by_serialization) { + GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) + << "Protocol message was modified concurrently during serialization."; + GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization) + << "Byte size calculation and serialization were inconsistent. This " + "may indicate a bug in protocol buffers or it may be caused by " + "concurrent modification of the message."; + GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; +} + string InitializationErrorMessage(const char* action, const MessageLite& message) { // Note: We want to avoid depending on strutil in the lite library, otherwise @@ -215,9 +232,29 @@ bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { bool MessageLite::SerializePartialToCodedStream( io::CodedOutputStream* output) const { - ByteSize(); // Force size to be cached. - SerializeWithCachedSizes(output); - return !output->HadError(); + const int size = ByteSize(); // Force size to be cached. + uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); + if (buffer != NULL) { + uint8* end = SerializeWithCachedSizesToArray(buffer); + if (end - buffer != size) { + ByteSizeConsistencyError(size, ByteSize(), end - buffer); + } + return true; + } else { + int original_byte_count = output->ByteCount(); + SerializeWithCachedSizes(output); + if (output->HadError()) { + return false; + } + int final_byte_count = output->ByteCount(); + + if (final_byte_count - original_byte_count != size) { + ByteSizeConsistencyError(size, ByteSize(), + final_byte_count - original_byte_count); + } + + return true; + } } bool MessageLite::SerializeToZeroCopyStream( @@ -243,7 +280,9 @@ bool MessageLite::AppendPartialToString(string* output) const { STLStringResizeUninitialized(output, old_size + byte_size); uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size); uint8* end = SerializeWithCachedSizesToArray(start); - GOOGLE_CHECK_EQ(end - start, byte_size); + if (end - start != byte_size) { + ByteSizeConsistencyError(byte_size, ByteSize(), end - start); + } return true; } @@ -265,9 +304,11 @@ bool MessageLite::SerializeToArray(void* data, int size) const { bool MessageLite::SerializePartialToArray(void* data, int size) const { int byte_size = ByteSize(); if (size < byte_size) return false; - uint8* end = - SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(data)); - GOOGLE_CHECK_EQ(end, reinterpret_cast<uint8*>(data) + byte_size); + uint8* start = reinterpret_cast<uint8*>(data); + uint8* end = SerializeWithCachedSizesToArray(start); + if (end - start != byte_size) { + ByteSizeConsistencyError(byte_size, ByteSize(), end - start); + } return true; } |