[M108 Migration][VD] Support set time and time zone offset
[platform/framework/web/chromium-efl.git] / base / pickle_unittest.cc
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/strings/utf_string_conversions.h"
16 #include "build/build_config.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace base {
20
21 namespace {
22
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;
41
42 // checks that the results can be read correctly from the Pickle
43 void VerifyResult(const Pickle& pickle) {
44   PickleIterator iter(pickle);
45
46   bool outbool;
47   EXPECT_TRUE(iter.ReadBool(&outbool));
48   EXPECT_FALSE(outbool);
49   EXPECT_TRUE(iter.ReadBool(&outbool));
50   EXPECT_TRUE(outbool);
51
52   int outint;
53   EXPECT_TRUE(iter.ReadInt(&outint));
54   EXPECT_EQ(testint, outint);
55
56   long outlong;
57   EXPECT_TRUE(iter.ReadLong(&outlong));
58   EXPECT_EQ(testlong, outlong);
59
60   uint16_t outuint16;
61   EXPECT_TRUE(iter.ReadUInt16(&outuint16));
62   EXPECT_EQ(testuint16, outuint16);
63
64   uint32_t outuint32;
65   EXPECT_TRUE(iter.ReadUInt32(&outuint32));
66   EXPECT_EQ(testuint32, outuint32);
67
68   int64_t outint64;
69   EXPECT_TRUE(iter.ReadInt64(&outint64));
70   EXPECT_EQ(testint64, outint64);
71
72   uint64_t outuint64;
73   EXPECT_TRUE(iter.ReadUInt64(&outuint64));
74   EXPECT_EQ(testuint64, outuint64);
75
76   float outfloat;
77   EXPECT_TRUE(iter.ReadFloat(&outfloat));
78   EXPECT_EQ(testfloat, outfloat);
79
80   double outdouble;
81   EXPECT_TRUE(iter.ReadDouble(&outdouble));
82   EXPECT_EQ(testdouble, outdouble);
83
84   std::string outstring;
85   EXPECT_TRUE(iter.ReadString(&outstring));
86   EXPECT_EQ(teststring, outstring);
87
88   std::u16string outstring16;
89   EXPECT_TRUE(iter.ReadString16(&outstring16));
90   EXPECT_EQ(teststring16, outstring16);
91
92   StringPiece outstringpiece;
93   EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
94   EXPECT_EQ(testrawstring, outstringpiece);
95
96   StringPiece16 outstringpiece16;
97   EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
98   EXPECT_EQ(testrawstring16, outstringpiece16);
99
100   const char* outdata;
101   size_t outdatalen;
102   EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
103   EXPECT_EQ(testdatalen, outdatalen);
104   EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
105
106   // reads past the end should fail
107   EXPECT_FALSE(iter.ReadInt(&outint));
108 }
109
110 }  // namespace
111
112 TEST(PickleTest, EncodeDecode) {
113   Pickle pickle;
114
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);
131
132   // test copy constructor
133   Pickle pickle2(pickle);
134   VerifyResult(pickle2);
135
136   // test operator=
137   Pickle pickle3;
138   pickle3 = pickle;
139   VerifyResult(pickle3);
140 }
141
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) {
146   Pickle pickle;
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);
150
151   PickleIterator iter(pickle);
152   long outlong;
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), "");
158 #endif
159   } else {
160     EXPECT_TRUE(iter.ReadLong(&outlong));
161     EXPECT_EQ(testint64, outlong);
162   }
163 }
164
165 // Tests that we can handle really small buffers.
166 TEST(PickleTest, SmallBuffer) {
167   std::unique_ptr<char[]> buffer(new char[1]);
168
169   // We should not touch the buffer.
170   Pickle pickle(buffer.get(), 1);
171
172   PickleIterator iter(pickle);
173   int data;
174   EXPECT_FALSE(iter.ReadInt(&data));
175 }
176
177 // Tests that we can handle improper headers.
178 TEST(PickleTest, BigSize) {
179   int buffer[] = { 0x56035200, 25, 40, 50 };
180
181   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
182   EXPECT_EQ(0U, pickle.size());
183
184   PickleIterator iter(pickle);
185   int data;
186   EXPECT_FALSE(iter.ReadInt(&data));
187 }
188
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.
194   {
195     Pickle::Header header = {.payload_size = 100};
196     const char* data = reinterpret_cast<char*>(&header);
197     const Pickle pickle(data, sizeof(header));
198
199     EXPECT_EQ(0U, pickle.size());
200     EXPECT_FALSE(pickle.data());
201
202     Pickle copy_built_with_op = pickle;
203     EXPECT_EQ(0U, copy_built_with_op.size());
204     EXPECT_FALSE(copy_built_with_op.data());
205
206     Pickle copy_built_with_ctor(pickle);
207     EXPECT_EQ(0U, copy_built_with_ctor.size());
208     EXPECT_FALSE(copy_built_with_ctor.data());
209   }
210   // 2. Input buffer's size < sizeof(Pickle::Header). Which must also result in
211   // Pickle's internal |header_| = null.
212   {
213     const char data[2] = {0x00, 0x00};
214     const Pickle pickle(data, sizeof(data));
215     static_assert(sizeof(Pickle::Header) > sizeof(data));
216
217     EXPECT_EQ(0U, pickle.size());
218     EXPECT_FALSE(pickle.data());
219
220     Pickle copy_built_with_op = pickle;
221     EXPECT_EQ(0U, copy_built_with_op.size());
222     EXPECT_FALSE(copy_built_with_op.data());
223
224     Pickle copy_built_with_ctor(pickle);
225     EXPECT_EQ(0U, copy_built_with_ctor.size());
226     EXPECT_FALSE(copy_built_with_ctor.data());
227   }
228 }
229
230 TEST(PickleTest, UnalignedSize) {
231   int buffer[] = { 10, 25, 40, 50 };
232
233   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
234
235   PickleIterator iter(pickle);
236   int data;
237   EXPECT_FALSE(iter.ReadInt(&data));
238 }
239
240 TEST(PickleTest, ZeroLenStr) {
241   Pickle pickle;
242   pickle.WriteString(std::string());
243
244   PickleIterator iter(pickle);
245   std::string outstr;
246   EXPECT_TRUE(iter.ReadString(&outstr));
247   EXPECT_EQ("", outstr);
248 }
249
250 TEST(PickleTest, ZeroLenStr16) {
251   Pickle pickle;
252   pickle.WriteString16(std::u16string());
253
254   PickleIterator iter(pickle);
255   std::string outstr;
256   EXPECT_TRUE(iter.ReadString(&outstr));
257   EXPECT_EQ("", outstr);
258 }
259
260 TEST(PickleTest, BadLenStr) {
261   Pickle pickle;
262   pickle.WriteInt(-2);
263
264   PickleIterator iter(pickle);
265   std::string outstr;
266   EXPECT_FALSE(iter.ReadString(&outstr));
267 }
268
269 TEST(PickleTest, BadLenStr16) {
270   Pickle pickle;
271   pickle.WriteInt(-1);
272
273   PickleIterator iter(pickle);
274   std::u16string outstr;
275   EXPECT_FALSE(iter.ReadString16(&outstr));
276 }
277
278 TEST(PickleTest, PeekNext) {
279   struct CustomHeader : base::Pickle::Header {
280     int cookies[10];
281   };
282
283   Pickle pickle(sizeof(CustomHeader));
284
285   pickle.WriteString("Goooooooooooogle");
286
287   const char* pickle_data = static_cast<const char*>(pickle.data());
288
289   size_t pickle_size;
290
291   // Data range doesn't contain header
292   EXPECT_FALSE(Pickle::PeekNext(
293       sizeof(CustomHeader),
294       pickle_data,
295       pickle_data + sizeof(CustomHeader) - 1,
296       &pickle_size));
297
298   // Data range contains header
299   EXPECT_TRUE(Pickle::PeekNext(
300       sizeof(CustomHeader),
301       pickle_data,
302       pickle_data + sizeof(CustomHeader),
303       &pickle_size));
304   EXPECT_EQ(pickle_size, pickle.size());
305
306   // Data range contains header and some other data
307   EXPECT_TRUE(Pickle::PeekNext(
308       sizeof(CustomHeader),
309       pickle_data,
310       pickle_data + sizeof(CustomHeader) + 1,
311       &pickle_size));
312   EXPECT_EQ(pickle_size, pickle.size());
313
314   // Data range contains full pickle
315   EXPECT_TRUE(Pickle::PeekNext(
316       sizeof(CustomHeader),
317       pickle_data,
318       pickle_data + pickle.size(),
319       &pickle_size));
320   EXPECT_EQ(pickle_size, pickle.size());
321 }
322
323 TEST(PickleTest, PeekNextOverflow) {
324   struct CustomHeader : base::Pickle::Header {
325     int cookies[10];
326   };
327
328   CustomHeader header;
329
330   // Check if we can wrap around at all
331   if (sizeof(size_t) > sizeof(header.payload_size))
332     return;
333
334   const char* pickle_data = reinterpret_cast<const char*>(&header);
335
336   size_t pickle_size;
337
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),
343       pickle_data,
344       pickle_data + sizeof(CustomHeader),
345       &pickle_size));
346   EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
347
348   // Ridiculous pickle sizes are fine (callers are supposed to
349   // verify them)
350   header.payload_size =
351       std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
352   EXPECT_TRUE(Pickle::PeekNext(
353       sizeof(CustomHeader),
354       pickle_data,
355       pickle_data + sizeof(CustomHeader),
356       &pickle_size));
357   EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
358 }
359
360 TEST(PickleTest, FindNext) {
361   Pickle pickle;
362   pickle.WriteInt(1);
363   pickle.WriteString("Domo");
364
365   const char* start = reinterpret_cast<const char*>(pickle.data());
366   const char* end = start + pickle.size();
367
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));
371 }
372
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);
377
378   const char* start = buffer.get();
379   const char* end = start + header_size - 1;
380
381   EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
382 }
383
384 #if defined(COMPILER_MSVC)
385 #pragma warning(push)
386 #pragma warning(disable: 4146)
387 #endif
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))
399     return;
400
401   header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
402   EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
403
404   header->payload_size = -header_size2;
405   EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
406
407   header->payload_size = 0;
408   end = start + header_size;
409   EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
410 }
411 #if defined(COMPILER_MSVC)
412 #pragma warning(pop)
413 #endif
414
415 TEST(PickleTest, GetReadPointerAndAdvance) {
416   Pickle pickle;
417
418   PickleIterator iter(pickle);
419   EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
420
421   pickle.WriteInt(1);
422   pickle.WriteInt(2);
423   int bytes = sizeof(int) * 2;
424
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));
432 }
433
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++)
439     data_ptr[i] = 'G';
440
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);
444   Pickle pickle;
445   pickle.WriteData(data_ptr, payload_size_after_header - sizeof(uint32_t));
446   size_t cur_payload = payload_size_after_header;
447
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);
451
452   // fill out a full page (noting data header)
453   pickle.WriteData(data_ptr, unit - sizeof(uint32_t));
454   cur_payload += unit;
455   EXPECT_EQ(unit * 2, pickle.capacity_after_header());
456   EXPECT_EQ(cur_payload, pickle.payload_size());
457
458   // one more byte should double the capacity
459   pickle.WriteData(data_ptr, 1);
460   cur_payload += 8;
461   EXPECT_EQ(unit * 4, pickle.capacity_after_header());
462   EXPECT_EQ(cur_payload, pickle.payload_size());
463 }
464
465 namespace {
466
467 struct CustomHeader : Pickle::Header {
468   int blah;
469 };
470
471 }  // namespace
472
473 TEST(PickleTest, HeaderPadding) {
474   const uint32_t kMagic = 0x12345678;
475
476   Pickle pickle(sizeof(CustomHeader));
477   pickle.WriteInt(kMagic);
478
479   // this should not overwrite the 'int' payload
480   pickle.headerT<CustomHeader>()->blah = 10;
481
482   PickleIterator iter(pickle);
483   int result;
484   ASSERT_TRUE(iter.ReadInt(&result));
485
486   EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
487 }
488
489 TEST(PickleTest, EqualsOperator) {
490   Pickle source;
491   source.WriteInt(1);
492
493   Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
494                                  source.size());
495   Pickle copy;
496   copy = copy_refs_source_buffer;
497   ASSERT_EQ(source.size(), copy.size());
498 }
499
500 TEST(PickleTest, EvilLengths) {
501   Pickle source;
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));
509
510   // And check we didn't break ReadString16.
511   str16 = (wchar_t) 'A';
512   Pickle str16_pickle;
513   str16_pickle.WriteString16(str16);
514   iter = PickleIterator(str16_pickle);
515   EXPECT_TRUE(iter.ReadString16(&str16));
516   EXPECT_EQ(1U, str16.length());
517
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.
520   Pickle bad_len;
521   bad_len.WriteInt(1 << 31);
522   iter = PickleIterator(bad_len);
523   EXPECT_FALSE(iter.ReadString16(&str16));
524 }
525
526 // Check we can write zero bytes of data and 'data' can be NULL.
527 TEST(PickleTest, ZeroLength) {
528   Pickle pickle;
529   pickle.WriteData(nullptr, 0);
530
531   PickleIterator iter(pickle);
532   const char* outdata;
533   size_t outdatalen;
534   EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
535   EXPECT_EQ(0u, outdatalen);
536   // We can't assert that outdata is NULL.
537 }
538
539 // Check that ReadBytes works properly with an iterator initialized to NULL.
540 TEST(PickleTest, ReadBytes) {
541   Pickle pickle;
542   int data = 0x7abcd;
543   pickle.WriteBytes(&data, sizeof(data));
544
545   PickleIterator iter(pickle);
546   const char* outdata_char = nullptr;
547   EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
548
549   int outdata;
550   memcpy(&outdata, outdata_char, sizeof(outdata));
551   EXPECT_EQ(data, outdata);
552 }
553
554 // Checks that when a pickle is deep-copied, the result is not larger than
555 // needed.
556 TEST(PickleTest, DeepCopyResize) {
557   Pickle pickle;
558   while (pickle.capacity_after_header() != pickle.payload_size())
559     pickle.WriteBool(true);
560
561   // Make a deep copy.
562   Pickle pickle2(pickle);
563
564   // Check that there isn't any extraneous capacity.
565   EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
566 }
567
568 namespace {
569
570 // Publicly exposes the ClaimBytes interface for testing.
571 class TestingPickle : public Pickle {
572  public:
573   TestingPickle() = default;
574
575   void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
576 };
577
578 }  // namespace
579
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]);
587   }
588 }
589
590 // Checks that ClaimBytes properly advances the write offset.
591 TEST(PickleTest, ClaimBytes) {
592   std::string data("Hello, world!");
593
594   TestingPickle pickle;
595   pickle.WriteUInt32(data.size());
596   void* bytes = pickle.ClaimBytes(data.size());
597   pickle.WriteInt(42);
598   memcpy(bytes, data.data(), data.size());
599
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);
604
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));
608
609   int out_value;
610   EXPECT_TRUE(iter.ReadInt(&out_value));
611   EXPECT_EQ(42, out_value);
612 }
613
614 TEST(PickleTest, ReachedEnd) {
615   Pickle pickle;
616   pickle.WriteInt(1);
617   pickle.WriteInt(2);
618   pickle.WriteInt(3);
619
620   PickleIterator iter(pickle);
621   int out;
622
623   EXPECT_FALSE(iter.ReachedEnd());
624   EXPECT_TRUE(iter.ReadInt(&out));
625   EXPECT_EQ(1, out);
626
627   EXPECT_FALSE(iter.ReachedEnd());
628   EXPECT_TRUE(iter.ReadInt(&out));
629   EXPECT_EQ(2, out);
630
631   EXPECT_FALSE(iter.ReachedEnd());
632   EXPECT_TRUE(iter.ReadInt(&out));
633   EXPECT_EQ(3, out);
634
635   EXPECT_TRUE(iter.ReachedEnd());
636   EXPECT_FALSE(iter.ReadInt(&out));
637   EXPECT_TRUE(iter.ReachedEnd());
638 }
639
640 }  // namespace base