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