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 #if GTEST_HAS_DEATH_TEST
157 EXPECT_DEATH(std::ignore = iter.ReadLong(&outlong), "");
160 EXPECT_TRUE(iter.ReadLong(&outlong));
161 EXPECT_EQ(testint64, outlong);
165 // Tests that we can handle really small buffers.
166 TEST(PickleTest, SmallBuffer) {
167 std::unique_ptr<char[]> buffer(new char[1]);
169 // We should not touch the buffer.
170 Pickle pickle(buffer.get(), 1);
172 PickleIterator iter(pickle);
174 EXPECT_FALSE(iter.ReadInt(&data));
177 // Tests that we can handle improper headers.
178 TEST(PickleTest, BigSize) {
179 int buffer[] = { 0x56035200, 25, 40, 50 };
181 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
182 EXPECT_EQ(0U, pickle.size());
184 PickleIterator iter(pickle);
186 EXPECT_FALSE(iter.ReadInt(&data));
189 // Tests that instances constructed with invalid parameter combinations can be
190 // properly copied. Regression test for https://crbug.com/1271311.
191 TEST(PickleTest, CopyWithInvalidHeader) {
192 // 1. Actual header size (calculated based on the input buffer) > passed in
193 // buffer size. Which results in Pickle's internal |header_| = null.
195 Pickle::Header header = {.payload_size = 100};
196 const char* data = reinterpret_cast<char*>(&header);
197 const Pickle pickle(data, sizeof(header));
199 EXPECT_EQ(0U, pickle.size());
200 EXPECT_FALSE(pickle.data());
202 Pickle copy_built_with_op = pickle;
203 EXPECT_EQ(0U, copy_built_with_op.size());
204 EXPECT_FALSE(copy_built_with_op.data());
206 Pickle copy_built_with_ctor(pickle);
207 EXPECT_EQ(0U, copy_built_with_ctor.size());
208 EXPECT_FALSE(copy_built_with_ctor.data());
210 // 2. Input buffer's size < sizeof(Pickle::Header). Which must also result in
211 // Pickle's internal |header_| = null.
213 const char data[2] = {0x00, 0x00};
214 const Pickle pickle(data, sizeof(data));
215 static_assert(sizeof(Pickle::Header) > sizeof(data));
217 EXPECT_EQ(0U, pickle.size());
218 EXPECT_FALSE(pickle.data());
220 Pickle copy_built_with_op = pickle;
221 EXPECT_EQ(0U, copy_built_with_op.size());
222 EXPECT_FALSE(copy_built_with_op.data());
224 Pickle copy_built_with_ctor(pickle);
225 EXPECT_EQ(0U, copy_built_with_ctor.size());
226 EXPECT_FALSE(copy_built_with_ctor.data());
230 TEST(PickleTest, UnalignedSize) {
231 int buffer[] = { 10, 25, 40, 50 };
233 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
235 PickleIterator iter(pickle);
237 EXPECT_FALSE(iter.ReadInt(&data));
240 TEST(PickleTest, ZeroLenStr) {
242 pickle.WriteString(std::string());
244 PickleIterator iter(pickle);
246 EXPECT_TRUE(iter.ReadString(&outstr));
247 EXPECT_EQ("", outstr);
250 TEST(PickleTest, ZeroLenStr16) {
252 pickle.WriteString16(std::u16string());
254 PickleIterator iter(pickle);
256 EXPECT_TRUE(iter.ReadString(&outstr));
257 EXPECT_EQ("", outstr);
260 TEST(PickleTest, BadLenStr) {
264 PickleIterator iter(pickle);
266 EXPECT_FALSE(iter.ReadString(&outstr));
269 TEST(PickleTest, BadLenStr16) {
273 PickleIterator iter(pickle);
274 std::u16string outstr;
275 EXPECT_FALSE(iter.ReadString16(&outstr));
278 TEST(PickleTest, PeekNext) {
279 struct CustomHeader : base::Pickle::Header {
283 Pickle pickle(sizeof(CustomHeader));
285 pickle.WriteString("Goooooooooooogle");
287 const char* pickle_data = static_cast<const char*>(pickle.data());
291 // Data range doesn't contain header
292 EXPECT_FALSE(Pickle::PeekNext(
293 sizeof(CustomHeader),
295 pickle_data + sizeof(CustomHeader) - 1,
298 // Data range contains header
299 EXPECT_TRUE(Pickle::PeekNext(
300 sizeof(CustomHeader),
302 pickle_data + sizeof(CustomHeader),
304 EXPECT_EQ(pickle_size, pickle.size());
306 // Data range contains header and some other data
307 EXPECT_TRUE(Pickle::PeekNext(
308 sizeof(CustomHeader),
310 pickle_data + sizeof(CustomHeader) + 1,
312 EXPECT_EQ(pickle_size, pickle.size());
314 // Data range contains full pickle
315 EXPECT_TRUE(Pickle::PeekNext(
316 sizeof(CustomHeader),
318 pickle_data + pickle.size(),
320 EXPECT_EQ(pickle_size, pickle.size());
323 TEST(PickleTest, PeekNextOverflow) {
324 struct CustomHeader : base::Pickle::Header {
330 // Check if we can wrap around at all
331 if (sizeof(size_t) > sizeof(header.payload_size))
334 const char* pickle_data = reinterpret_cast<const char*>(&header);
338 // Wrapping around is detected and reported as maximum size_t value
339 header.payload_size = static_cast<uint32_t>(
340 1 - static_cast<int32_t>(sizeof(CustomHeader)));
341 EXPECT_TRUE(Pickle::PeekNext(
342 sizeof(CustomHeader),
344 pickle_data + sizeof(CustomHeader),
346 EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
348 // Ridiculous pickle sizes are fine (callers are supposed to
350 header.payload_size =
351 std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
352 EXPECT_TRUE(Pickle::PeekNext(
353 sizeof(CustomHeader),
355 pickle_data + sizeof(CustomHeader),
357 EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
360 TEST(PickleTest, FindNext) {
363 pickle.WriteString("Domo");
365 const char* start = reinterpret_cast<const char*>(pickle.data());
366 const char* end = start + pickle.size();
368 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end));
369 EXPECT_EQ(nullptr, Pickle::FindNext(pickle.header_size_, start, end - 1));
370 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end + 1));
373 TEST(PickleTest, FindNextWithIncompleteHeader) {
374 size_t header_size = sizeof(Pickle::Header);
375 std::unique_ptr<char[]> buffer(new char[header_size - 1]);
376 memset(buffer.get(), 0x1, header_size - 1);
378 const char* start = buffer.get();
379 const char* end = start + header_size - 1;
381 EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
384 #if defined(COMPILER_MSVC)
385 #pragma warning(push)
386 #pragma warning(disable: 4146)
388 TEST(PickleTest, FindNextOverflow) {
389 size_t header_size = sizeof(Pickle::Header);
390 size_t header_size2 = 2 * header_size;
391 size_t payload_received = 100;
392 std::unique_ptr<char[]> buffer(new char[header_size2 + payload_received]);
393 const char* start = buffer.get();
394 Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
395 const char* end = start + header_size2 + payload_received;
396 // It is impossible to construct an overflow test otherwise.
397 if (sizeof(size_t) > sizeof(header->payload_size) ||
398 sizeof(uintptr_t) > sizeof(header->payload_size))
401 header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
402 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
404 header->payload_size = -header_size2;
405 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
407 header->payload_size = 0;
408 end = start + header_size;
409 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
411 #if defined(COMPILER_MSVC)
415 TEST(PickleTest, GetReadPointerAndAdvance) {
418 PickleIterator iter(pickle);
419 EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
423 int bytes = sizeof(int) * 2;
425 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
426 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
427 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
428 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
429 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
430 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
431 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
434 TEST(PickleTest, Resize) {
435 size_t unit = Pickle::kPayloadUnit;
436 std::unique_ptr<char[]> data(new char[unit]);
437 char* data_ptr = data.get();
438 for (size_t i = 0; i < unit; i++)
441 // construct a message that will be exactly the size of one payload unit,
442 // note that any data will have a 4-byte header indicating the size
443 const size_t payload_size_after_header = unit - sizeof(uint32_t);
445 pickle.WriteData(data_ptr, payload_size_after_header - sizeof(uint32_t));
446 size_t cur_payload = payload_size_after_header;
448 // note: we assume 'unit' is a power of 2
449 EXPECT_EQ(unit, pickle.capacity_after_header());
450 EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
452 // fill out a full page (noting data header)
453 pickle.WriteData(data_ptr, unit - sizeof(uint32_t));
455 EXPECT_EQ(unit * 2, pickle.capacity_after_header());
456 EXPECT_EQ(cur_payload, pickle.payload_size());
458 // one more byte should double the capacity
459 pickle.WriteData(data_ptr, 1);
461 EXPECT_EQ(unit * 4, pickle.capacity_after_header());
462 EXPECT_EQ(cur_payload, pickle.payload_size());
467 struct CustomHeader : Pickle::Header {
473 TEST(PickleTest, HeaderPadding) {
474 const uint32_t kMagic = 0x12345678;
476 Pickle pickle(sizeof(CustomHeader));
477 pickle.WriteInt(kMagic);
479 // this should not overwrite the 'int' payload
480 pickle.headerT<CustomHeader>()->blah = 10;
482 PickleIterator iter(pickle);
484 ASSERT_TRUE(iter.ReadInt(&result));
486 EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
489 TEST(PickleTest, EqualsOperator) {
493 Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
496 copy = copy_refs_source_buffer;
497 ASSERT_EQ(source.size(), copy.size());
500 TEST(PickleTest, EvilLengths) {
502 std::string str(100000, 'A');
503 source.WriteData(str.c_str(), 100000);
504 // ReadString16 used to have its read buffer length calculation wrong leading
505 // to out-of-bounds reading.
506 PickleIterator iter(source);
507 std::u16string str16;
508 EXPECT_FALSE(iter.ReadString16(&str16));
510 // And check we didn't break ReadString16.
511 str16 = (wchar_t) 'A';
513 str16_pickle.WriteString16(str16);
514 iter = PickleIterator(str16_pickle);
515 EXPECT_TRUE(iter.ReadString16(&str16));
516 EXPECT_EQ(1U, str16.length());
518 // Check we don't fail in a length check with invalid String16 size.
519 // (1<<31) * sizeof(char16_t) == 0, so this is particularly evil.
521 bad_len.WriteInt(1 << 31);
522 iter = PickleIterator(bad_len);
523 EXPECT_FALSE(iter.ReadString16(&str16));
526 // Check we can write zero bytes of data and 'data' can be NULL.
527 TEST(PickleTest, ZeroLength) {
529 pickle.WriteData(nullptr, 0);
531 PickleIterator iter(pickle);
534 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
535 EXPECT_EQ(0u, outdatalen);
536 // We can't assert that outdata is NULL.
539 // Check that ReadBytes works properly with an iterator initialized to NULL.
540 TEST(PickleTest, ReadBytes) {
543 pickle.WriteBytes(&data, sizeof(data));
545 PickleIterator iter(pickle);
546 const char* outdata_char = nullptr;
547 EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
550 memcpy(&outdata, outdata_char, sizeof(outdata));
551 EXPECT_EQ(data, outdata);
554 // Checks that when a pickle is deep-copied, the result is not larger than
556 TEST(PickleTest, DeepCopyResize) {
558 while (pickle.capacity_after_header() != pickle.payload_size())
559 pickle.WriteBool(true);
562 Pickle pickle2(pickle);
564 // Check that there isn't any extraneous capacity.
565 EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
570 // Publicly exposes the ClaimBytes interface for testing.
571 class TestingPickle : public Pickle {
573 TestingPickle() = default;
575 void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
580 // Checks that claimed bytes are zero-initialized.
581 TEST(PickleTest, ClaimBytesInitialization) {
582 static const int kChunkSize = 64;
583 TestingPickle pickle;
584 const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
585 for (size_t i = 0; i < kChunkSize; ++i) {
586 EXPECT_EQ(0, bytes[i]);
590 // Checks that ClaimBytes properly advances the write offset.
591 TEST(PickleTest, ClaimBytes) {
592 std::string data("Hello, world!");
594 TestingPickle pickle;
595 pickle.WriteUInt32(data.size());
596 void* bytes = pickle.ClaimBytes(data.size());
598 memcpy(bytes, data.data(), data.size());
600 PickleIterator iter(pickle);
601 uint32_t out_data_length;
602 EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
603 EXPECT_EQ(data.size(), out_data_length);
605 const char* out_data = nullptr;
606 EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
607 EXPECT_EQ(data, std::string(out_data, out_data_length));
610 EXPECT_TRUE(iter.ReadInt(&out_value));
611 EXPECT_EQ(42, out_value);
614 TEST(PickleTest, ReachedEnd) {
620 PickleIterator iter(pickle);
623 EXPECT_FALSE(iter.ReachedEnd());
624 EXPECT_TRUE(iter.ReadInt(&out));
627 EXPECT_FALSE(iter.ReachedEnd());
628 EXPECT_TRUE(iter.ReadInt(&out));
631 EXPECT_FALSE(iter.ReachedEnd());
632 EXPECT_TRUE(iter.ReadInt(&out));
635 EXPECT_TRUE(iter.ReachedEnd());
636 EXPECT_FALSE(iter.ReadInt(&out));
637 EXPECT_TRUE(iter.ReachedEnd());