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 (at) google.com (Wink Saville), 32 // kenton (at) google.com (Kenton Varda) 33 // Based on original Protocol Buffers design by 34 // Sanjay Ghemawat, Jeff Dean, and others. 35 36 #include <google/protobuf/message_lite.h> 37 #include <google/protobuf/arena.h> 38 #include <google/protobuf/repeated_field.h> 39 #include <string> 40 #include <google/protobuf/stubs/logging.h> 41 #include <google/protobuf/stubs/common.h> 42 #include <google/protobuf/io/coded_stream.h> 43 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> 44 #include <google/protobuf/stubs/stl_util.h> 45 46 namespace google { 47 namespace protobuf { 48 49 MessageLite::~MessageLite() {} 50 51 string MessageLite::InitializationErrorString() const { 52 return "(cannot determine missing fields for lite message)"; 53 } 54 55 namespace { 56 57 // 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 // 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 // of the message. This function attempts to distinguish between the two and 62 // provide a useful error message. 63 void ByteSizeConsistencyError(int byte_size_before_serialization, 64 int byte_size_after_serialization, 65 int bytes_produced_by_serialization, 66 const MessageLite& message) { 67 GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) 68 << message.GetTypeName() 69 << " was modified concurrently during serialization."; 70 GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization) 71 << "Byte size calculation and serialization were inconsistent. This " 72 "may indicate a bug in protocol buffers or it may be caused by " 73 "concurrent modification of " << message.GetTypeName() << "."; 74 GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; 75 } 76 77 string InitializationErrorMessage(const char* action, 78 const MessageLite& message) { 79 // Note: We want to avoid depending on strutil in the lite library, otherwise 80 // we'd use: 81 // 82 // return strings::Substitute( 83 // "Can't $0 message of type \"$1\" because it is missing required " 84 // "fields: $2", 85 // action, message.GetTypeName(), 86 // message.InitializationErrorString()); 87 88 string result; 89 result += "Can't "; 90 result += action; 91 result += " message of type \""; 92 result += message.GetTypeName(); 93 result += "\" because it is missing required fields: "; 94 result += message.InitializationErrorString(); 95 return result; 96 } 97 98 // Several of the Parse methods below just do one thing and then call another 99 // method. In a naive implementation, we might have ParseFromString() call 100 // ParseFromArray() which would call ParseFromZeroCopyStream() which would call 101 // ParseFromCodedStream() which would call MergeFromCodedStream() which would 102 // call MergePartialFromCodedStream(). However, when parsing very small 103 // messages, every function call introduces significant overhead. To avoid 104 // this without reproducing code, we use these forced-inline helpers. 105 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream( 106 io::CodedInputStream* input, MessageLite* message); 107 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream( 108 io::CodedInputStream* input, MessageLite* message); 109 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream( 110 io::CodedInputStream* input, MessageLite* message); 111 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray( 112 const void* data, int size, MessageLite* message); 113 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray( 114 const void* data, int size, MessageLite* message); 115 116 inline bool InlineMergeFromCodedStream(io::CodedInputStream* input, 117 MessageLite* message) { 118 if (!message->MergePartialFromCodedStream(input)) return false; 119 if (!message->IsInitialized()) { 120 GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message); 121 return false; 122 } 123 return true; 124 } 125 126 inline bool InlineParseFromCodedStream(io::CodedInputStream* input, 127 MessageLite* message) { 128 message->Clear(); 129 return InlineMergeFromCodedStream(input, message); 130 } 131 132 inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, 133 MessageLite* message) { 134 message->Clear(); 135 return message->MergePartialFromCodedStream(input); 136 } 137 138 inline bool InlineParseFromArray( 139 const void* data, int size, MessageLite* message) { 140 io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size); 141 return InlineParseFromCodedStream(&input, message) && 142 input.ConsumedEntireMessage(); 143 } 144 145 inline bool InlineParsePartialFromArray( 146 const void* data, int size, MessageLite* message) { 147 io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size); 148 return InlineParsePartialFromCodedStream(&input, message) && 149 input.ConsumedEntireMessage(); 150 } 151 152 } // namespace 153 154 155 MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const { 156 MessageLite* message = New(); 157 if (arena != NULL) { 158 arena->Own(message); 159 } 160 return message; 161 } 162 163 bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) { 164 return InlineMergeFromCodedStream(input, this); 165 } 166 167 bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) { 168 return InlineParseFromCodedStream(input, this); 169 } 170 171 bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) { 172 return InlineParsePartialFromCodedStream(input, this); 173 } 174 175 bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { 176 io::CodedInputStream decoder(input); 177 return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); 178 } 179 180 bool MessageLite::ParsePartialFromZeroCopyStream( 181 io::ZeroCopyInputStream* input) { 182 io::CodedInputStream decoder(input); 183 return ParsePartialFromCodedStream(&decoder) && 184 decoder.ConsumedEntireMessage(); 185 } 186 187 bool MessageLite::ParseFromBoundedZeroCopyStream( 188 io::ZeroCopyInputStream* input, int size) { 189 io::CodedInputStream decoder(input); 190 decoder.PushLimit(size); 191 return ParseFromCodedStream(&decoder) && 192 decoder.ConsumedEntireMessage() && 193 decoder.BytesUntilLimit() == 0; 194 } 195 196 bool MessageLite::ParsePartialFromBoundedZeroCopyStream( 197 io::ZeroCopyInputStream* input, int size) { 198 io::CodedInputStream decoder(input); 199 decoder.PushLimit(size); 200 return ParsePartialFromCodedStream(&decoder) && 201 decoder.ConsumedEntireMessage() && 202 decoder.BytesUntilLimit() == 0; 203 } 204 205 bool MessageLite::ParseFromString(const string& data) { 206 return InlineParseFromArray(data.data(), data.size(), this); 207 } 208 209 bool MessageLite::ParsePartialFromString(const string& data) { 210 return InlineParsePartialFromArray(data.data(), data.size(), this); 211 } 212 213 bool MessageLite::ParseFromArray(const void* data, int size) { 214 return InlineParseFromArray(data, size, this); 215 } 216 217 bool MessageLite::ParsePartialFromArray(const void* data, int size) { 218 return InlineParsePartialFromArray(data, size, this); 219 } 220 221 222 // =================================================================== 223 224 uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const { 225 // We only optimize this when using optimize_for = SPEED. In other cases 226 // we just use the CodedOutputStream path. 227 int size = GetCachedSize(); 228 io::ArrayOutputStream out(target, size); 229 io::CodedOutputStream coded_out(&out); 230 SerializeWithCachedSizes(&coded_out); 231 GOOGLE_CHECK(!coded_out.HadError()); 232 return target + size; 233 } 234 235 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { 236 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); 237 return SerializePartialToCodedStream(output); 238 } 239 240 bool MessageLite::SerializePartialToCodedStream( 241 io::CodedOutputStream* output) const { 242 const int size = ByteSize(); // Force size to be cached. 243 if (size < 0) { 244 // Messages >2G cannot be serialized due to overflow computing ByteSize. 245 GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?)."; 246 return false; 247 } 248 249 uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); 250 if (buffer != NULL) { 251 uint8* end = SerializeWithCachedSizesToArray(buffer); 252 if (end - buffer != size) { 253 ByteSizeConsistencyError(size, ByteSize(), end - buffer, *this); 254 } 255 return true; 256 } else { 257 int original_byte_count = output->ByteCount(); 258 SerializeWithCachedSizes(output); 259 if (output->HadError()) { 260 return false; 261 } 262 int final_byte_count = output->ByteCount(); 263 264 if (final_byte_count - original_byte_count != size) { 265 ByteSizeConsistencyError(size, ByteSize(), 266 final_byte_count - original_byte_count, *this); 267 } 268 269 return true; 270 } 271 } 272 273 bool MessageLite::SerializeToZeroCopyStream( 274 io::ZeroCopyOutputStream* output) const { 275 io::CodedOutputStream encoder(output); 276 return SerializeToCodedStream(&encoder); 277 } 278 279 bool MessageLite::SerializePartialToZeroCopyStream( 280 io::ZeroCopyOutputStream* output) const { 281 io::CodedOutputStream encoder(output); 282 return SerializePartialToCodedStream(&encoder); 283 } 284 285 bool MessageLite::AppendToString(string* output) const { 286 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); 287 return AppendPartialToString(output); 288 } 289 290 bool MessageLite::AppendPartialToString(string* output) const { 291 int old_size = output->size(); 292 int byte_size = ByteSize(); 293 if (byte_size < 0) { 294 // Messages >2G cannot be serialized due to overflow computing ByteSize. 295 GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?)."; 296 return false; 297 } 298 299 STLStringResizeUninitialized(output, old_size + byte_size); 300 uint8* start = 301 reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size); 302 uint8* end = SerializeWithCachedSizesToArray(start); 303 if (end - start != byte_size) { 304 ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this); 305 } 306 return true; 307 } 308 309 bool MessageLite::SerializeToString(string* output) const { 310 output->clear(); 311 return AppendToString(output); 312 } 313 314 bool MessageLite::SerializePartialToString(string* output) const { 315 output->clear(); 316 return AppendPartialToString(output); 317 } 318 319 bool MessageLite::SerializeToArray(void* data, int size) const { 320 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); 321 return SerializePartialToArray(data, size); 322 } 323 324 bool MessageLite::SerializePartialToArray(void* data, int size) const { 325 int byte_size = ByteSize(); 326 if (size < byte_size) return false; 327 uint8* start = reinterpret_cast<uint8*>(data); 328 uint8* end = SerializeWithCachedSizesToArray(start); 329 if (end - start != byte_size) { 330 ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this); 331 } 332 return true; 333 } 334 335 string MessageLite::SerializeAsString() const { 336 // If the compiler implements the (Named) Return Value Optimization, 337 // 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 // caller supplied for the return value to be constructed in. 340 string output; 341 if (!AppendToString(&output)) 342 output.clear(); 343 return output; 344 } 345 346 string MessageLite::SerializePartialAsString() const { 347 string output; 348 if (!AppendPartialToString(&output)) 349 output.clear(); 350 return output; 351 } 352 353 namespace internal { 354 template<> 355 MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype( 356 const MessageLite* prototype, google::protobuf::Arena* arena) { 357 return prototype->New(arena); 358 } 359 template <> 360 void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from, 361 MessageLite* to) { 362 to->CheckTypeAndMergeFrom(from); 363 } 364 template<> 365 void GenericTypeHandler<string>::Merge(const string& from, 366 string* to) { 367 *to = from; 368 } 369 } // namespace internal 370 371 } // namespace protobuf 372 } // namespace google 373