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 // Program to test the SafeBrowsing protocol parsing v2.1. 6 7 #include "base/strings/stringprintf.h" 8 #include "chrome/browser/safe_browsing/protocol_parser.h" 9 #include "chrome/browser/safe_browsing/safe_browsing_util.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 // Test parsing one add chunk. 13 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) { 14 std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999"); 15 add_chunk[13] = '\0'; 16 17 // Run the parse. 18 SafeBrowsingProtocolParser parser; 19 SBChunkList chunks; 20 bool result = parser.ParseChunk( 21 safe_browsing_util::kMalwareList, 22 add_chunk.data(), 23 static_cast<int>(add_chunk.length()), 24 &chunks); 25 EXPECT_TRUE(result); 26 EXPECT_EQ(chunks.size(), 1U); 27 EXPECT_EQ(chunks[0].chunk_number, 1); 28 EXPECT_EQ(chunks[0].hosts.size(), 3U); 29 30 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 31 SBEntry* entry = chunks[0].hosts[0].entry; 32 EXPECT_TRUE(entry->IsAdd()); 33 EXPECT_TRUE(entry->IsPrefix()); 34 EXPECT_EQ(entry->prefix_count(), 0); 35 36 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 37 entry = chunks[0].hosts[1].entry; 38 EXPECT_TRUE(entry->IsAdd()); 39 EXPECT_TRUE(entry->IsPrefix()); 40 EXPECT_EQ(entry->prefix_count(), 3); 41 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 42 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 43 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 44 45 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 46 entry = chunks[0].hosts[2].entry; 47 EXPECT_TRUE(entry->IsAdd()); 48 EXPECT_TRUE(entry->IsPrefix()); 49 EXPECT_EQ(entry->prefix_count(), 2); 50 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 51 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 52 } 53 54 // Test parsing one add chunk with full hashes. 55 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) { 56 std::string add_chunk("a:1:32:69\naaaa"); 57 add_chunk.push_back(2); 58 59 SBFullHash full_hash1, full_hash2; 60 for (int i = 0; i < 32; ++i) { 61 full_hash1.full_hash[i] = i % 2 ? 1 : 2; 62 full_hash2.full_hash[i] = i % 2 ? 3 : 4; 63 } 64 65 add_chunk.append(full_hash1.full_hash, 32); 66 add_chunk.append(full_hash2.full_hash, 32); 67 68 // Run the parse. 69 SafeBrowsingProtocolParser parser; 70 SBChunkList chunks; 71 bool result = parser.ParseChunk( 72 safe_browsing_util::kMalwareList, 73 add_chunk.data(), 74 static_cast<int>(add_chunk.length()), 75 &chunks); 76 EXPECT_TRUE(result); 77 EXPECT_EQ(chunks.size(), 1U); 78 EXPECT_EQ(chunks[0].chunk_number, 1); 79 EXPECT_EQ(chunks[0].hosts.size(), 1U); 80 81 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 82 SBEntry* entry = chunks[0].hosts[0].entry; 83 EXPECT_TRUE(entry->IsAdd()); 84 EXPECT_FALSE(entry->IsPrefix()); 85 EXPECT_EQ(entry->prefix_count(), 2); 86 EXPECT_TRUE(entry->FullHashAt(0) == full_hash1); 87 EXPECT_TRUE(entry->FullHashAt(1) == full_hash2); 88 } 89 90 // Test parsing multiple add chunks. We'll use the same chunk as above, and add 91 // one more after it. 92 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) { 93 std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999" 94 "a:2:4:13\n5555\002ppppgggg"); 95 add_chunk[13] = '\0'; 96 97 // Run the parse. 98 SafeBrowsingProtocolParser parser; 99 SBChunkList chunks; 100 bool result = parser.ParseChunk( 101 safe_browsing_util::kMalwareList, 102 add_chunk.data(), 103 static_cast<int>(add_chunk.length()), 104 &chunks); 105 EXPECT_TRUE(result); 106 EXPECT_EQ(chunks.size(), 2U); 107 EXPECT_EQ(chunks[0].chunk_number, 1); 108 EXPECT_EQ(chunks[0].hosts.size(), 3U); 109 110 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 111 SBEntry* entry = chunks[0].hosts[0].entry; 112 EXPECT_TRUE(entry->IsAdd()); 113 EXPECT_TRUE(entry->IsPrefix()); 114 EXPECT_EQ(entry->prefix_count(), 0); 115 116 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 117 entry = chunks[0].hosts[1].entry; 118 EXPECT_TRUE(entry->IsAdd()); 119 EXPECT_TRUE(entry->IsPrefix()); 120 EXPECT_EQ(entry->prefix_count(), 3); 121 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 122 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 123 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 124 125 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 126 entry = chunks[0].hosts[2].entry; 127 EXPECT_TRUE(entry->IsAdd()); 128 EXPECT_TRUE(entry->IsPrefix()); 129 EXPECT_EQ(entry->prefix_count(), 2); 130 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 131 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 132 133 134 EXPECT_EQ(chunks[1].chunk_number, 2); 135 EXPECT_EQ(chunks[1].hosts.size(), 1U); 136 137 EXPECT_EQ(chunks[1].hosts[0].host, 0x35353535); 138 entry = chunks[1].hosts[0].entry; 139 EXPECT_TRUE(entry->IsAdd()); 140 EXPECT_TRUE(entry->IsPrefix()); 141 EXPECT_EQ(entry->prefix_count(), 2); 142 EXPECT_EQ(entry->PrefixAt(0), 0x70707070); 143 EXPECT_EQ(entry->PrefixAt(1), 0x67676767); 144 } 145 146 // Test parsing one add chunk where a hostkey spans several entries. 147 TEST(SafeBrowsingProtocolParsingTest, TestAddBigChunk) { 148 std::string add_chunk("a:1:4:1050\naaaaX"); 149 add_chunk[add_chunk.size() - 1] |= 0xFF; 150 for (int i = 0; i < 255; ++i) 151 add_chunk.append(base::StringPrintf("%04d", i)); 152 153 add_chunk.append("aaaa"); 154 add_chunk.push_back(5); 155 for (int i = 0; i < 5; ++i) 156 add_chunk.append(base::StringPrintf("001%d", i)); 157 158 SafeBrowsingProtocolParser parser; 159 SBChunkList chunks; 160 bool result = parser.ParseChunk( 161 safe_browsing_util::kMalwareList, 162 add_chunk.data(), 163 static_cast<int>(add_chunk.length()), 164 &chunks); 165 EXPECT_TRUE(result); 166 EXPECT_EQ(chunks.size(), 1U); 167 EXPECT_EQ(chunks[0].chunk_number, 1); 168 169 EXPECT_EQ(chunks[0].hosts.size(), 2U); 170 171 const SBChunkHost& host0 = chunks[0].hosts[0]; 172 EXPECT_EQ(host0.host, 0x61616161); 173 EXPECT_EQ(host0.entry->prefix_count(), 255); 174 175 const SBChunkHost& host1 = chunks[0].hosts[1]; 176 EXPECT_EQ(host1.host, 0x61616161); 177 EXPECT_EQ(host1.entry->prefix_count(), 5); 178 } 179 180 // Test to make sure we could deal with truncated bin hash chunk. 181 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedBinHashChunk) { 182 // This chunk delares there are 4 prefixes but actually only contains 2. 183 const char add_chunk[] = "a:1:4:16\n11112222"; 184 SafeBrowsingProtocolParser parser; 185 SBChunkList chunks; 186 bool result = parser.ParseChunk(safe_browsing_util::kBinHashList, 187 add_chunk, 188 static_cast<int>(sizeof(add_chunk)), 189 &chunks); 190 EXPECT_FALSE(result); 191 EXPECT_EQ(chunks.size(), 0U); 192 } 193 194 // Test to make sure we could deal with truncated malwarelist chunk. 195 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedUrlHashChunk) { 196 // This chunk delares there are 4 prefixes but actually only contains 2. 197 const char add_chunk[] = "a:1:4:21\naaaa\00411112222"; 198 SafeBrowsingProtocolParser parser; 199 SBChunkList chunks; 200 201 // For safe_browsing_util::kMalwareList. 202 bool result = parser.ParseChunk(safe_browsing_util::kMalwareList, 203 add_chunk, 204 static_cast<int>(sizeof(add_chunk)), 205 &chunks); 206 EXPECT_FALSE(result); 207 EXPECT_EQ(chunks.size(), 0U); 208 209 // For safe_browsing_util::kPhishingList. 210 result = parser.ParseChunk(safe_browsing_util::kPhishingList, 211 add_chunk, 212 static_cast<int>(sizeof(add_chunk)), 213 &chunks); 214 EXPECT_FALSE(result); 215 EXPECT_EQ(chunks.size(), 0U); 216 217 // For safe_browsing_util::kBinUrlList. 218 result = parser.ParseChunk(safe_browsing_util::kBinUrlList, 219 add_chunk, 220 static_cast<int>(sizeof(add_chunk)), 221 &chunks); 222 EXPECT_FALSE(result); 223 EXPECT_EQ(chunks.size(), 0U); 224 } 225 226 // Test to verify handling of a truncated chunk header. 227 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedHeader) { 228 std::string truncated_chunks("a:1:4:0\na:"); 229 230 // Run the parser. 231 SafeBrowsingProtocolParser parser; 232 SBChunkList chunks; 233 bool result = parser.ParseChunk( 234 safe_browsing_util::kMalwareList, 235 truncated_chunks.data(), 236 static_cast<int>(truncated_chunks.length()), 237 &chunks); 238 EXPECT_FALSE(result); 239 } 240 241 // Test parsing one sub chunk. 242 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) { 243 std::string sub_chunk("s:9:4:59\naaaaxkkkk1111\003" 244 "zzzz2222zzzz3333zzzz4444" 245 "7777\002yyyy8888yyyy9999"); 246 sub_chunk[13] = '\0'; 247 248 // Run the parse. 249 SafeBrowsingProtocolParser parser; 250 SBChunkList chunks; 251 bool result = parser.ParseChunk( 252 safe_browsing_util::kMalwareList, 253 sub_chunk.data(), 254 static_cast<int>(sub_chunk.length()), 255 &chunks); 256 EXPECT_TRUE(result); 257 EXPECT_EQ(chunks.size(), 1U); 258 EXPECT_EQ(chunks[0].chunk_number, 9); 259 EXPECT_EQ(chunks[0].hosts.size(), 3U); 260 261 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 262 SBEntry* entry = chunks[0].hosts[0].entry; 263 EXPECT_TRUE(entry->IsSub()); 264 EXPECT_TRUE(entry->IsPrefix()); 265 EXPECT_EQ(entry->chunk_id(), 0x6b6b6b6b); 266 EXPECT_EQ(entry->prefix_count(), 0); 267 268 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 269 entry = chunks[0].hosts[1].entry; 270 EXPECT_TRUE(entry->IsSub()); 271 EXPECT_TRUE(entry->IsPrefix()); 272 EXPECT_EQ(entry->prefix_count(), 3); 273 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x7a7a7a7a); 274 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 275 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a); 276 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 277 EXPECT_EQ(entry->ChunkIdAtPrefix(2), 0x7a7a7a7a); 278 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 279 280 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 281 entry = chunks[0].hosts[2].entry; 282 EXPECT_TRUE(entry->IsSub()); 283 EXPECT_TRUE(entry->IsPrefix()); 284 EXPECT_EQ(entry->prefix_count(), 2); 285 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979); 286 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 287 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x79797979); 288 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 289 } 290 291 // Test parsing one sub chunk with full hashes. 292 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) { 293 std::string sub_chunk("s:1:32:77\naaaa"); 294 sub_chunk.push_back(2); 295 296 SBFullHash full_hash1, full_hash2; 297 for (int i = 0; i < 32; ++i) { 298 full_hash1.full_hash[i] = i % 2 ? 1 : 2; 299 full_hash2.full_hash[i] = i % 2 ? 3 : 4; 300 } 301 302 sub_chunk.append("yyyy"); 303 sub_chunk.append(full_hash1.full_hash, 32); 304 sub_chunk.append("zzzz"); 305 sub_chunk.append(full_hash2.full_hash, 32); 306 307 // Run the parse. 308 SafeBrowsingProtocolParser parser; 309 SBChunkList chunks; 310 bool result = parser.ParseChunk( 311 safe_browsing_util::kMalwareList, 312 sub_chunk.data(), 313 static_cast<int>(sub_chunk.length()), 314 &chunks); 315 EXPECT_TRUE(result); 316 EXPECT_EQ(chunks.size(), 1U); 317 EXPECT_EQ(chunks[0].chunk_number, 1); 318 EXPECT_EQ(chunks[0].hosts.size(), 1U); 319 320 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 321 SBEntry* entry = chunks[0].hosts[0].entry; 322 EXPECT_TRUE(entry->IsSub()); 323 EXPECT_FALSE(entry->IsPrefix()); 324 EXPECT_EQ(entry->prefix_count(), 2); 325 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979); 326 EXPECT_TRUE(entry->FullHashAt(0) == full_hash1); 327 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a); 328 EXPECT_TRUE(entry->FullHashAt(1) == full_hash2); 329 } 330 331 // Test parsing the SafeBrowsing update response. 332 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) { 333 std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n" 334 "i:malware\nsd:21-27,42,171717\n"); 335 336 SafeBrowsingProtocolParser parser; 337 int next_query_sec = 0; 338 bool reset = false; 339 std::vector<SBChunkDelete> deletes; 340 std::vector<ChunkUrl> urls; 341 EXPECT_TRUE(parser.ParseUpdate(add_del.data(), 342 static_cast<int>(add_del.length()), 343 &next_query_sec, &reset, &deletes, &urls)); 344 345 EXPECT_TRUE(urls.empty()); 346 EXPECT_FALSE(reset); 347 EXPECT_EQ(next_query_sec, 1700); 348 EXPECT_EQ(deletes.size(), 2U); 349 350 EXPECT_EQ(deletes[0].chunk_del.size(), 4U); 351 EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7)); 352 EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597)); 353 EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444)); 354 EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999)); 355 356 EXPECT_EQ(deletes[1].chunk_del.size(), 3U); 357 EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27)); 358 EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42)); 359 EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717)); 360 361 // An update response with missing list name. 362 363 next_query_sec = 0; 364 deletes.clear(); 365 urls.clear(); 366 add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n"; 367 EXPECT_FALSE(parser.ParseUpdate(add_del.data(), 368 static_cast<int>(add_del.length()), 369 &next_query_sec, &reset, &deletes, &urls)); 370 } 371 372 // Test parsing the SafeBrowsing update response. 373 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) { 374 std::string redirects("i:goog-malware-shavar\n" 375 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n" 376 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n" 377 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n" 378 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 379 "8691-8731,8733-8786\n"); 380 381 SafeBrowsingProtocolParser parser; 382 int next_query_sec = 0; 383 bool reset = false; 384 std::vector<SBChunkDelete> deletes; 385 std::vector<ChunkUrl> urls; 386 EXPECT_TRUE(parser.ParseUpdate(redirects.data(), 387 static_cast<int>(redirects.length()), 388 &next_query_sec, &reset, &deletes, &urls)); 389 390 EXPECT_FALSE(reset); 391 EXPECT_EQ(urls.size(), 4U); 392 EXPECT_EQ(urls[0].url, 393 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1"); 394 EXPECT_EQ(urls[1].url, 395 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2"); 396 EXPECT_EQ(urls[2].url, 397 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3"); 398 EXPECT_EQ(urls[3].url, 399 "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 400 "8691-8731,8733-8786"); 401 EXPECT_EQ(next_query_sec, 0); 402 EXPECT_TRUE(deletes.empty()); 403 } 404 405 // Test parsing various SafeBrowsing protocol headers. 406 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) { 407 std::string headers("n:1800\ni:goog-white-shavar\n"); 408 SafeBrowsingProtocolParser parser; 409 int next_query_sec = 0; 410 bool reset = false; 411 std::vector<SBChunkDelete> deletes; 412 std::vector<ChunkUrl> urls; 413 EXPECT_TRUE(parser.ParseUpdate(headers.data(), 414 static_cast<int>(headers.length()), 415 &next_query_sec, &reset, &deletes, &urls)); 416 417 EXPECT_EQ(next_query_sec, 1800); 418 EXPECT_FALSE(reset); 419 EXPECT_TRUE(deletes.empty()); 420 EXPECT_TRUE(urls.empty()); 421 } 422 423 // Test parsing data from a GetHashRequest 424 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) { 425 std::string get_hash("goog-phish-shavar:19:96\n" 426 "00112233445566778899aabbccddeeff" 427 "00001111222233334444555566667777" 428 "ffffeeeeddddccccbbbbaaaa99998888"); 429 std::vector<SBFullHashResult> full_hashes; 430 SafeBrowsingProtocolParser parser; 431 EXPECT_TRUE(parser.ParseGetHash(get_hash.data(), 432 static_cast<int>(get_hash.length()), 433 &full_hashes)); 434 435 EXPECT_EQ(full_hashes.size(), 3U); 436 EXPECT_EQ(memcmp(&full_hashes[0].hash, 437 "00112233445566778899aabbccddeeff", 438 sizeof(SBFullHash)), 0); 439 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 440 EXPECT_EQ(memcmp(&full_hashes[1].hash, 441 "00001111222233334444555566667777", 442 sizeof(SBFullHash)), 0); 443 EXPECT_EQ(full_hashes[1].list_name, "goog-phish-shavar"); 444 EXPECT_EQ(memcmp(&full_hashes[2].hash, 445 "ffffeeeeddddccccbbbbaaaa99998888", 446 sizeof(SBFullHash)), 0); 447 EXPECT_EQ(full_hashes[2].list_name, "goog-phish-shavar"); 448 449 // Test multiple lists in the GetHash results. 450 std::string get_hash2("goog-phish-shavar:19:32\n" 451 "00112233445566778899aabbccddeeff" 452 "goog-malware-shavar:19:64\n" 453 "cafebeefcafebeefdeaddeaddeaddead" 454 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"); 455 EXPECT_TRUE(parser.ParseGetHash(get_hash2.data(), 456 static_cast<int>(get_hash2.length()), 457 &full_hashes)); 458 459 EXPECT_EQ(full_hashes.size(), 3U); 460 EXPECT_EQ(memcmp(&full_hashes[0].hash, 461 "00112233445566778899aabbccddeeff", 462 sizeof(SBFullHash)), 0); 463 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 464 EXPECT_EQ(memcmp(&full_hashes[1].hash, 465 "cafebeefcafebeefdeaddeaddeaddead", 466 sizeof(SBFullHash)), 0); 467 EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar"); 468 EXPECT_EQ(memcmp(&full_hashes[2].hash, 469 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", 470 sizeof(SBFullHash)), 0); 471 EXPECT_EQ(full_hashes[2].list_name, "goog-malware-shavar"); 472 } 473 474 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) { 475 std::string hash_response = "goog-phish-shavar:1:32\n" 476 "12345678901234567890123456789012" 477 "googpub-phish-shavar:19:32\n" 478 "09876543210987654321098765432109"; 479 std::vector<SBFullHashResult> full_hashes; 480 SafeBrowsingProtocolParser parser; 481 EXPECT_TRUE(parser.ParseGetHash(hash_response.data(), 482 hash_response.size(), 483 &full_hashes)); 484 485 EXPECT_EQ(full_hashes.size(), 1U); 486 EXPECT_EQ(memcmp("12345678901234567890123456789012", 487 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 488 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 489 EXPECT_EQ(full_hashes[0].add_chunk_id, 1); 490 491 hash_response += "goog-malware-shavar:7:32\n" 492 "abcdefghijklmnopqrstuvwxyz123457"; 493 full_hashes.clear(); 494 EXPECT_TRUE(parser.ParseGetHash(hash_response.data(), 495 hash_response.size(), 496 &full_hashes)); 497 498 EXPECT_EQ(full_hashes.size(), 2U); 499 EXPECT_EQ(memcmp("12345678901234567890123456789012", 500 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 501 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 502 EXPECT_EQ(full_hashes[0].add_chunk_id, 1); 503 EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457", 504 &full_hashes[1].hash, sizeof(SBFullHash)), 0); 505 EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar"); 506 EXPECT_EQ(full_hashes[1].add_chunk_id, 7); 507 } 508 509 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) { 510 SafeBrowsingProtocolParser parser; 511 std::vector<SBPrefix> prefixes; 512 std::string get_hash; 513 514 prefixes.push_back(0x34333231); 515 prefixes.push_back(0x64636261); 516 prefixes.push_back(0x73727170); 517 518 parser.FormatGetHash(prefixes, &get_hash); 519 EXPECT_EQ(get_hash, "4:12\n1234abcdpqrs"); 520 } 521 522 TEST(SafeBrowsingProtocolParsingTest, TestReset) { 523 SafeBrowsingProtocolParser parser; 524 std::string update("n:1800\ni:phishy\nr:pleasereset\n"); 525 526 bool reset = false; 527 int next_update = -1; 528 std::vector<SBChunkDelete> deletes; 529 std::vector<ChunkUrl> urls; 530 EXPECT_TRUE(parser.ParseUpdate(update.data(), 531 static_cast<int>(update.size()), 532 &next_update, &reset, &deletes, &urls)); 533 EXPECT_TRUE(reset); 534 } 535 536 // The SafeBrowsing service will occasionally send zero length chunks so that 537 // client requests will have longer contiguous chunk number ranges, and thus 538 // reduce the request size. 539 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) { 540 std::string add_chunk("a:1:4:0\n"); 541 SafeBrowsingProtocolParser parser; 542 SBChunkList chunks; 543 544 bool result = parser.ParseChunk( 545 safe_browsing_util::kMalwareList, 546 add_chunk.data(), 547 static_cast<int>(add_chunk.length()), 548 &chunks); 549 EXPECT_TRUE(result); 550 EXPECT_EQ(chunks.size(), 1U); 551 EXPECT_EQ(chunks[0].chunk_number, 1); 552 EXPECT_EQ(chunks[0].hosts.size(), 0U); 553 554 // Now test a zero size chunk in between normal chunks. 555 chunks.clear(); 556 std::string add_chunks("a:1:4:18\n1234\001abcd5678\001wxyz" 557 "a:2:4:0\n" 558 "a:3:4:9\ncafe\001beef"); 559 result = parser.ParseChunk( 560 safe_browsing_util::kMalwareList, 561 add_chunks.data(), 562 static_cast<int>(add_chunks.length()), 563 &chunks); 564 EXPECT_TRUE(result); 565 EXPECT_EQ(chunks.size(), 3U); 566 567 // See that each chunk has the right content. 568 EXPECT_EQ(chunks[0].chunk_number, 1); 569 EXPECT_EQ(chunks[0].hosts.size(), 2U); 570 EXPECT_EQ(chunks[0].hosts[0].host, 0x34333231); 571 EXPECT_EQ(chunks[0].hosts[0].entry->PrefixAt(0), 0x64636261); 572 EXPECT_EQ(chunks[0].hosts[1].host, 0x38373635); 573 EXPECT_EQ(chunks[0].hosts[1].entry->PrefixAt(0), 0x7a797877); 574 575 EXPECT_EQ(chunks[1].chunk_number, 2); 576 EXPECT_EQ(chunks[1].hosts.size(), 0U); 577 578 EXPECT_EQ(chunks[2].chunk_number, 3); 579 EXPECT_EQ(chunks[2].hosts.size(), 1U); 580 EXPECT_EQ(chunks[2].hosts[0].host, 0x65666163); 581 EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x66656562); 582 } 583 584 // Test parsing a zero sized sub chunk. 585 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) { 586 std::string sub_chunk("s:9:4:0\n"); 587 SafeBrowsingProtocolParser parser; 588 SBChunkList chunks; 589 590 bool result = parser.ParseChunk( 591 safe_browsing_util::kMalwareList, 592 sub_chunk.data(), 593 static_cast<int>(sub_chunk.length()), 594 &chunks); 595 EXPECT_TRUE(result); 596 EXPECT_EQ(chunks.size(), 1U); 597 EXPECT_EQ(chunks[0].chunk_number, 9); 598 EXPECT_EQ(chunks[0].hosts.size(), 0U); 599 chunks.clear(); 600 601 // Test parsing a zero sized sub chunk mixed in with content carrying chunks. 602 std::string sub_chunks("s:1:4:9\nabcdxwxyz" 603 "s:2:4:0\n" 604 "s:3:4:26\nefgh\0011234pqrscafe\0015678lmno"); 605 sub_chunks[12] = '\0'; 606 607 result = parser.ParseChunk( 608 safe_browsing_util::kMalwareList, 609 sub_chunks.data(), 610 static_cast<int>(sub_chunks.length()), 611 &chunks); 612 EXPECT_TRUE(result); 613 614 EXPECT_EQ(chunks[0].chunk_number, 1); 615 EXPECT_EQ(chunks[0].hosts.size(), 1U); 616 EXPECT_EQ(chunks[0].hosts[0].host, 0x64636261); 617 EXPECT_EQ(chunks[0].hosts[0].entry->prefix_count(), 0); 618 619 EXPECT_EQ(chunks[1].chunk_number, 2); 620 EXPECT_EQ(chunks[1].hosts.size(), 0U); 621 622 EXPECT_EQ(chunks[2].chunk_number, 3); 623 EXPECT_EQ(chunks[2].hosts.size(), 2U); 624 EXPECT_EQ(chunks[2].hosts[0].host, 0x68676665); 625 EXPECT_EQ(chunks[2].hosts[0].entry->prefix_count(), 1); 626 EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x73727170); 627 EXPECT_EQ(chunks[2].hosts[0].entry->ChunkIdAtPrefix(0), 0x31323334); 628 EXPECT_EQ(chunks[2].hosts[1].host, 0x65666163); 629 EXPECT_EQ(chunks[2].hosts[1].entry->prefix_count(), 1); 630 EXPECT_EQ(chunks[2].hosts[1].entry->PrefixAt(0), 0x6f6e6d6c); 631 EXPECT_EQ(chunks[2].hosts[1].entry->ChunkIdAtPrefix(0), 0x35363738); 632 } 633 634 TEST(SafeBrowsingProtocolParsingTest, TestAddBinHashChunks) { 635 std::string add_chunk("a:1:4:16\naaaabbbbccccdddd" 636 "a:2:4:8\n11112222"); 637 // Run the parse. 638 SafeBrowsingProtocolParser parser; 639 SBChunkList chunks; 640 bool result = parser.ParseChunk( 641 safe_browsing_util::kBinHashList, 642 add_chunk.data(), 643 static_cast<int>(add_chunk.length()), 644 &chunks); 645 EXPECT_TRUE(result); 646 EXPECT_EQ(chunks.size(), 2U); 647 EXPECT_EQ(chunks[0].chunk_number, 1); 648 EXPECT_EQ(chunks[0].hosts.size(), 1U); 649 650 EXPECT_EQ(chunks[0].hosts[0].host, 0); 651 SBEntry* entry = chunks[0].hosts[0].entry; 652 EXPECT_TRUE(entry->IsAdd()); 653 EXPECT_TRUE(entry->IsPrefix()); 654 EXPECT_EQ(entry->prefix_count(), 4); 655 656 EXPECT_EQ(chunks[1].chunk_number, 2); 657 EXPECT_EQ(chunks[1].hosts.size(), 1U); 658 659 EXPECT_EQ(chunks[1].hosts[0].host, 0); 660 entry = chunks[1].hosts[0].entry; 661 EXPECT_TRUE(entry->IsAdd()); 662 EXPECT_TRUE(entry->IsPrefix()); 663 EXPECT_EQ(entry->prefix_count(), 2); 664 EXPECT_EQ(entry->PrefixAt(0), 0x31313131); 665 EXPECT_EQ(entry->PrefixAt(1), 0x32323232); 666 } 667 668 // Test parsing one add chunk where a hostkey spans several entries. 669 TEST(SafeBrowsingProtocolParsingTest, TestAddBigBinHashChunk) { 670 std::string add_chunk("a:1:4:1028\n"); 671 for (int i = 0; i < 257; ++i) 672 add_chunk.append(base::StringPrintf("%04d", i)); 673 674 SafeBrowsingProtocolParser parser; 675 SBChunkList chunks; 676 bool result = parser.ParseChunk( 677 safe_browsing_util::kBinHashList, 678 add_chunk.data(), 679 static_cast<int>(add_chunk.length()), 680 &chunks); 681 EXPECT_TRUE(result); 682 EXPECT_EQ(chunks.size(), 1U); 683 EXPECT_EQ(chunks[0].chunk_number, 1); 684 685 EXPECT_EQ(chunks[0].hosts.size(), 1U); 686 687 const SBChunkHost& host0 = chunks[0].hosts[0]; 688 EXPECT_EQ(host0.host, 0); 689 EXPECT_EQ(host0.entry->prefix_count(), 257); 690 } 691 692 // Test parsing one sub chunk. 693 TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) { 694 std::string sub_chunk("s:9:4:16\n1111mmmm2222nnnn"); 695 696 // Run the parser. 697 SafeBrowsingProtocolParser parser; 698 SBChunkList chunks; 699 bool result = parser.ParseChunk( 700 safe_browsing_util::kBinHashList, 701 sub_chunk.data(), 702 static_cast<int>(sub_chunk.length()), 703 &chunks); 704 EXPECT_TRUE(result); 705 EXPECT_EQ(chunks.size(), 1U); 706 EXPECT_EQ(chunks[0].chunk_number, 9); 707 EXPECT_EQ(chunks[0].hosts.size(), 1U); 708 709 EXPECT_EQ(chunks[0].hosts[0].host, 0); 710 SBEntry* entry = chunks[0].hosts[0].entry; 711 EXPECT_TRUE(entry->IsSub()); 712 EXPECT_TRUE(entry->IsPrefix()); 713 EXPECT_EQ(entry->prefix_count(), 2); 714 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131); 715 EXPECT_EQ(entry->PrefixAt(0), 0x6d6d6d6d); 716 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232); 717 EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e); 718 } 719 720 TEST(SafeBrowsingProtocolParsingTest, TestAddDownloadWhitelistChunk) { 721 std::string add_chunk("a:1:32:32\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 722 "a:2:32:64\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" 723 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); 724 // Run the parse. 725 SafeBrowsingProtocolParser parser; 726 SBChunkList chunks; 727 bool result = parser.ParseChunk( 728 safe_browsing_util::kDownloadWhiteList, 729 add_chunk.data(), 730 static_cast<int>(add_chunk.length()), 731 &chunks); 732 EXPECT_TRUE(result); 733 EXPECT_EQ(chunks.size(), 2U); 734 EXPECT_EQ(chunks[0].chunk_number, 1); 735 EXPECT_EQ(chunks[0].hosts.size(), 1U); 736 EXPECT_EQ(chunks[0].hosts[0].host, 0); 737 SBEntry* entry = chunks[0].hosts[0].entry; 738 EXPECT_TRUE(entry->IsAdd()); 739 EXPECT_FALSE(entry->IsPrefix()); 740 EXPECT_EQ(entry->prefix_count(), 1); 741 SBFullHash full; 742 memcpy(full.full_hash, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 32); 743 EXPECT_TRUE(entry->FullHashAt(0) == full); 744 745 EXPECT_EQ(chunks[1].chunk_number, 2); 746 EXPECT_EQ(chunks[1].hosts.size(), 1U); 747 EXPECT_EQ(chunks[1].hosts[0].host, 0); 748 entry = chunks[1].hosts[0].entry; 749 EXPECT_TRUE(entry->IsAdd()); 750 EXPECT_FALSE(entry->IsPrefix()); 751 EXPECT_EQ(entry->prefix_count(), 2); 752 memcpy(full.full_hash, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", 32); 753 EXPECT_TRUE(entry->FullHashAt(0) == full); 754 memcpy(full.full_hash, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 32); 755 EXPECT_TRUE(entry->FullHashAt(1) == full); 756 } 757 758 // Test parsing one sub chunk. 759 TEST(SafeBrowsingProtocolParsingTest, TestSubDownloadWhitelistChunk) { 760 std::string sub_chunk("s:1:32:36\n1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 761 762 // Run the parser. 763 SafeBrowsingProtocolParser parser; 764 SBChunkList chunks; 765 bool result = parser.ParseChunk( 766 safe_browsing_util::kDownloadWhiteList, 767 sub_chunk.data(), 768 static_cast<int>(sub_chunk.length()), 769 &chunks); 770 ASSERT_TRUE(result); 771 ASSERT_EQ(chunks.size(), 1U); 772 EXPECT_EQ(chunks[0].chunk_number, 1); 773 EXPECT_EQ(chunks[0].hosts.size(), 1U); 774 775 EXPECT_EQ(chunks[0].hosts[0].host, 0); 776 SBEntry* entry = chunks[0].hosts[0].entry; 777 EXPECT_TRUE(entry->IsSub()); 778 ASSERT_FALSE(entry->IsPrefix()); 779 ASSERT_EQ(entry->prefix_count(), 1); 780 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131); 781 SBFullHash full; 782 memcpy(full.full_hash, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 32); 783 EXPECT_TRUE(entry->FullHashAt(0) == full); 784 } 785