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 += 5; 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