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