xref: /aosp_15_r20/external/cronet/base/pickle_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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