Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      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 <string>
      6 
      7 #include "base/basictypes.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/pickle.h"
     10 #include "base/strings/string16.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 // Remove when this file is in the base namespace.
     14 using base::string16;
     15 
     16 namespace {
     17 
     18 const int testint = 2093847192;
     19 const std::string teststr("Hello world");  // note non-aligned string length
     20 const std::wstring testwstr(L"Hello, world");
     21 const char testdata[] = "AAA\0BBB\0";
     22 const int testdatalen = arraysize(testdata) - 1;
     23 const bool testbool1 = false;
     24 const bool testbool2 = true;
     25 const uint16 testuint16 = 32123;
     26 const float testfloat = 3.1415926935f;
     27 
     28 // checks that the result
     29 void VerifyResult(const Pickle& pickle) {
     30   PickleIterator iter(pickle);
     31 
     32   int outint;
     33   EXPECT_TRUE(pickle.ReadInt(&iter, &outint));
     34   EXPECT_EQ(testint, outint);
     35 
     36   std::string outstr;
     37   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
     38   EXPECT_EQ(teststr, outstr);
     39 
     40   std::wstring outwstr;
     41   EXPECT_TRUE(pickle.ReadWString(&iter, &outwstr));
     42   EXPECT_EQ(testwstr, outwstr);
     43 
     44   bool outbool;
     45   EXPECT_TRUE(pickle.ReadBool(&iter, &outbool));
     46   EXPECT_FALSE(outbool);
     47   EXPECT_TRUE(pickle.ReadBool(&iter, &outbool));
     48   EXPECT_TRUE(outbool);
     49 
     50   uint16 outuint16;
     51   EXPECT_TRUE(pickle.ReadUInt16(&iter, &outuint16));
     52   EXPECT_EQ(testuint16, outuint16);
     53 
     54   float outfloat;
     55   EXPECT_TRUE(pickle.ReadFloat(&iter, &outfloat));
     56   EXPECT_EQ(testfloat, outfloat);
     57 
     58   const char* outdata;
     59   int outdatalen;
     60   EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen));
     61   EXPECT_EQ(testdatalen, outdatalen);
     62   EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
     63 
     64   // reads past the end should fail
     65   EXPECT_FALSE(pickle.ReadInt(&iter, &outint));
     66 }
     67 
     68 }  // namespace
     69 
     70 TEST(PickleTest, EncodeDecode) {
     71   Pickle pickle;
     72 
     73   EXPECT_TRUE(pickle.WriteInt(testint));
     74   EXPECT_TRUE(pickle.WriteString(teststr));
     75   EXPECT_TRUE(pickle.WriteWString(testwstr));
     76   EXPECT_TRUE(pickle.WriteBool(testbool1));
     77   EXPECT_TRUE(pickle.WriteBool(testbool2));
     78   EXPECT_TRUE(pickle.WriteUInt16(testuint16));
     79   EXPECT_TRUE(pickle.WriteFloat(testfloat));
     80   EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
     81   VerifyResult(pickle);
     82 
     83   // test copy constructor
     84   Pickle pickle2(pickle);
     85   VerifyResult(pickle2);
     86 
     87   // test operator=
     88   Pickle pickle3;
     89   pickle3 = pickle;
     90   VerifyResult(pickle3);
     91 }
     92 
     93 // Tests that we can handle really small buffers.
     94 TEST(PickleTest, SmallBuffer) {
     95   scoped_ptr<char[]> buffer(new char[1]);
     96 
     97   // We should not touch the buffer.
     98   Pickle pickle(buffer.get(), 1);
     99 
    100   PickleIterator iter(pickle);
    101   int data;
    102   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
    103 }
    104 
    105 // Tests that we can handle improper headers.
    106 TEST(PickleTest, BigSize) {
    107   int buffer[] = { 0x56035200, 25, 40, 50 };
    108 
    109   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
    110 
    111   PickleIterator iter(pickle);
    112   int data;
    113   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
    114 }
    115 
    116 TEST(PickleTest, UnalignedSize) {
    117   int buffer[] = { 10, 25, 40, 50 };
    118 
    119   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
    120 
    121   PickleIterator iter(pickle);
    122   int data;
    123   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
    124 }
    125 
    126 TEST(PickleTest, ZeroLenStr) {
    127   Pickle pickle;
    128   EXPECT_TRUE(pickle.WriteString(std::string()));
    129 
    130   PickleIterator iter(pickle);
    131   std::string outstr;
    132   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
    133   EXPECT_EQ("", outstr);
    134 }
    135 
    136 TEST(PickleTest, ZeroLenWStr) {
    137   Pickle pickle;
    138   EXPECT_TRUE(pickle.WriteWString(std::wstring()));
    139 
    140   PickleIterator iter(pickle);
    141   std::string outstr;
    142   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
    143   EXPECT_EQ("", outstr);
    144 }
    145 
    146 TEST(PickleTest, BadLenStr) {
    147   Pickle pickle;
    148   EXPECT_TRUE(pickle.WriteInt(-2));
    149 
    150   PickleIterator iter(pickle);
    151   std::string outstr;
    152   EXPECT_FALSE(pickle.ReadString(&iter, &outstr));
    153 }
    154 
    155 TEST(PickleTest, BadLenWStr) {
    156   Pickle pickle;
    157   EXPECT_TRUE(pickle.WriteInt(-1));
    158 
    159   PickleIterator iter(pickle);
    160   std::wstring woutstr;
    161   EXPECT_FALSE(pickle.ReadWString(&iter, &woutstr));
    162 }
    163 
    164 TEST(PickleTest, FindNext) {
    165   Pickle pickle;
    166   EXPECT_TRUE(pickle.WriteInt(1));
    167   EXPECT_TRUE(pickle.WriteString("Domo"));
    168 
    169   const char* start = reinterpret_cast<const char*>(pickle.data());
    170   const char* end = start + pickle.size();
    171 
    172   EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end));
    173   EXPECT_TRUE(NULL == Pickle::FindNext(pickle.header_size_, start, end - 1));
    174   EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
    175 }
    176 
    177 TEST(PickleTest, FindNextWithIncompleteHeader) {
    178   size_t header_size = sizeof(Pickle::Header);
    179   scoped_ptr<char[]> buffer(new char[header_size - 1]);
    180   memset(buffer.get(), 0x1, header_size - 1);
    181 
    182   const char* start = buffer.get();
    183   const char* end = start + header_size - 1;
    184 
    185   EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
    186 }
    187 
    188 #if defined(COMPILER_MSVC)
    189 #pragma warning(push)
    190 #pragma warning(disable: 4146)
    191 #endif
    192 TEST(PickleTest, FindNextOverflow) {
    193   size_t header_size = sizeof(Pickle::Header);
    194   size_t header_size2 = 2 * header_size;
    195   size_t payload_received = 100;
    196   scoped_ptr<char[]> buffer(new char[header_size2 + payload_received]);
    197   const char* start = buffer.get();
    198   Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
    199   const char* end = start + header_size2 + payload_received;
    200   // It is impossible to construct an overflow test otherwise.
    201   if (sizeof(size_t) > sizeof(header->payload_size) ||
    202       sizeof(uintptr_t) > sizeof(header->payload_size))
    203     return;
    204 
    205   header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
    206   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
    207 
    208   header->payload_size = -header_size2;
    209   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
    210 
    211   header->payload_size = 0;
    212   end = start + header_size;
    213   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
    214 }
    215 #if defined(COMPILER_MSVC)
    216 #pragma warning(pop)
    217 #endif
    218 
    219 TEST(PickleTest, GetReadPointerAndAdvance) {
    220   Pickle pickle;
    221 
    222   PickleIterator iter(pickle);
    223   EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
    224 
    225   EXPECT_TRUE(pickle.WriteInt(1));
    226   EXPECT_TRUE(pickle.WriteInt(2));
    227   int bytes = sizeof(int) * 2;
    228 
    229   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
    230   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
    231   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
    232   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
    233   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
    234   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
    235   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
    236 }
    237 
    238 TEST(PickleTest, Resize) {
    239   size_t unit = Pickle::kPayloadUnit;
    240   scoped_ptr<char[]> data(new char[unit]);
    241   char* data_ptr = data.get();
    242   for (size_t i = 0; i < unit; i++)
    243     data_ptr[i] = 'G';
    244 
    245   // construct a message that will be exactly the size of one payload unit,
    246   // note that any data will have a 4-byte header indicating the size
    247   const size_t payload_size_after_header = unit - sizeof(uint32);
    248   Pickle pickle;
    249   pickle.WriteData(data_ptr,
    250       static_cast<int>(payload_size_after_header - sizeof(uint32)));
    251   size_t cur_payload = payload_size_after_header;
    252 
    253   // note: we assume 'unit' is a power of 2
    254   EXPECT_EQ(unit, pickle.capacity_after_header());
    255   EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
    256 
    257   // fill out a full page (noting data header)
    258   pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32)));
    259   cur_payload += unit;
    260   EXPECT_EQ(unit * 2, pickle.capacity_after_header());
    261   EXPECT_EQ(cur_payload, pickle.payload_size());
    262 
    263   // one more byte should double the capacity
    264   pickle.WriteData(data_ptr, 1);
    265   cur_payload += 8;
    266   EXPECT_EQ(unit * 4, pickle.capacity_after_header());
    267   EXPECT_EQ(cur_payload, pickle.payload_size());
    268 }
    269 
    270 namespace {
    271 
    272 struct CustomHeader : Pickle::Header {
    273   int blah;
    274 };
    275 
    276 }  // namespace
    277 
    278 TEST(PickleTest, HeaderPadding) {
    279   const uint32 kMagic = 0x12345678;
    280 
    281   Pickle pickle(sizeof(CustomHeader));
    282   pickle.WriteInt(kMagic);
    283 
    284   // this should not overwrite the 'int' payload
    285   pickle.headerT<CustomHeader>()->blah = 10;
    286 
    287   PickleIterator iter(pickle);
    288   int result;
    289   ASSERT_TRUE(pickle.ReadInt(&iter, &result));
    290 
    291   EXPECT_EQ(static_cast<uint32>(result), kMagic);
    292 }
    293 
    294 TEST(PickleTest, EqualsOperator) {
    295   Pickle source;
    296   source.WriteInt(1);
    297 
    298   Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
    299                                  source.size());
    300   Pickle copy;
    301   copy = copy_refs_source_buffer;
    302   ASSERT_EQ(source.size(), copy.size());
    303 }
    304 
    305 TEST(PickleTest, EvilLengths) {
    306   Pickle source;
    307   std::string str(100000, 'A');
    308   EXPECT_TRUE(source.WriteData(str.c_str(), 100000));
    309   // ReadString16 used to have its read buffer length calculation wrong leading
    310   // to out-of-bounds reading.
    311   PickleIterator iter(source);
    312   string16 str16;
    313   EXPECT_FALSE(source.ReadString16(&iter, &str16));
    314 
    315   // And check we didn't break ReadString16.
    316   str16 = (wchar_t) 'A';
    317   Pickle str16_pickle;
    318   EXPECT_TRUE(str16_pickle.WriteString16(str16));
    319   iter = PickleIterator(str16_pickle);
    320   EXPECT_TRUE(str16_pickle.ReadString16(&iter, &str16));
    321   EXPECT_EQ(1U, str16.length());
    322 
    323   // Check we don't fail in a length check with invalid String16 size.
    324   // (1<<31) * sizeof(char16) == 0, so this is particularly evil.
    325   Pickle bad_len;
    326   EXPECT_TRUE(bad_len.WriteInt(1 << 31));
    327   iter = PickleIterator(bad_len);
    328   EXPECT_FALSE(bad_len.ReadString16(&iter, &str16));
    329 
    330   // Check we don't fail in a length check with large WStrings.
    331   Pickle big_len;
    332   EXPECT_TRUE(big_len.WriteInt(1 << 30));
    333   iter = PickleIterator(big_len);
    334   std::wstring wstr;
    335   EXPECT_FALSE(big_len.ReadWString(&iter, &wstr));
    336 }
    337 
    338 // Check we can write zero bytes of data and 'data' can be NULL.
    339 TEST(PickleTest, ZeroLength) {
    340   Pickle pickle;
    341   EXPECT_TRUE(pickle.WriteData(NULL, 0));
    342 
    343   PickleIterator iter(pickle);
    344   const char* outdata;
    345   int outdatalen;
    346   EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen));
    347   EXPECT_EQ(0, outdatalen);
    348   // We can't assert that outdata is NULL.
    349 }
    350 
    351 // Check that ReadBytes works properly with an iterator initialized to NULL.
    352 TEST(PickleTest, ReadBytes) {
    353   Pickle pickle;
    354   int data = 0x7abcd;
    355   EXPECT_TRUE(pickle.WriteBytes(&data, sizeof(data)));
    356 
    357   PickleIterator iter(pickle);
    358   const char* outdata_char = NULL;
    359   EXPECT_TRUE(pickle.ReadBytes(&iter, &outdata_char, sizeof(data)));
    360 
    361   int outdata;
    362   memcpy(&outdata, outdata_char, sizeof(outdata));
    363   EXPECT_EQ(data, outdata);
    364 }
    365