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.
4
5 #include "base/pickle.h"
6
7 #include <limits.h>
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <memory>
12 #include <string>
13 #include <tuple>
14
15 #include "base/containers/heap_array.h"
16 #include "base/containers/span.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "build/build_config.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base {
22
23 namespace {
24
25 const bool testbool1 = false;
26 const bool testbool2 = true;
27 const int testint = 2'093'847'192;
28 const long testlong = 1'093'847'192;
29 const uint16_t testuint16 = 32123;
30 const uint32_t testuint32 = 1593847192;
31 const int64_t testint64 = -0x7E8CA925'3104BDFCLL;
32 const uint64_t testuint64 = 0xCE8CA925'3104BDF7ULL;
33 const float testfloat = 3.1415926935f;
34 const double testdouble = 2.71828182845904523;
35 const std::string teststring("Hello world"); // note non-aligned string length
36 const std::wstring testwstring(L"Hello, world");
37 const std::u16string teststring16(u"Hello, world");
38 const char testrawstring[] = "Hello new world"; // Test raw string writing
39 // Test raw char16_t writing, assumes UTF16 encoding is ANSI for alpha chars.
40 const char16_t testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
41 const char testdata[] = "AAA\0BBB\0";
42 const size_t testdatalen = std::size(testdata) - 1;
43
44 // checks that the results can be read correctly from the Pickle
VerifyResult(const Pickle & pickle)45 void VerifyResult(const Pickle& pickle) {
46 PickleIterator iter(pickle);
47
48 bool outbool;
49 EXPECT_TRUE(iter.ReadBool(&outbool));
50 EXPECT_FALSE(outbool);
51 EXPECT_TRUE(iter.ReadBool(&outbool));
52 EXPECT_TRUE(outbool);
53
54 int outint;
55 EXPECT_TRUE(iter.ReadInt(&outint));
56 EXPECT_EQ(testint, outint);
57
58 long outlong;
59 EXPECT_TRUE(iter.ReadLong(&outlong));
60 EXPECT_EQ(testlong, outlong);
61
62 uint16_t outuint16;
63 EXPECT_TRUE(iter.ReadUInt16(&outuint16));
64 EXPECT_EQ(testuint16, outuint16);
65
66 uint32_t outuint32;
67 EXPECT_TRUE(iter.ReadUInt32(&outuint32));
68 EXPECT_EQ(testuint32, outuint32);
69
70 int64_t outint64;
71 EXPECT_TRUE(iter.ReadInt64(&outint64));
72 EXPECT_EQ(testint64, outint64);
73
74 uint64_t outuint64;
75 EXPECT_TRUE(iter.ReadUInt64(&outuint64));
76 EXPECT_EQ(testuint64, outuint64);
77
78 float outfloat;
79 EXPECT_TRUE(iter.ReadFloat(&outfloat));
80 EXPECT_EQ(testfloat, outfloat);
81
82 double outdouble;
83 EXPECT_TRUE(iter.ReadDouble(&outdouble));
84 EXPECT_EQ(testdouble, outdouble);
85
86 std::string outstring;
87 EXPECT_TRUE(iter.ReadString(&outstring));
88 EXPECT_EQ(teststring, outstring);
89
90 std::u16string outstring16;
91 EXPECT_TRUE(iter.ReadString16(&outstring16));
92 EXPECT_EQ(teststring16, outstring16);
93
94 StringPiece outstringpiece;
95 EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
96 EXPECT_EQ(testrawstring, outstringpiece);
97
98 StringPiece16 outstringpiece16;
99 EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
100 EXPECT_EQ(testrawstring16, outstringpiece16);
101
102 const char* outdata;
103 size_t outdatalen;
104 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
105 EXPECT_EQ(testdatalen, outdatalen);
106 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
107
108 // reads past the end should fail
109 EXPECT_FALSE(iter.ReadInt(&outint));
110 }
111
112 } // namespace
113
TEST(PickleTest,UnownedVsOwned)114 TEST(PickleTest, UnownedVsOwned) {
115 const uint8_t buffer[1] = {0x00};
116
117 Pickle unowned_pickle = Pickle::WithUnownedBuffer(buffer);
118 EXPECT_EQ(unowned_pickle.GetTotalAllocatedSize(), 0u);
119
120 Pickle owned_pickle = Pickle::WithData(buffer);
121 EXPECT_GE(unowned_pickle.GetTotalAllocatedSize(), 0u);
122 }
123
TEST(PickleTest,EncodeDecode)124 TEST(PickleTest, EncodeDecode) {
125 Pickle pickle;
126
127 pickle.WriteBool(testbool1);
128 pickle.WriteBool(testbool2);
129 pickle.WriteInt(testint);
130 pickle.WriteLong(testlong);
131 pickle.WriteUInt16(testuint16);
132 pickle.WriteUInt32(testuint32);
133 pickle.WriteInt64(testint64);
134 pickle.WriteUInt64(testuint64);
135 pickle.WriteFloat(testfloat);
136 pickle.WriteDouble(testdouble);
137 pickle.WriteString(teststring);
138 pickle.WriteString16(teststring16);
139 pickle.WriteString(testrawstring);
140 pickle.WriteString16(testrawstring16);
141 pickle.WriteData(std::string_view(testdata, testdatalen));
142 VerifyResult(pickle);
143
144 // test copy constructor
145 Pickle pickle2(pickle);
146 VerifyResult(pickle2);
147
148 // test operator=
149 Pickle pickle3;
150 pickle3 = pickle;
151 VerifyResult(pickle3);
152 }
153
154 // Tests that reading/writing a long works correctly when the source process
155 // is 64-bit. We rely on having both 32- and 64-bit trybots to validate both
156 // arms of the conditional in this test.
TEST(PickleTest,LongFrom64Bit)157 TEST(PickleTest, LongFrom64Bit) {
158 Pickle pickle;
159 // Under the hood long is always written as a 64-bit value, so simulate a
160 // 64-bit long even on 32-bit architectures by explicitly writing an int64_t.
161 pickle.WriteInt64(testint64);
162
163 PickleIterator iter(pickle);
164 long outlong;
165 if (sizeof(long) < sizeof(int64_t)) {
166 // ReadLong() should return false when the original written value can't be
167 // represented as a long.
168 EXPECT_FALSE(iter.ReadLong(&outlong));
169 } else {
170 EXPECT_TRUE(iter.ReadLong(&outlong));
171 EXPECT_EQ(testint64, outlong);
172 }
173 }
174
175 // Tests that we can handle really small buffers.
TEST(PickleTest,SmallBuffer)176 TEST(PickleTest, SmallBuffer) {
177 const uint8_t buffer[] = {0x00};
178
179 // We should not touch the buffer.
180 Pickle pickle = Pickle::WithUnownedBuffer(buffer);
181
182 PickleIterator iter(pickle);
183 int data;
184 EXPECT_FALSE(iter.ReadInt(&data));
185 }
186
187 // Tests that we can handle improper headers.
TEST(PickleTest,BigSize)188 TEST(PickleTest, BigSize) {
189 const int buffer[4] = {0x56035200, 25, 40, 50};
190
191 Pickle pickle = Pickle::WithUnownedBuffer(as_byte_span(buffer));
192 EXPECT_EQ(0U, pickle.size());
193
194 PickleIterator iter(pickle);
195 int data;
196 EXPECT_FALSE(iter.ReadInt(&data));
197 }
198
199 // Tests that instances constructed with invalid parameter combinations can be
200 // properly copied. Regression test for https://crbug.com/1271311.
TEST(PickleTest,CopyWithInvalidHeader)201 TEST(PickleTest, CopyWithInvalidHeader) {
202 // 1. Actual header size (calculated based on the input buffer) > passed in
203 // buffer size. Which results in Pickle's internal |header_| = null.
204 {
205 Pickle::Header header = {.payload_size = 100};
206 const Pickle pickle = Pickle::WithUnownedBuffer(byte_span_from_ref(header));
207
208 EXPECT_EQ(0U, pickle.size());
209 EXPECT_FALSE(pickle.data());
210
211 Pickle copy_built_with_op = pickle;
212 EXPECT_EQ(0U, copy_built_with_op.size());
213 EXPECT_FALSE(copy_built_with_op.data());
214
215 Pickle copy_built_with_ctor(pickle);
216 EXPECT_EQ(0U, copy_built_with_ctor.size());
217 EXPECT_FALSE(copy_built_with_ctor.data());
218 }
219 // 2. Input buffer's size < sizeof(Pickle::Header). Which must also result in
220 // Pickle's internal |header_| = null.
221 {
222 const uint8_t data[] = {0x00, 0x00};
223 const Pickle pickle = Pickle::WithUnownedBuffer(data);
224 static_assert(sizeof(Pickle::Header) > sizeof(data));
225
226 EXPECT_EQ(0U, pickle.size());
227 EXPECT_FALSE(pickle.data());
228
229 Pickle copy_built_with_op = pickle;
230 EXPECT_EQ(0U, copy_built_with_op.size());
231 EXPECT_FALSE(copy_built_with_op.data());
232
233 Pickle copy_built_with_ctor(pickle);
234 EXPECT_EQ(0U, copy_built_with_ctor.size());
235 EXPECT_FALSE(copy_built_with_ctor.data());
236 }
237 }
238
TEST(PickleTest,UnalignedSize)239 TEST(PickleTest, UnalignedSize) {
240 int buffer[] = { 10, 25, 40, 50 };
241
242 Pickle pickle = Pickle::WithUnownedBuffer(as_byte_span(buffer));
243
244 PickleIterator iter(pickle);
245 int data;
246 EXPECT_FALSE(iter.ReadInt(&data));
247 }
248
TEST(PickleTest,ZeroLenStr)249 TEST(PickleTest, ZeroLenStr) {
250 Pickle pickle;
251 pickle.WriteString(std::string());
252
253 PickleIterator iter(pickle);
254 std::string outstr;
255 EXPECT_TRUE(iter.ReadString(&outstr));
256 EXPECT_EQ("", outstr);
257 }
258
TEST(PickleTest,ZeroLenStr16)259 TEST(PickleTest, ZeroLenStr16) {
260 Pickle pickle;
261 pickle.WriteString16(std::u16string());
262
263 PickleIterator iter(pickle);
264 std::string outstr;
265 EXPECT_TRUE(iter.ReadString(&outstr));
266 EXPECT_EQ("", outstr);
267 }
268
TEST(PickleTest,BadLenStr)269 TEST(PickleTest, BadLenStr) {
270 Pickle pickle;
271 pickle.WriteInt(-2);
272
273 PickleIterator iter(pickle);
274 std::string outstr;
275 EXPECT_FALSE(iter.ReadString(&outstr));
276 }
277
TEST(PickleTest,BadLenStr16)278 TEST(PickleTest, BadLenStr16) {
279 Pickle pickle;
280 pickle.WriteInt(-1);
281
282 PickleIterator iter(pickle);
283 std::u16string outstr;
284 EXPECT_FALSE(iter.ReadString16(&outstr));
285 }
286
TEST(PickleTest,PeekNext)287 TEST(PickleTest, PeekNext) {
288 struct CustomHeader : base::Pickle::Header {
289 int cookies[10];
290 };
291
292 Pickle pickle(sizeof(CustomHeader));
293
294 pickle.WriteString("Goooooooooooogle");
295
296 const char* pickle_data = pickle.data_as_char();
297
298 size_t pickle_size;
299
300 // Data range doesn't contain header
301 EXPECT_FALSE(Pickle::PeekNext(
302 sizeof(CustomHeader),
303 pickle_data,
304 pickle_data + sizeof(CustomHeader) - 1,
305 &pickle_size));
306
307 // Data range contains header
308 EXPECT_TRUE(Pickle::PeekNext(
309 sizeof(CustomHeader),
310 pickle_data,
311 pickle_data + sizeof(CustomHeader),
312 &pickle_size));
313 EXPECT_EQ(pickle_size, pickle.size());
314
315 // Data range contains header and some other data
316 EXPECT_TRUE(Pickle::PeekNext(
317 sizeof(CustomHeader),
318 pickle_data,
319 pickle_data + sizeof(CustomHeader) + 1,
320 &pickle_size));
321 EXPECT_EQ(pickle_size, pickle.size());
322
323 // Data range contains full pickle
324 EXPECT_TRUE(Pickle::PeekNext(
325 sizeof(CustomHeader),
326 pickle_data,
327 pickle_data + pickle.size(),
328 &pickle_size));
329 EXPECT_EQ(pickle_size, pickle.size());
330 }
331
TEST(PickleTest,PeekNextOverflow)332 TEST(PickleTest, PeekNextOverflow) {
333 struct CustomHeader : base::Pickle::Header {
334 int cookies[10];
335 };
336
337 CustomHeader header;
338
339 // Check if we can wrap around at all
340 if (sizeof(size_t) > sizeof(header.payload_size))
341 return;
342
343 const char* pickle_data = reinterpret_cast<const char*>(&header);
344
345 size_t pickle_size;
346
347 // Wrapping around is detected and reported as maximum size_t value
348 header.payload_size = static_cast<uint32_t>(
349 1 - static_cast<int32_t>(sizeof(CustomHeader)));
350 EXPECT_TRUE(Pickle::PeekNext(
351 sizeof(CustomHeader),
352 pickle_data,
353 pickle_data + sizeof(CustomHeader),
354 &pickle_size));
355 EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
356
357 // Ridiculous pickle sizes are fine (callers are supposed to
358 // verify them)
359 header.payload_size =
360 std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
361 EXPECT_TRUE(Pickle::PeekNext(
362 sizeof(CustomHeader),
363 pickle_data,
364 pickle_data + sizeof(CustomHeader),
365 &pickle_size));
366 EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
367 }
368
TEST(PickleTest,FindNext)369 TEST(PickleTest, FindNext) {
370 Pickle pickle;
371 pickle.WriteInt(1);
372 pickle.WriteString("Domo");
373
374 const char* start = reinterpret_cast<const char*>(pickle.data());
375 const char* end = start + pickle.size();
376
377 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end));
378 EXPECT_EQ(nullptr, Pickle::FindNext(pickle.header_size_, start, end - 1));
379 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end + 1));
380 }
381
TEST(PickleTest,FindNextWithIncompleteHeader)382 TEST(PickleTest, FindNextWithIncompleteHeader) {
383 size_t header_size = sizeof(Pickle::Header);
384 auto buffer = base::HeapArray<char>::Uninit(header_size - 1);
385 memset(buffer.data(), 0x1, header_size - 1);
386
387 const char* start = buffer.data();
388 const char* end = start + header_size - 1;
389
390 EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
391 }
392
393 #if defined(COMPILER_MSVC)
394 #pragma warning(push)
395 #pragma warning(disable: 4146)
396 #endif
TEST(PickleTest,FindNextOverflow)397 TEST(PickleTest, FindNextOverflow) {
398 size_t header_size = sizeof(Pickle::Header);
399 size_t header_size2 = 2 * header_size;
400 size_t payload_received = 100;
401 auto buffer = base::HeapArray<char>::Uninit(header_size2 + payload_received);
402 const char* start = buffer.data();
403 Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.data());
404 const char* end = start + header_size2 + payload_received;
405 // It is impossible to construct an overflow test otherwise.
406 if (sizeof(size_t) > sizeof(header->payload_size) ||
407 sizeof(uintptr_t) > sizeof(header->payload_size))
408 return;
409
410 header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
411 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
412
413 header->payload_size = -header_size2;
414 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
415
416 header->payload_size = 0;
417 end = start + header_size;
418 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
419 }
420 #if defined(COMPILER_MSVC)
421 #pragma warning(pop)
422 #endif
423
TEST(PickleTest,GetReadPointerAndAdvance)424 TEST(PickleTest, GetReadPointerAndAdvance) {
425 Pickle pickle;
426
427 PickleIterator iter(pickle);
428 EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
429
430 pickle.WriteInt(1);
431 pickle.WriteInt(2);
432 int bytes = sizeof(int) * 2;
433
434 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
435 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
436 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
437 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
438 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
439 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
440 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
441 }
442
TEST(PickleTest,Resize)443 TEST(PickleTest, Resize) {
444 size_t unit = Pickle::kPayloadUnit;
445 auto data = base::HeapArray<char>::Uninit(unit);
446 char* data_ptr = data.data();
447 for (size_t i = 0; i < unit; i++)
448 data_ptr[i] = 'G';
449
450 // construct a message that will be exactly the size of one payload unit,
451 // note that any data will have a 4-byte header indicating the size
452 const size_t payload_size_after_header = unit - sizeof(uint32_t);
453 Pickle pickle;
454 pickle.WriteData(
455 std::string_view(data_ptr, payload_size_after_header - sizeof(uint32_t)));
456 size_t cur_payload = payload_size_after_header;
457
458 // note: we assume 'unit' is a power of 2
459 EXPECT_EQ(unit, pickle.capacity_after_header());
460 EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
461
462 // fill out a full page (noting data header)
463 pickle.WriteData(std::string_view(data_ptr, unit - sizeof(uint32_t)));
464 cur_payload += unit;
465 EXPECT_EQ(unit * 2, pickle.capacity_after_header());
466 EXPECT_EQ(cur_payload, pickle.payload_size());
467
468 // one more byte should double the capacity
469 pickle.WriteData(std::string_view(data_ptr, 1u));
470 cur_payload += 8;
471 EXPECT_EQ(unit * 4, pickle.capacity_after_header());
472 EXPECT_EQ(cur_payload, pickle.payload_size());
473 }
474
475 namespace {
476
477 struct CustomHeader : Pickle::Header {
478 int blah;
479 };
480
481 } // namespace
482
TEST(PickleTest,HeaderPadding)483 TEST(PickleTest, HeaderPadding) {
484 const uint32_t kMagic = 0x12345678;
485
486 Pickle pickle(sizeof(CustomHeader));
487 pickle.WriteInt(kMagic);
488
489 // this should not overwrite the 'int' payload
490 pickle.headerT<CustomHeader>()->blah = 10;
491
492 PickleIterator iter(pickle);
493 int result;
494 ASSERT_TRUE(iter.ReadInt(&result));
495
496 EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
497 }
498
TEST(PickleTest,EqualsOperator)499 TEST(PickleTest, EqualsOperator) {
500 Pickle source;
501 source.WriteInt(1);
502
503 Pickle copy_refs_source_buffer = Pickle::WithUnownedBuffer(source);
504 Pickle copy;
505 copy = copy_refs_source_buffer;
506 ASSERT_EQ(source.size(), copy.size());
507 }
508
TEST(PickleTest,EvilLengths)509 TEST(PickleTest, EvilLengths) {
510 Pickle source;
511 std::string str(100000, 'A');
512 source.WriteData(std::string_view(str.c_str(), 100000u));
513 // ReadString16 used to have its read buffer length calculation wrong leading
514 // to out-of-bounds reading.
515 PickleIterator iter(source);
516 std::u16string str16;
517 EXPECT_FALSE(iter.ReadString16(&str16));
518
519 // And check we didn't break ReadString16.
520 str16 = u"A";
521 Pickle str16_pickle;
522 str16_pickle.WriteString16(str16);
523 iter = PickleIterator(str16_pickle);
524 EXPECT_TRUE(iter.ReadString16(&str16));
525 EXPECT_EQ(1U, str16.length());
526
527 // Check we don't fail in a length check with invalid String16 size.
528 // (1<<31) * sizeof(char16_t) == 0, so this is particularly evil.
529 Pickle bad_len;
530 bad_len.WriteInt(1 << 31);
531 iter = PickleIterator(bad_len);
532 EXPECT_FALSE(iter.ReadString16(&str16));
533 }
534
535 // Check we can write zero bytes of data and 'data' can be NULL.
TEST(PickleTest,ZeroLength)536 TEST(PickleTest, ZeroLength) {
537 Pickle pickle;
538 pickle.WriteData(std::string_view());
539
540 PickleIterator iter(pickle);
541 const char* outdata;
542 size_t outdatalen;
543 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
544 EXPECT_EQ(0u, outdatalen);
545 // We can't assert that outdata is NULL.
546 }
547
548 // Check that ReadBytes works properly with an iterator initialized to NULL.
TEST(PickleTest,ReadBytes)549 TEST(PickleTest, ReadBytes) {
550 Pickle pickle;
551 int data = 0x7abcd;
552 pickle.WriteBytes(&data, sizeof(data));
553
554 PickleIterator iter(pickle);
555 const char* outdata_char = nullptr;
556 EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
557
558 int outdata;
559 memcpy(&outdata, outdata_char, sizeof(outdata));
560 EXPECT_EQ(data, outdata);
561 }
562
563 // Checks that when a pickle is deep-copied, the result is not larger than
564 // needed.
TEST(PickleTest,DeepCopyResize)565 TEST(PickleTest, DeepCopyResize) {
566 Pickle pickle;
567 while (pickle.capacity_after_header() != pickle.payload_size())
568 pickle.WriteBool(true);
569
570 // Make a deep copy.
571 Pickle pickle2(pickle);
572
573 // Check that there isn't any extraneous capacity.
574 EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
575 }
576
577 namespace {
578
579 // Publicly exposes the ClaimBytes interface for testing.
580 class TestingPickle : public Pickle {
581 public:
582 TestingPickle() = default;
583
ClaimBytes(size_t num_bytes)584 void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
585 };
586
587 } // namespace
588
589 // Checks that claimed bytes are zero-initialized.
TEST(PickleTest,ClaimBytesInitialization)590 TEST(PickleTest, ClaimBytesInitialization) {
591 static const int kChunkSize = 64;
592 TestingPickle pickle;
593 const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
594 for (size_t i = 0; i < kChunkSize; ++i) {
595 EXPECT_EQ(0, bytes[i]);
596 }
597 }
598
599 // Checks that ClaimBytes properly advances the write offset.
TEST(PickleTest,ClaimBytes)600 TEST(PickleTest, ClaimBytes) {
601 std::string data("Hello, world!");
602
603 TestingPickle pickle;
604 pickle.WriteUInt32(data.size());
605 void* bytes = pickle.ClaimBytes(data.size());
606 pickle.WriteInt(42);
607 memcpy(bytes, data.data(), data.size());
608
609 PickleIterator iter(pickle);
610 uint32_t out_data_length;
611 EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
612 EXPECT_EQ(data.size(), out_data_length);
613
614 const char* out_data = nullptr;
615 EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
616 EXPECT_EQ(data, std::string(out_data, out_data_length));
617
618 int out_value;
619 EXPECT_TRUE(iter.ReadInt(&out_value));
620 EXPECT_EQ(42, out_value);
621 }
622
TEST(PickleTest,ReachedEnd)623 TEST(PickleTest, ReachedEnd) {
624 Pickle pickle;
625 pickle.WriteInt(1);
626 pickle.WriteInt(2);
627 pickle.WriteInt(3);
628
629 PickleIterator iter(pickle);
630 int out;
631
632 EXPECT_FALSE(iter.ReachedEnd());
633 EXPECT_TRUE(iter.ReadInt(&out));
634 EXPECT_EQ(1, out);
635
636 EXPECT_FALSE(iter.ReachedEnd());
637 EXPECT_TRUE(iter.ReadInt(&out));
638 EXPECT_EQ(2, out);
639
640 EXPECT_FALSE(iter.ReachedEnd());
641 EXPECT_TRUE(iter.ReadInt(&out));
642 EXPECT_EQ(3, out);
643
644 EXPECT_TRUE(iter.ReachedEnd());
645 EXPECT_FALSE(iter.ReadInt(&out));
646 EXPECT_TRUE(iter.ReachedEnd());
647 }
648
649 // Test that reading a value other than 0 or 1 as a bool does not trigger
650 // UBSan.
TEST(PickleTest,NonCanonicalBool)651 TEST(PickleTest, NonCanonicalBool) {
652 Pickle pickle;
653 pickle.WriteInt(0xff);
654
655 PickleIterator iter(pickle);
656 bool b;
657 ASSERT_TRUE(iter.ReadBool(&b));
658 EXPECT_TRUE(b);
659 }
660
661 } // namespace base
662