1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/pickle.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h"
17 #include "testing/gtest/include/gtest/gtest.h"
23 const bool testbool1 = false;
24 const bool testbool2 = true;
25 const int testint = 2'093'847'192;
26 const long testlong = 1'093'847'192;
27 const uint16_t testuint16 = 32123;
28 const uint32_t testuint32 = 1593847192;
29 const int64_t testint64 = -0x7E8CA925'3104BDFCLL;
30 const uint64_t testuint64 = 0xCE8CA925'3104BDF7ULL;
31 const float testfloat = 3.1415926935f;
32 const double testdouble = 2.71828182845904523;
33 const std::string teststring("Hello world"); // note non-aligned string length
34 const std::wstring testwstring(L"Hello, world");
35 const std::u16string teststring16(u"Hello, world");
36 const char testrawstring[] = "Hello new world"; // Test raw string writing
37 // Test raw char16_t writing, assumes UTF16 encoding is ANSI for alpha chars.
38 const char16_t testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
39 const char testdata[] = "AAA\0BBB\0";
40 const size_t testdatalen = std::size(testdata) - 1;
42 // checks that the results can be read correctly from the Pickle
43 void VerifyResult(const Pickle& pickle) {
44 PickleIterator iter(pickle);
47 EXPECT_TRUE(iter.ReadBool(&outbool));
48 EXPECT_FALSE(outbool);
49 EXPECT_TRUE(iter.ReadBool(&outbool));
53 EXPECT_TRUE(iter.ReadInt(&outint));
54 EXPECT_EQ(testint, outint);
57 EXPECT_TRUE(iter.ReadLong(&outlong));
58 EXPECT_EQ(testlong, outlong);
61 EXPECT_TRUE(iter.ReadUInt16(&outuint16));
62 EXPECT_EQ(testuint16, outuint16);
65 EXPECT_TRUE(iter.ReadUInt32(&outuint32));
66 EXPECT_EQ(testuint32, outuint32);
69 EXPECT_TRUE(iter.ReadInt64(&outint64));
70 EXPECT_EQ(testint64, outint64);
73 EXPECT_TRUE(iter.ReadUInt64(&outuint64));
74 EXPECT_EQ(testuint64, outuint64);
77 EXPECT_TRUE(iter.ReadFloat(&outfloat));
78 EXPECT_EQ(testfloat, outfloat);
81 EXPECT_TRUE(iter.ReadDouble(&outdouble));
82 EXPECT_EQ(testdouble, outdouble);
84 std::string outstring;
85 EXPECT_TRUE(iter.ReadString(&outstring));
86 EXPECT_EQ(teststring, outstring);
88 std::u16string outstring16;
89 EXPECT_TRUE(iter.ReadString16(&outstring16));
90 EXPECT_EQ(teststring16, outstring16);
92 StringPiece outstringpiece;
93 EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
94 EXPECT_EQ(testrawstring, outstringpiece);
96 StringPiece16 outstringpiece16;
97 EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
98 EXPECT_EQ(testrawstring16, outstringpiece16);
102 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
103 EXPECT_EQ(testdatalen, outdatalen);
104 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
106 // reads past the end should fail
107 EXPECT_FALSE(iter.ReadInt(&outint));
112 TEST(PickleTest, EncodeDecode) {
115 pickle.WriteBool(testbool1);
116 pickle.WriteBool(testbool2);
117 pickle.WriteInt(testint);
118 pickle.WriteLong(testlong);
119 pickle.WriteUInt16(testuint16);
120 pickle.WriteUInt32(testuint32);
121 pickle.WriteInt64(testint64);
122 pickle.WriteUInt64(testuint64);
123 pickle.WriteFloat(testfloat);
124 pickle.WriteDouble(testdouble);
125 pickle.WriteString(teststring);
126 pickle.WriteString16(teststring16);
127 pickle.WriteString(testrawstring);
128 pickle.WriteString16(testrawstring16);
129 pickle.WriteData(testdata, testdatalen);
130 VerifyResult(pickle);
132 // test copy constructor
133 Pickle pickle2(pickle);
134 VerifyResult(pickle2);
139 VerifyResult(pickle3);
142 // Tests that reading/writing a long works correctly when the source process
143 // is 64-bit. We rely on having both 32- and 64-bit trybots to validate both
144 // arms of the conditional in this test.
145 TEST(PickleTest, LongFrom64Bit) {
147 // Under the hood long is always written as a 64-bit value, so simulate a
148 // 64-bit long even on 32-bit architectures by explicitly writing an int64_t.
149 pickle.WriteInt64(testint64);
151 PickleIterator iter(pickle);
153 if (sizeof(long) < sizeof(int64_t)) {
154 // ReadLong() should return false when the original written value can't be
155 // represented as a long.
156 EXPECT_FALSE(iter.ReadLong(&outlong));
158 EXPECT_TRUE(iter.ReadLong(&outlong));
159 EXPECT_EQ(testint64, outlong);
163 // Tests that we can handle really small buffers.
164 TEST(PickleTest, SmallBuffer) {
165 std::unique_ptr<char[]> buffer(new char[1]);
167 // We should not touch the buffer.
168 Pickle pickle(buffer.get(), 1);
170 PickleIterator iter(pickle);
172 EXPECT_FALSE(iter.ReadInt(&data));
175 // Tests that we can handle improper headers.
176 TEST(PickleTest, BigSize) {
177 int buffer[] = { 0x56035200, 25, 40, 50 };
179 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
180 EXPECT_EQ(0U, pickle.size());
182 PickleIterator iter(pickle);
184 EXPECT_FALSE(iter.ReadInt(&data));
187 // Tests that instances constructed with invalid parameter combinations can be
188 // properly copied. Regression test for https://crbug.com/1271311.
189 TEST(PickleTest, CopyWithInvalidHeader) {
190 // 1. Actual header size (calculated based on the input buffer) > passed in
191 // buffer size. Which results in Pickle's internal |header_| = null.
193 Pickle::Header header = {.payload_size = 100};
194 const char* data = reinterpret_cast<char*>(&header);
195 const Pickle pickle(data, sizeof(header));
197 EXPECT_EQ(0U, pickle.size());
198 EXPECT_FALSE(pickle.data());
200 Pickle copy_built_with_op = pickle;
201 EXPECT_EQ(0U, copy_built_with_op.size());
202 EXPECT_FALSE(copy_built_with_op.data());
204 Pickle copy_built_with_ctor(pickle);
205 EXPECT_EQ(0U, copy_built_with_ctor.size());
206 EXPECT_FALSE(copy_built_with_ctor.data());
208 // 2. Input buffer's size < sizeof(Pickle::Header). Which must also result in
209 // Pickle's internal |header_| = null.
211 const char data[2] = {0x00, 0x00};
212 const Pickle pickle(data, sizeof(data));
213 static_assert(sizeof(Pickle::Header) > sizeof(data));
215 EXPECT_EQ(0U, pickle.size());
216 EXPECT_FALSE(pickle.data());
218 Pickle copy_built_with_op = pickle;
219 EXPECT_EQ(0U, copy_built_with_op.size());
220 EXPECT_FALSE(copy_built_with_op.data());
222 Pickle copy_built_with_ctor(pickle);
223 EXPECT_EQ(0U, copy_built_with_ctor.size());
224 EXPECT_FALSE(copy_built_with_ctor.data());
228 TEST(PickleTest, UnalignedSize) {
229 int buffer[] = { 10, 25, 40, 50 };
231 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
233 PickleIterator iter(pickle);
235 EXPECT_FALSE(iter.ReadInt(&data));
238 TEST(PickleTest, ZeroLenStr) {
240 pickle.WriteString(std::string());
242 PickleIterator iter(pickle);
244 EXPECT_TRUE(iter.ReadString(&outstr));
245 EXPECT_EQ("", outstr);
248 TEST(PickleTest, ZeroLenStr16) {
250 pickle.WriteString16(std::u16string());
252 PickleIterator iter(pickle);
254 EXPECT_TRUE(iter.ReadString(&outstr));
255 EXPECT_EQ("", outstr);
258 TEST(PickleTest, BadLenStr) {
262 PickleIterator iter(pickle);
264 EXPECT_FALSE(iter.ReadString(&outstr));
267 TEST(PickleTest, BadLenStr16) {
271 PickleIterator iter(pickle);
272 std::u16string outstr;
273 EXPECT_FALSE(iter.ReadString16(&outstr));
276 TEST(PickleTest, PeekNext) {
277 struct CustomHeader : base::Pickle::Header {
281 Pickle pickle(sizeof(CustomHeader));
283 pickle.WriteString("Goooooooooooogle");
285 const char* pickle_data = pickle.data_as_char();
289 // Data range doesn't contain header
290 EXPECT_FALSE(Pickle::PeekNext(
291 sizeof(CustomHeader),
293 pickle_data + sizeof(CustomHeader) - 1,
296 // Data range contains header
297 EXPECT_TRUE(Pickle::PeekNext(
298 sizeof(CustomHeader),
300 pickle_data + sizeof(CustomHeader),
302 EXPECT_EQ(pickle_size, pickle.size());
304 // Data range contains header and some other data
305 EXPECT_TRUE(Pickle::PeekNext(
306 sizeof(CustomHeader),
308 pickle_data + sizeof(CustomHeader) + 1,
310 EXPECT_EQ(pickle_size, pickle.size());
312 // Data range contains full pickle
313 EXPECT_TRUE(Pickle::PeekNext(
314 sizeof(CustomHeader),
316 pickle_data + pickle.size(),
318 EXPECT_EQ(pickle_size, pickle.size());
321 TEST(PickleTest, PeekNextOverflow) {
322 struct CustomHeader : base::Pickle::Header {
328 // Check if we can wrap around at all
329 if (sizeof(size_t) > sizeof(header.payload_size))
332 const char* pickle_data = reinterpret_cast<const char*>(&header);
336 // Wrapping around is detected and reported as maximum size_t value
337 header.payload_size = static_cast<uint32_t>(
338 1 - static_cast<int32_t>(sizeof(CustomHeader)));
339 EXPECT_TRUE(Pickle::PeekNext(
340 sizeof(CustomHeader),
342 pickle_data + sizeof(CustomHeader),
344 EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
346 // Ridiculous pickle sizes are fine (callers are supposed to
348 header.payload_size =
349 std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
350 EXPECT_TRUE(Pickle::PeekNext(
351 sizeof(CustomHeader),
353 pickle_data + sizeof(CustomHeader),
355 EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
358 TEST(PickleTest, FindNext) {
361 pickle.WriteString("Domo");
363 const char* start = reinterpret_cast<const char*>(pickle.data());
364 const char* end = start + pickle.size();
366 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end));
367 EXPECT_EQ(nullptr, Pickle::FindNext(pickle.header_size_, start, end - 1));
368 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end + 1));
371 TEST(PickleTest, FindNextWithIncompleteHeader) {
372 size_t header_size = sizeof(Pickle::Header);
373 std::unique_ptr<char[]> buffer(new char[header_size - 1]);
374 memset(buffer.get(), 0x1, header_size - 1);
376 const char* start = buffer.get();
377 const char* end = start + header_size - 1;
379 EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
382 #if defined(COMPILER_MSVC)
383 #pragma warning(push)
384 #pragma warning(disable: 4146)
386 TEST(PickleTest, FindNextOverflow) {
387 size_t header_size = sizeof(Pickle::Header);
388 size_t header_size2 = 2 * header_size;
389 size_t payload_received = 100;
390 std::unique_ptr<char[]> buffer(new char[header_size2 + payload_received]);
391 const char* start = buffer.get();
392 Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
393 const char* end = start + header_size2 + payload_received;
394 // It is impossible to construct an overflow test otherwise.
395 if (sizeof(size_t) > sizeof(header->payload_size) ||
396 sizeof(uintptr_t) > sizeof(header->payload_size))
399 header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
400 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
402 header->payload_size = -header_size2;
403 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
405 header->payload_size = 0;
406 end = start + header_size;
407 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
409 #if defined(COMPILER_MSVC)
413 TEST(PickleTest, GetReadPointerAndAdvance) {
416 PickleIterator iter(pickle);
417 EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
421 int bytes = sizeof(int) * 2;
423 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
424 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
425 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
426 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
427 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
428 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
429 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
432 TEST(PickleTest, Resize) {
433 size_t unit = Pickle::kPayloadUnit;
434 std::unique_ptr<char[]> data(new char[unit]);
435 char* data_ptr = data.get();
436 for (size_t i = 0; i < unit; i++)
439 // construct a message that will be exactly the size of one payload unit,
440 // note that any data will have a 4-byte header indicating the size
441 const size_t payload_size_after_header = unit - sizeof(uint32_t);
443 pickle.WriteData(data_ptr, payload_size_after_header - sizeof(uint32_t));
444 size_t cur_payload = payload_size_after_header;
446 // note: we assume 'unit' is a power of 2
447 EXPECT_EQ(unit, pickle.capacity_after_header());
448 EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
450 // fill out a full page (noting data header)
451 pickle.WriteData(data_ptr, unit - sizeof(uint32_t));
453 EXPECT_EQ(unit * 2, pickle.capacity_after_header());
454 EXPECT_EQ(cur_payload, pickle.payload_size());
456 // one more byte should double the capacity
457 pickle.WriteData(data_ptr, 1);
459 EXPECT_EQ(unit * 4, pickle.capacity_after_header());
460 EXPECT_EQ(cur_payload, pickle.payload_size());
465 struct CustomHeader : Pickle::Header {
471 TEST(PickleTest, HeaderPadding) {
472 const uint32_t kMagic = 0x12345678;
474 Pickle pickle(sizeof(CustomHeader));
475 pickle.WriteInt(kMagic);
477 // this should not overwrite the 'int' payload
478 pickle.headerT<CustomHeader>()->blah = 10;
480 PickleIterator iter(pickle);
482 ASSERT_TRUE(iter.ReadInt(&result));
484 EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
487 TEST(PickleTest, EqualsOperator) {
491 Pickle copy_refs_source_buffer(source.data_as_char(), source.size());
493 copy = copy_refs_source_buffer;
494 ASSERT_EQ(source.size(), copy.size());
497 TEST(PickleTest, EvilLengths) {
499 std::string str(100000, 'A');
500 source.WriteData(str.c_str(), 100000);
501 // ReadString16 used to have its read buffer length calculation wrong leading
502 // to out-of-bounds reading.
503 PickleIterator iter(source);
504 std::u16string str16;
505 EXPECT_FALSE(iter.ReadString16(&str16));
507 // And check we didn't break ReadString16.
508 str16 = (wchar_t) 'A';
510 str16_pickle.WriteString16(str16);
511 iter = PickleIterator(str16_pickle);
512 EXPECT_TRUE(iter.ReadString16(&str16));
513 EXPECT_EQ(1U, str16.length());
515 // Check we don't fail in a length check with invalid String16 size.
516 // (1<<31) * sizeof(char16_t) == 0, so this is particularly evil.
518 bad_len.WriteInt(1 << 31);
519 iter = PickleIterator(bad_len);
520 EXPECT_FALSE(iter.ReadString16(&str16));
523 // Check we can write zero bytes of data and 'data' can be NULL.
524 TEST(PickleTest, ZeroLength) {
526 pickle.WriteData(nullptr, 0);
528 PickleIterator iter(pickle);
531 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
532 EXPECT_EQ(0u, outdatalen);
533 // We can't assert that outdata is NULL.
536 // Check that ReadBytes works properly with an iterator initialized to NULL.
537 TEST(PickleTest, ReadBytes) {
540 pickle.WriteBytes(&data, sizeof(data));
542 PickleIterator iter(pickle);
543 const char* outdata_char = nullptr;
544 EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
547 memcpy(&outdata, outdata_char, sizeof(outdata));
548 EXPECT_EQ(data, outdata);
551 // Checks that when a pickle is deep-copied, the result is not larger than
553 TEST(PickleTest, DeepCopyResize) {
555 while (pickle.capacity_after_header() != pickle.payload_size())
556 pickle.WriteBool(true);
559 Pickle pickle2(pickle);
561 // Check that there isn't any extraneous capacity.
562 EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
567 // Publicly exposes the ClaimBytes interface for testing.
568 class TestingPickle : public Pickle {
570 TestingPickle() = default;
572 void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
577 // Checks that claimed bytes are zero-initialized.
578 TEST(PickleTest, ClaimBytesInitialization) {
579 static const int kChunkSize = 64;
580 TestingPickle pickle;
581 const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
582 for (size_t i = 0; i < kChunkSize; ++i) {
583 EXPECT_EQ(0, bytes[i]);
587 // Checks that ClaimBytes properly advances the write offset.
588 TEST(PickleTest, ClaimBytes) {
589 std::string data("Hello, world!");
591 TestingPickle pickle;
592 pickle.WriteUInt32(data.size());
593 void* bytes = pickle.ClaimBytes(data.size());
595 memcpy(bytes, data.data(), data.size());
597 PickleIterator iter(pickle);
598 uint32_t out_data_length;
599 EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
600 EXPECT_EQ(data.size(), out_data_length);
602 const char* out_data = nullptr;
603 EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
604 EXPECT_EQ(data, std::string(out_data, out_data_length));
607 EXPECT_TRUE(iter.ReadInt(&out_value));
608 EXPECT_EQ(42, out_value);
611 TEST(PickleTest, ReachedEnd) {
617 PickleIterator iter(pickle);
620 EXPECT_FALSE(iter.ReachedEnd());
621 EXPECT_TRUE(iter.ReadInt(&out));
624 EXPECT_FALSE(iter.ReachedEnd());
625 EXPECT_TRUE(iter.ReadInt(&out));
628 EXPECT_FALSE(iter.ReachedEnd());
629 EXPECT_TRUE(iter.ReadInt(&out));
632 EXPECT_TRUE(iter.ReachedEnd());
633 EXPECT_FALSE(iter.ReadInt(&out));
634 EXPECT_TRUE(iter.ReachedEnd());
637 // Test that reading a value other than 0 or 1 as a bool does not trigger
639 TEST(PickleTest, NonCanonicalBool) {
641 pickle.WriteInt(0xff);
643 PickleIterator iter(pickle);
645 ASSERT_TRUE(iter.ReadBool(&b));