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 30 matching lines...) Expand all Loading... |
41 #include <io.h> | 41 #include <io.h> |
42 #else | 42 #else |
43 #include <unistd.h> | 43 #include <unistd.h> |
44 #endif | 44 #endif |
45 #include <sstream> | 45 #include <sstream> |
46 #include <fstream> | 46 #include <fstream> |
47 | 47 |
48 #include <google/protobuf/test_util.h> | 48 #include <google/protobuf/test_util.h> |
49 #include <google/protobuf/unittest.pb.h> | 49 #include <google/protobuf/unittest.pb.h> |
50 #include <google/protobuf/io/coded_stream.h> | 50 #include <google/protobuf/io/coded_stream.h> |
| 51 #include <google/protobuf/io/zero_copy_stream.h> |
51 #include <google/protobuf/io/zero_copy_stream_impl.h> | 52 #include <google/protobuf/io/zero_copy_stream_impl.h> |
52 #include <google/protobuf/descriptor.pb.h> | 53 #include <google/protobuf/descriptor.pb.h> |
53 #include <google/protobuf/descriptor.h> | 54 #include <google/protobuf/descriptor.h> |
54 #include <google/protobuf/generated_message_reflection.h> | 55 #include <google/protobuf/generated_message_reflection.h> |
55 | 56 |
56 #include <google/protobuf/stubs/logging.h> | 57 #include <google/protobuf/stubs/logging.h> |
57 #include <google/protobuf/stubs/common.h> | 58 #include <google/protobuf/stubs/common.h> |
58 #include <google/protobuf/stubs/logging.h> | 59 #include <google/protobuf/stubs/logging.h> |
59 #include <google/protobuf/testing/googletest.h> | 60 #include <google/protobuf/testing/googletest.h> |
60 #include <gtest/gtest.h> | 61 #include <gtest/gtest.h> |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 // EOF is reached before the expected number of bytes. | 176 // EOF is reached before the expected number of bytes. |
176 io::ArrayInputStream stream(data.data(), data.size()); | 177 io::ArrayInputStream stream(data.data(), data.size()); |
177 protobuf_unittest::TestAllTypes message; | 178 protobuf_unittest::TestAllTypes message; |
178 EXPECT_FALSE( | 179 EXPECT_FALSE( |
179 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); | 180 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); |
180 } | 181 } |
181 } | 182 } |
182 | 183 |
183 TEST(MessageTest, ParseFailsIfNotInitialized) { | 184 TEST(MessageTest, ParseFailsIfNotInitialized) { |
184 unittest::TestRequired message; | 185 unittest::TestRequired message; |
185 vector<string> errors; | 186 std::vector<string> errors; |
186 | 187 |
187 { | 188 { |
188 ScopedMemoryLog log; | 189 ScopedMemoryLog log; |
189 EXPECT_FALSE(message.ParseFromString("")); | 190 EXPECT_FALSE(message.ParseFromString("")); |
190 errors = log.GetMessages(ERROR); | 191 errors = log.GetMessages(ERROR); |
191 } | 192 } |
192 | 193 |
193 ASSERT_EQ(1, errors.size()); | 194 ASSERT_EQ(1, errors.size()); |
194 EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" " | 195 EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" " |
195 "because it is missing required fields: a, b, c", | 196 "because it is missing required fields: a, b, c", |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 } | 259 } |
259 | 260 |
260 for (int i = 0; i < 2 * 1024 + 1; ++i) { | 261 for (int i = 0; i < 2 * 1024 + 1; ++i) { |
261 message.add_repeated_cord()->CopyFrom(one_megabyte); | 262 message.add_repeated_cord()->CopyFrom(one_megabyte); |
262 } | 263 } |
263 | 264 |
264 Cord serialized; | 265 Cord serialized; |
265 EXPECT_FALSE(message.AppendToCord(&serialized)); | 266 EXPECT_FALSE(message.AppendToCord(&serialized)); |
266 } | 267 } |
267 | 268 |
| 269 TEST(MessageTest, CheckBigOverflow) { |
| 270 unittest::TestAllTypes message; |
| 271 // Create a message with size just over 4GB. We should be able to detect this |
| 272 // too, even though it will make a plain "int" wrap back to a positive number. |
| 273 const string data(1024, 'x'); |
| 274 Cord one_megabyte; |
| 275 for (int i = 0; i < 1024; i++) { |
| 276 one_megabyte.Append(data); |
| 277 } |
| 278 |
| 279 for (int i = 0; i < 4 * 1024 + 1; ++i) { |
| 280 message.add_repeated_cord()->CopyFrom(one_megabyte); |
| 281 } |
| 282 |
| 283 Cord serialized; |
| 284 EXPECT_FALSE(message.AppendToCord(&serialized)); |
| 285 } |
| 286 |
268 #endif // PROTOBUF_HAS_DEATH_TEST | 287 #endif // PROTOBUF_HAS_DEATH_TEST |
269 | 288 |
270 namespace { | 289 namespace { |
| 290 // An input stream that repeats a string's content for a number of times. It |
| 291 // helps us create a really large input without consuming too much memory. Used |
| 292 // to test the parsing behavior when the input size exceeds 2G or close to it. |
| 293 class RepeatedInputStream : public io::ZeroCopyInputStream { |
| 294 public: |
| 295 RepeatedInputStream(const string& data, size_t count) |
| 296 : data_(data), count_(count), position_(0), total_byte_count_(0) {} |
271 | 297 |
272 class NegativeByteSize : public unittest::TestRequired { | 298 virtual bool Next(const void** data, int* size) { |
273 public: | 299 if (position_ == data_.size()) { |
274 virtual int ByteSize() const { return -1; } | 300 if (--count_ == 0) { |
| 301 return false; |
| 302 } |
| 303 position_ = 0; |
| 304 } |
| 305 *data = &data_[position_]; |
| 306 *size = static_cast<int>(data_.size() - position_); |
| 307 position_ = data_.size(); |
| 308 total_byte_count_ += *size; |
| 309 return true; |
| 310 } |
| 311 |
| 312 virtual void BackUp(int count) { |
| 313 position_ -= static_cast<size_t>(count); |
| 314 total_byte_count_ -= count; |
| 315 } |
| 316 |
| 317 virtual bool Skip(int count) { |
| 318 while (count > 0) { |
| 319 const void* data; |
| 320 int size; |
| 321 if (!Next(&data, &size)) { |
| 322 break; |
| 323 } |
| 324 if (size >= count) { |
| 325 BackUp(size - count); |
| 326 return true; |
| 327 } else { |
| 328 count -= size; |
| 329 } |
| 330 } |
| 331 return false; |
| 332 } |
| 333 |
| 334 virtual int64 ByteCount() const { return total_byte_count_; } |
| 335 |
| 336 private: |
| 337 string data_; |
| 338 size_t count_; // The number of strings that haven't been consuemd. |
| 339 size_t position_; // Position in the string for the next read. |
| 340 int64 total_byte_count_; |
275 }; | 341 }; |
276 | |
277 } // namespace | 342 } // namespace |
278 | 343 |
279 TEST(MessageTest, SerializationFailsOnNegativeByteSize) { | 344 TEST(MessageTest, TestParseMessagesCloseTo2G) { |
280 NegativeByteSize message; | 345 // Create a message with a large string field. |
281 string string_output; | 346 string value = string(64 * 1024 * 1024, 'x'); |
282 EXPECT_FALSE(message.AppendPartialToString(&string_output)); | 347 protobuf_unittest::TestAllTypes message; |
| 348 message.set_optional_string(value); |
283 | 349 |
284 io::ArrayOutputStream coded_raw_output(NULL, 100); | 350 // Repeat this message in the input stream to make the total input size |
285 io::CodedOutputStream coded_output(&coded_raw_output); | 351 // close to 2G. |
286 EXPECT_FALSE(message.SerializePartialToCodedStream(&coded_output)); | 352 string data = message.SerializeAsString(); |
| 353 size_t count = static_cast<size_t>(kint32max) / data.size(); |
| 354 RepeatedInputStream input(data, count); |
| 355 |
| 356 // The parsing should succeed. |
| 357 protobuf_unittest::TestAllTypes result; |
| 358 EXPECT_TRUE(result.ParseFromZeroCopyStream(&input)); |
| 359 |
| 360 // When there are multiple occurences of a singulr field, the last one |
| 361 // should win. |
| 362 EXPECT_EQ(value, result.optional_string()); |
| 363 } |
| 364 |
| 365 TEST(MessageTest, TestParseMessagesOver2G) { |
| 366 // Create a message with a large string field. |
| 367 string value = string(64 * 1024 * 1024, 'x'); |
| 368 protobuf_unittest::TestAllTypes message; |
| 369 message.set_optional_string(value); |
| 370 |
| 371 // Repeat this message in the input stream to make the total input size |
| 372 // larger than 2G. |
| 373 string data = message.SerializeAsString(); |
| 374 size_t count = static_cast<size_t>(kint32max) / data.size() + 1; |
| 375 RepeatedInputStream input(data, count); |
| 376 |
| 377 // The parsing should fail. |
| 378 protobuf_unittest::TestAllTypes result; |
| 379 EXPECT_FALSE(result.ParseFromZeroCopyStream(&input)); |
287 } | 380 } |
288 | 381 |
289 TEST(MessageTest, BypassInitializationCheckOnSerialize) { | 382 TEST(MessageTest, BypassInitializationCheckOnSerialize) { |
290 unittest::TestRequired message; | 383 unittest::TestRequired message; |
291 io::ArrayOutputStream raw_output(NULL, 0); | 384 io::ArrayOutputStream raw_output(NULL, 0); |
292 io::CodedOutputStream output(&raw_output); | 385 io::CodedOutputStream output(&raw_output); |
293 EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); | 386 EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); |
294 } | 387 } |
295 | 388 |
296 TEST(MessageTest, FindInitializationErrors) { | 389 TEST(MessageTest, FindInitializationErrors) { |
297 unittest::TestRequired message; | 390 unittest::TestRequired message; |
298 vector<string> errors; | 391 std::vector<string> errors; |
299 message.FindInitializationErrors(&errors); | 392 message.FindInitializationErrors(&errors); |
300 ASSERT_EQ(3, errors.size()); | 393 ASSERT_EQ(3, errors.size()); |
301 EXPECT_EQ("a", errors[0]); | 394 EXPECT_EQ("a", errors[0]); |
302 EXPECT_EQ("b", errors[1]); | 395 EXPECT_EQ("b", errors[1]); |
303 EXPECT_EQ("c", errors[2]); | 396 EXPECT_EQ("c", errors[2]); |
304 } | 397 } |
305 | 398 |
306 TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { | 399 TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { |
307 unittest::TestAllTypes message; | 400 unittest::TestAllTypes message; |
308 | 401 |
309 // Control case. | 402 // Control case. |
310 EXPECT_TRUE(message.ParseFromArray("", 0)); | 403 EXPECT_TRUE(message.ParseFromArray("", 0)); |
311 | 404 |
312 // The byte is a valid varint, but not a valid tag (zero). | 405 // The byte is a valid varint, but not a valid tag (zero). |
313 EXPECT_FALSE(message.ParseFromArray("\0", 1)); | 406 EXPECT_FALSE(message.ParseFromArray("\0", 1)); |
314 | 407 |
315 // The byte is a malformed varint. | 408 // The byte is a malformed varint. |
316 EXPECT_FALSE(message.ParseFromArray("\200", 1)); | 409 EXPECT_FALSE(message.ParseFromArray("\200", 1)); |
317 | 410 |
318 // The byte is an endgroup tag, but we aren't parsing a group. | 411 // The byte is an endgroup tag, but we aren't parsing a group. |
319 EXPECT_FALSE(message.ParseFromArray("\014", 1)); | 412 EXPECT_FALSE(message.ParseFromArray("\014", 1)); |
320 } | 413 } |
321 | 414 |
| 415 // Regression test for b/23630858 |
| 416 TEST(MessageTest, MessageIsStillValidAfterParseFails) { |
| 417 unittest::TestAllTypes message; |
| 418 |
| 419 // 9 0xFFs for the "optional_uint64" field. |
| 420 string invalid_data = "\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; |
| 421 |
| 422 EXPECT_FALSE(message.ParseFromString(invalid_data)); |
| 423 message.Clear(); |
| 424 EXPECT_EQ(0, message.optional_uint64()); |
| 425 } |
| 426 |
322 namespace { | 427 namespace { |
323 | 428 |
324 void ExpectMessageMerged(const unittest::TestAllTypes& message) { | 429 void ExpectMessageMerged(const unittest::TestAllTypes& message) { |
325 EXPECT_EQ(3, message.optional_int32()); | 430 EXPECT_EQ(3, message.optional_int32()); |
326 EXPECT_EQ(2, message.optional_int64()); | 431 EXPECT_EQ(2, message.optional_int64()); |
327 EXPECT_EQ("hello", message.optional_string()); | 432 EXPECT_EQ("hello", message.optional_string()); |
328 } | 433 } |
329 | 434 |
330 void AssignParsingMergeMessages( | 435 void AssignParsingMergeMessages( |
331 unittest::TestAllTypes* msg1, | 436 unittest::TestAllTypes* msg1, |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); | 567 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); |
463 | 568 |
464 // Trying to construct it should return NULL. | 569 // Trying to construct it should return NULL. |
465 EXPECT_TRUE( | 570 EXPECT_TRUE( |
466 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); | 571 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); |
467 } | 572 } |
468 | 573 |
469 | 574 |
470 } // namespace protobuf | 575 } // namespace protobuf |
471 } // namespace google | 576 } // namespace google |
OLD | NEW |