| 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 |