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