Home | History | Annotate | Download | only in safe_browsing
      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/time/time.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   const char kRawAddChunk[] = {
     15     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
     16     '\x08',                    // field 1, wire format varint
     17     '\x01',                    // chunk_number varint 1
     18     '\x22',                    // field 4, wire format length-delimited
     19     '\x18',                    // varint length 24
     20     '1', '1', '1', '1',        // 4-byte prefixes
     21     '2', '2', '2', '2',
     22     '3', '3', '3', '3',
     23     '4', '4', '4', '4',
     24     '8', '8', '8', '8',
     25     '9', '9', '9', '9',
     26   };
     27 
     28   ScopedVector<SBChunkData> chunks;
     29   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
     30                                         &chunks));
     31   ASSERT_EQ(1U, chunks.size());
     32   EXPECT_EQ(1, chunks[0]->ChunkNumber());
     33   EXPECT_TRUE(chunks[0]->IsAdd());
     34   EXPECT_FALSE(chunks[0]->IsSub());
     35   EXPECT_TRUE(chunks[0]->IsPrefix());
     36   EXPECT_FALSE(chunks[0]->IsFullHash());
     37   ASSERT_EQ(6U, chunks[0]->PrefixCount());
     38   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
     39   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
     40   EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2));  // 3333
     41   EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3));  // 4444
     42   EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4));  // 8888
     43   EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5));  // 9999
     44 }
     45 
     46 // Test parsing one add chunk with full hashes.
     47 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) {
     48   const char kRawAddChunk[] = {
     49     '\0', '\0', '\0', '\x46',  // 32-bit payload length in network byte order.
     50     '\x08',                    // field 1, wire format varint
     51     '\x01',                    // chunk_number varint 1
     52     '\x18',                    // field 3, wire format varint
     53     '\x01',                    // enum PrefixType == FULL_32B
     54     '\x22',                    // field 4, wire format length-delimited
     55     '\x40',                    // varint length 64 (2 full hashes)
     56 
     57     '0', '1', '0', '1', '0', '1', '0', '1',
     58     '0', '1', '0', '1', '0', '1', '0', '1',
     59     '0', '1', '0', '1', '0', '1', '0', '1',
     60     '0', '1', '0', '1', '0', '1', '0', '1',
     61 
     62     '2', '3', '2', '3', '2', '3', '2', '3',
     63     '2', '3', '2', '3', '2', '3', '2', '3',
     64     '2', '3', '2', '3', '2', '3', '2', '3',
     65     '2', '3', '2', '3', '2', '3', '2', '3',
     66   };
     67 
     68   SBFullHash full_hash1, full_hash2;
     69   for (int i = 0; i < 32; ++i) {
     70     full_hash1.full_hash[i] = i % 2 ? '1' : '0';
     71     full_hash2.full_hash[i] = i % 2 ? '3' : '2';
     72   }
     73 
     74   ScopedVector<SBChunkData> chunks;
     75   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
     76                                         &chunks));
     77   ASSERT_EQ(1U, chunks.size());
     78   EXPECT_EQ(1, chunks[0]->ChunkNumber());
     79   EXPECT_TRUE(chunks[0]->IsAdd());
     80   EXPECT_FALSE(chunks[0]->IsSub());
     81   EXPECT_FALSE(chunks[0]->IsPrefix());
     82   EXPECT_TRUE(chunks[0]->IsFullHash());
     83 
     84   ASSERT_EQ(2U, chunks[0]->FullHashCount());
     85   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1));
     86   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2));
     87 }
     88 
     89 // Test parsing multiple add chunks. We'll use the same chunk as above, and add
     90 // one more after it.
     91 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) {
     92   const char kRawAddChunk[] = {
     93     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
     94     '\x08',                    // field 1, wire format varint
     95     '\x01',                    // chunk_number varint 1
     96     '\x22',                    // field 4, wire format length-delimited
     97     '\x18',                    // varint length 24
     98 
     99     '1', '1', '1', '1',        // 4-byte prefixes
    100     '2', '2', '2', '2',
    101     '3', '3', '3', '3',
    102     '4', '4', '4', '4',
    103     '8', '8', '8', '8',
    104     '9', '9', '9', '9',
    105 
    106     '\0', '\0', '\0', '\x0C',  // 32-bit payload length in network byte order.
    107     '\x08',                    // field 1, wire format varint
    108     '\x02',                    // chunk_number varint 1
    109     '\x22',                    // field 4, wire format length-delimited
    110     '\x08',                    // varint length 8
    111     'p', 'p', 'p', 'p',        // 4-byte prefixes
    112     'g', 'g', 'g', 'g',
    113   };
    114 
    115   ScopedVector<SBChunkData> chunks;
    116   EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
    117                                         &chunks));
    118   ASSERT_EQ(2U, chunks.size());
    119 
    120   EXPECT_EQ(1, chunks[0]->ChunkNumber());
    121   EXPECT_TRUE(chunks[0]->IsAdd());
    122   EXPECT_FALSE(chunks[0]->IsSub());
    123   EXPECT_TRUE(chunks[0]->IsPrefix());
    124   EXPECT_FALSE(chunks[0]->IsFullHash());
    125   ASSERT_EQ(6U, chunks[0]->PrefixCount());
    126   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
    127   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
    128   EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2));  // 3333
    129   EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3));  // 4444
    130   EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4));  // 8888
    131   EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5));  // 9999
    132 
    133   EXPECT_EQ(2, chunks[1]->ChunkNumber());
    134   EXPECT_TRUE(chunks[1]->IsAdd());
    135   EXPECT_FALSE(chunks[1]->IsSub());
    136   EXPECT_TRUE(chunks[1]->IsPrefix());
    137   EXPECT_FALSE(chunks[1]->IsFullHash());
    138   ASSERT_EQ(2U, chunks[1]->PrefixCount());
    139   EXPECT_EQ(0x70707070U, chunks[1]->PrefixAt(0));  // pppp
    140   EXPECT_EQ(0x67676767U, chunks[1]->PrefixAt(1));  // gggg
    141 }
    142 
    143 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedPrefixChunk) {
    144   // This chunk delares there are 6 prefixes but actually only contains 3.
    145   const char kRawAddChunk[] = {
    146     '\0', '\0', '\0', '\x1C',  // 32-bit payload length in network byte order.
    147     '\x08',                    // field 1, wire format varint
    148     '\x01',                    // chunk_number varint 1
    149     '\x22',                    // field 4, wire format length-delimited
    150     '\x18',                    // varint length 24
    151     '1', '1', '1', '1',        // 4-byte prefixes
    152     '2', '2', '2', '2',
    153     '3', '3', '3', '3',
    154   };
    155 
    156   ScopedVector<SBChunkData> chunks;
    157   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
    158                                          &chunks));
    159 }
    160 
    161 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedFullHashChunk) {
    162   // This chunk delares there are two full hashes but there is only one.
    163   const char kRawAddChunk[] = {
    164     '\0', '\0', '\0', '\x46',  // 32-bit payload length in network byte order.
    165     '\x08',                    // field 1, wire format varint
    166     '\x01',                    // chunk_number varint 1
    167     '\x18',                    // field 3, wire format varint
    168     '\x01',                    // enum PrefixType == FULL_32B
    169     '\x22',                    // field 4, wire format length-delimited
    170     '\x40',                    // varint length 64 (2 full hashes)
    171 
    172     '0', '1', '0', '1', '0', '1', '0', '1',
    173     '0', '1', '0', '1', '0', '1', '0', '1',
    174     '0', '1', '0', '1', '0', '1', '0', '1',
    175     '0', '1', '0', '1', '0', '1', '0', '1',
    176   };
    177 
    178   ScopedVector<SBChunkData> chunks;
    179   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
    180                                          &chunks));
    181 }
    182 
    183 TEST(SafeBrowsingProtocolParsingTest, TestHugeChunk) {
    184   // This chunk delares there are 6 prefixes but actually only contains 3.
    185   const char kRawAddChunk[] = {
    186     '\x1', '\0', '\0', '\0',   // 32-bit payload length in network byte order.
    187     '\x08',                    // field 1, wire format varint
    188     '\x01',                    // chunk_number varint 1
    189     '\x22',                    // field 4, wire format length-delimited
    190     '\x18',                    // varint length 24
    191     '1', '1', '1', '1',        // 4-byte prefixes
    192     '2', '2', '2', '2',
    193     '3', '3', '3', '3',
    194   };
    195 
    196   ScopedVector<SBChunkData> chunks;
    197   EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk),
    198                                          &chunks));
    199 }
    200 
    201 // Test parsing one sub chunk.
    202 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) {
    203   const char kRawSubChunk[] = {
    204     '\0', '\0', '\0', '\x12',  // 32-bit payload length in network byte order
    205     '\x08',                    // field 1, wire format varint
    206     '\x03',                    // chunk_number varint 3
    207     '\x10',                    // field 2, wire format varint
    208     '\x01',                    // enum ChunkType == SUB
    209     '\x22',                    // field 4, wire format length-delimited
    210     '\x08',                    // varint length 8 (2 prefixes)
    211     '1', '1', '1', '1',        // 4-byte prefixes
    212     '2', '2', '2', '2',
    213     '\x2a',                    // field 5, wire format length-delimited
    214     '\x02',                    // varint length 2 (2 add-chunk numbers)
    215     '\x07', '\x09',            // varint 7, varint 9
    216   };
    217 
    218   ScopedVector<SBChunkData> chunks;
    219   EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk),
    220                                         &chunks));
    221   ASSERT_EQ(1U, chunks.size());
    222   EXPECT_EQ(3, chunks[0]->ChunkNumber());
    223   EXPECT_FALSE(chunks[0]->IsAdd());
    224   EXPECT_TRUE(chunks[0]->IsSub());
    225   EXPECT_TRUE(chunks[0]->IsPrefix());
    226   EXPECT_FALSE(chunks[0]->IsFullHash());
    227   ASSERT_EQ(2U, chunks[0]->PrefixCount());
    228   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
    229   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
    230   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
    231   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
    232 }
    233 
    234 // Test parsing one sub chunk with full hashes.
    235 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) {
    236   const char kRawSubChunk[] = {
    237     '\0', '\0', '\0', '\x4C',  // 32-bit payload length in network byte order.
    238     '\x08',                    // field 1, wire format varint
    239     '\x02',                    // chunk_number varint 2
    240     '\x10',                    // field 2, wire format varint
    241     '\x01',                    // enum ChunkType == SUB
    242     '\x18',                    // field 3, wire format varint
    243     '\x01',                    // enum PrefixType == FULL_32B
    244     '\x22',                    // field 4, wire format length-delimited
    245     '\x40',                    // varint length 64 (2 full hashes)
    246 
    247     '0', '1', '0', '1', '0', '1', '0', '1',
    248     '0', '1', '0', '1', '0', '1', '0', '1',
    249     '0', '1', '0', '1', '0', '1', '0', '1',
    250     '0', '1', '0', '1', '0', '1', '0', '1',
    251 
    252     '2', '3', '2', '3', '2', '3', '2', '3',
    253     '2', '3', '2', '3', '2', '3', '2', '3',
    254     '2', '3', '2', '3', '2', '3', '2', '3',
    255     '2', '3', '2', '3', '2', '3', '2', '3',
    256 
    257     '\x2a',                    // field 5, wire format length-delimited
    258     '\x02',                    // varint length 2 (2 add-chunk numbers)
    259     '\x07', '\x09',            // varint 7, varint 9
    260   };
    261 
    262   SBFullHash full_hash1, full_hash2;
    263   for (int i = 0; i < 32; ++i) {
    264     full_hash1.full_hash[i] = i % 2 ? '1' : '0';
    265     full_hash2.full_hash[i] = i % 2 ? '3' : '2';
    266   }
    267 
    268   ScopedVector<SBChunkData> chunks;
    269   EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk),
    270                                         &chunks));
    271   ASSERT_EQ(1U, chunks.size());
    272   EXPECT_EQ(2, chunks[0]->ChunkNumber());
    273   EXPECT_FALSE(chunks[0]->IsAdd());
    274   EXPECT_TRUE(chunks[0]->IsSub());
    275   EXPECT_FALSE(chunks[0]->IsPrefix());
    276   EXPECT_TRUE(chunks[0]->IsFullHash());
    277 
    278   ASSERT_EQ(2U, chunks[0]->FullHashCount());
    279   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1));
    280   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
    281   EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2));
    282   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
    283 }
    284 
    285 // Test parsing the SafeBrowsing update response.
    286 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) {
    287   std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n"
    288                       "i:malware\nsd:21-27,42,171717\n");
    289 
    290   size_t next_query_sec = 0;
    291   bool reset = false;
    292   std::vector<SBChunkDelete> deletes;
    293   std::vector<ChunkUrl> urls;
    294   EXPECT_TRUE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(),
    295                                          &next_query_sec, &reset,
    296                                          &deletes, &urls));
    297 
    298   EXPECT_TRUE(urls.empty());
    299   EXPECT_FALSE(reset);
    300   EXPECT_EQ(1700U, next_query_sec);
    301   ASSERT_EQ(2U, deletes.size());
    302 
    303   ASSERT_EQ(4U, deletes[0].chunk_del.size());
    304   EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7));
    305   EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597));
    306   EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444));
    307   EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999));
    308 
    309   ASSERT_EQ(3U, deletes[1].chunk_del.size());
    310   EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27));
    311   EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42));
    312   EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717));
    313 
    314   // An update response with missing list name.
    315   next_query_sec = 0;
    316   deletes.clear();
    317   urls.clear();
    318   add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n";
    319   EXPECT_FALSE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(),
    320                                           &next_query_sec, &reset,
    321                                           &deletes, &urls));
    322 }
    323 
    324 // Test parsing the SafeBrowsing update response.
    325 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) {
    326   std::string redirects("i:goog-malware-shavar\n"
    327     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n"
    328     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n"
    329     "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n"
    330     "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689,"
    331     "8691-8731,8733-8786\n");
    332 
    333   size_t next_query_sec = 0;
    334   bool reset = false;
    335   std::vector<SBChunkDelete> deletes;
    336   std::vector<ChunkUrl> urls;
    337   EXPECT_TRUE(safe_browsing::ParseUpdate(redirects.data(), redirects.length(),
    338                                          &next_query_sec, &reset,
    339                                          &deletes, &urls));
    340   EXPECT_FALSE(reset);
    341   EXPECT_EQ(0U, next_query_sec);
    342   EXPECT_TRUE(deletes.empty());
    343 
    344   ASSERT_EQ(4U, urls.size());
    345   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1",
    346             urls[0].url);
    347   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2",
    348             urls[1].url);
    349   EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3",
    350             urls[2].url);
    351   EXPECT_EQ("s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:"
    352             "8641-8689,8691-8731,8733-8786",
    353             urls[3].url);
    354 }
    355 
    356 // Test parsing various SafeBrowsing protocol headers.
    357 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) {
    358   std::string headers("n:1800\ni:goog-white-shavar\n");
    359   size_t next_query_sec = 0;
    360   bool reset = false;
    361   std::vector<SBChunkDelete> deletes;
    362   std::vector<ChunkUrl> urls;
    363   EXPECT_TRUE(safe_browsing::ParseUpdate(headers.data(), headers.length(),
    364                                          &next_query_sec, &reset,
    365                                          &deletes, &urls));
    366 
    367   EXPECT_EQ(1800U, next_query_sec);
    368   EXPECT_FALSE(reset);
    369   EXPECT_TRUE(deletes.empty());
    370   EXPECT_TRUE(urls.empty());
    371 }
    372 
    373 // Test parsing data from a GetHashRequest
    374 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) {
    375   std::string get_hash("45\n"
    376                        "goog-phish-shavar:32:3\n"
    377                        "00112233445566778899aabbccddeeff"
    378                        "00001111222233334444555566667777"
    379                        "ffffeeeeddddccccbbbbaaaa99998888");
    380   std::vector<SBFullHashResult> full_hashes;
    381   base::TimeDelta cache_lifetime;
    382   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash.data(), get_hash.length(),
    383                                           &cache_lifetime, &full_hashes));
    384 
    385   ASSERT_EQ(3U, full_hashes.size());
    386   EXPECT_EQ(memcmp(&full_hashes[0].hash,
    387                    "00112233445566778899aabbccddeeff",
    388                    sizeof(SBFullHash)), 0);
    389   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
    390   EXPECT_EQ(memcmp(&full_hashes[1].hash,
    391                    "00001111222233334444555566667777",
    392                    sizeof(SBFullHash)), 0);
    393   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[1].list_id);
    394   EXPECT_EQ(memcmp(&full_hashes[2].hash,
    395                    "ffffeeeeddddccccbbbbaaaa99998888",
    396                    sizeof(SBFullHash)), 0);
    397   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id);
    398 
    399   // Test multiple lists in the GetHash results.
    400   std::string get_hash2("45\n"
    401                         "goog-phish-shavar:32:1\n"
    402                         "00112233445566778899aabbccddeeff"
    403                         "goog-malware-shavar:32:2\n"
    404                         "cafebeefcafebeefdeaddeaddeaddead"
    405                         "zzzzyyyyxxxxwwwwvvvvuuuuttttssss");
    406   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash2.data(), get_hash2.length(),
    407                                           &cache_lifetime, &full_hashes));
    408 
    409   ASSERT_EQ(3U, full_hashes.size());
    410   EXPECT_EQ(memcmp(&full_hashes[0].hash,
    411                    "00112233445566778899aabbccddeeff",
    412                    sizeof(SBFullHash)), 0);
    413   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
    414   EXPECT_EQ(memcmp(&full_hashes[1].hash,
    415                    "cafebeefcafebeefdeaddeaddeaddead",
    416                    sizeof(SBFullHash)), 0);
    417   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
    418   EXPECT_EQ(memcmp(&full_hashes[2].hash,
    419                    "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
    420                    sizeof(SBFullHash)), 0);
    421   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[2].list_id);
    422 
    423   // Test metadata parsing.
    424   // TODO(shess): Currently the code doesn't actually put the metadata anywhere,
    425   // this is just testing that metadata doesn't break parsing.
    426   std::string get_hash3("45\n"
    427                         "goog-malware-shavar:32:2:m\n"
    428                         "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"
    429                         "00112233445566778899aabbccddeeff"
    430                         "2\nab2\nxy"
    431                         "goog-phish-shavar:32:1\n"
    432                         "cafebeefcafebeefdeaddeaddeaddead");
    433   EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3.data(), get_hash3.length(),
    434                                           &cache_lifetime, &full_hashes));
    435 
    436   ASSERT_EQ(3U, full_hashes.size());
    437   EXPECT_EQ(memcmp(&full_hashes[0].hash,
    438                    "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
    439                    sizeof(SBFullHash)), 0);
    440   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id);
    441   EXPECT_EQ(memcmp(&full_hashes[1].hash,
    442                    "00112233445566778899aabbccddeeff",
    443                    sizeof(SBFullHash)), 0);
    444   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
    445   EXPECT_EQ(memcmp(&full_hashes[2].hash,
    446                    "cafebeefcafebeefdeaddeaddeaddead",
    447                    sizeof(SBFullHash)), 0);
    448   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id);
    449 }
    450 
    451 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) {
    452   std::string hash_response = "45\n"
    453                               "goog-phish-shavar:32:1\n"
    454                               "12345678901234567890123456789012"
    455                               "googpub-phish-shavar:32:1\n"
    456                               "09876543210987654321098765432109";
    457   std::vector<SBFullHashResult> full_hashes;
    458   base::TimeDelta cache_lifetime;
    459   EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(),
    460                                           hash_response.size(),
    461                                           &cache_lifetime,
    462                                           &full_hashes));
    463 
    464   ASSERT_EQ(1U, full_hashes.size());
    465   EXPECT_EQ(memcmp("12345678901234567890123456789012",
    466                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
    467   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
    468 
    469   hash_response += "goog-malware-shavar:32:1\n"
    470                    "abcdefghijklmnopqrstuvwxyz123457";
    471   full_hashes.clear();
    472   EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(),
    473                                           hash_response.size(),
    474                                           &cache_lifetime,
    475                                           &full_hashes));
    476 
    477   EXPECT_EQ(2U, full_hashes.size());
    478   EXPECT_EQ(memcmp("12345678901234567890123456789012",
    479                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
    480   EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id);
    481   EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457",
    482                    &full_hashes[1].hash, sizeof(SBFullHash)), 0);
    483   EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id);
    484 }
    485 
    486 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) {
    487   std::vector<SBPrefix> prefixes;
    488   prefixes.push_back(0x34333231);
    489   prefixes.push_back(0x64636261);
    490   prefixes.push_back(0x73727170);
    491 
    492   EXPECT_EQ("4:12\n1234abcdpqrs", safe_browsing::FormatGetHash(prefixes));
    493 }
    494 
    495 TEST(SafeBrowsingProtocolParsingTest, TestReset) {
    496   std::string update("n:1800\ni:phishy\nr:pleasereset\n");
    497 
    498   bool reset = false;
    499   size_t next_update = 0;
    500   std::vector<SBChunkDelete> deletes;
    501   std::vector<ChunkUrl> urls;
    502   EXPECT_TRUE(safe_browsing::ParseUpdate(update.data(), update.size(),
    503                                          &next_update, &reset,
    504                                          &deletes, &urls));
    505   EXPECT_TRUE(reset);
    506 }
    507 
    508 // The SafeBrowsing service will occasionally send zero length chunks so that
    509 // client requests will have longer contiguous chunk number ranges, and thus
    510 // reduce the request size.
    511 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) {
    512   const char kEmptyAddChunk[] = {
    513     '\0', '\0', '\0', '\x02',  // 32-bit payload length in network byte order.
    514     '\x08',                    // field 1, wire format varint
    515     '\x02',                    // chunk_number varint 2
    516   };
    517 
    518   ScopedVector<SBChunkData> chunks;
    519   EXPECT_TRUE(safe_browsing::ParseChunk(kEmptyAddChunk, sizeof(kEmptyAddChunk),
    520                                         &chunks));
    521   ASSERT_EQ(1U, chunks.size());
    522   EXPECT_EQ(2, chunks[0]->ChunkNumber());
    523   EXPECT_TRUE(chunks[0]->IsAdd());
    524   EXPECT_FALSE(chunks[0]->IsSub());
    525   EXPECT_TRUE(chunks[0]->IsPrefix());
    526   EXPECT_FALSE(chunks[0]->IsFullHash());
    527   EXPECT_EQ(0U, chunks[0]->PrefixCount());
    528 
    529   // Now test a zero size chunk in between normal chunks.
    530   chunks.clear();
    531   const char kAddChunks[] = {
    532     '\0', '\0', '\0', '\x0C',  // 32-bit payload length in network byte order.
    533     '\x08',                    // field 1, wire format varint
    534     '\x01',                    // chunk_number varint 1
    535     '\x22',                    // field 4, wire format length-delimited
    536     '\x08',                    // varint length 8
    537 
    538     '1', '1', '1', '1',        // 4-byte prefixes
    539     '2', '2', '2', '2',
    540 
    541     '\0', '\0', '\0', '\x02',  // 32-bit payload length in network byte order.
    542     '\x08',                    // field 1, wire format varint
    543     '\x02',                    // chunk_number varint 2
    544 
    545     '\0', '\0', '\0', '\x08',  // 32-bit payload length in network byte order.
    546     '\x08',                    // field 1, wire format varint
    547     '\x03',                    // chunk_number varint 3
    548     '\x22',                    // field 4, wire format length-delimited
    549     '\x04',                    // varint length 8
    550     'p', 'p', 'p', 'p',        // 4-byte prefixes
    551   };
    552   EXPECT_TRUE(safe_browsing::ParseChunk(kAddChunks, sizeof(kAddChunks),
    553                                         &chunks));
    554   ASSERT_EQ(3U, chunks.size());
    555 
    556   EXPECT_EQ(1, chunks[0]->ChunkNumber());
    557   EXPECT_TRUE(chunks[0]->IsAdd());
    558   EXPECT_FALSE(chunks[0]->IsSub());
    559   EXPECT_TRUE(chunks[0]->IsPrefix());
    560   EXPECT_FALSE(chunks[0]->IsFullHash());
    561   ASSERT_EQ(2U, chunks[0]->PrefixCount());
    562   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
    563   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
    564 
    565   EXPECT_EQ(2, chunks[1]->ChunkNumber());
    566   EXPECT_TRUE(chunks[1]->IsAdd());
    567   EXPECT_FALSE(chunks[1]->IsSub());
    568   EXPECT_TRUE(chunks[1]->IsPrefix());
    569   EXPECT_FALSE(chunks[1]->IsFullHash());
    570   EXPECT_EQ(0U, chunks[1]->PrefixCount());
    571 
    572   EXPECT_EQ(3, chunks[2]->ChunkNumber());
    573   EXPECT_TRUE(chunks[2]->IsAdd());
    574   EXPECT_FALSE(chunks[2]->IsSub());
    575   EXPECT_TRUE(chunks[2]->IsPrefix());
    576   EXPECT_FALSE(chunks[2]->IsFullHash());
    577   ASSERT_EQ(1U, chunks[2]->PrefixCount());
    578   EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0));  // pppp
    579 }
    580 
    581 // Test parsing a zero sized sub chunk.
    582 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) {
    583   const char kEmptySubChunk[] = {
    584     '\0', '\0', '\0', '\x04',  // 32-bit payload length in network byte order.
    585     '\x08',                    // field 1, wire format varint
    586     '\x02',                    // chunk_number varint 2
    587     '\x10',                    // field 2, wire format varint
    588     '\x01',                    // enum ChunkType == SUB
    589   };
    590 
    591   ScopedVector<SBChunkData> chunks;
    592   EXPECT_TRUE(safe_browsing::ParseChunk(kEmptySubChunk, sizeof(kEmptySubChunk),
    593                                         &chunks));
    594   ASSERT_EQ(1U, chunks.size());
    595   EXPECT_EQ(2, chunks[0]->ChunkNumber());
    596   EXPECT_FALSE(chunks[0]->IsAdd());
    597   EXPECT_TRUE(chunks[0]->IsSub());
    598   EXPECT_TRUE(chunks[0]->IsPrefix());
    599   EXPECT_FALSE(chunks[0]->IsFullHash());
    600   EXPECT_EQ(0U, chunks[0]->PrefixCount());
    601 
    602   // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
    603   chunks.clear();
    604   const char kSubChunks[] = {
    605     '\0', '\0', '\0', '\x12',  // 32-bit payload length in network byte order.
    606     '\x08',                    // field 1, wire format varint
    607     '\x01',                    // chunk_number varint 1
    608     '\x10',                    // field 2, wire format varint
    609     '\x01',                    // enum ChunkType == SUB
    610     '\x22',                    // field 4, wire format length-delimited
    611     '\x08',                    // varint length 8
    612     '1', '1', '1', '1',        // 4-byte prefixes
    613     '2', '2', '2', '2',
    614     '\x2a',                    // field 5, wire format length-delimited
    615     '\x02',                    // varint length 2 (2 add-chunk numbers)
    616     '\x07', '\x09',            // varint 7, varint 9
    617 
    618     '\0', '\0', '\0', '\x04',  // 32-bit payload length in network byte order.
    619     '\x08',                    // field 1, wire format varint
    620     '\x02',                    // chunk_number varint 2
    621     '\x10',                    // field 2, wire format varint
    622     '\x01',                    // enum ChunkType == SUB
    623 
    624     '\0', '\0', '\0', '\x0D',  // 32-bit payload length in network byte order.
    625     '\x08',                    // field 1, wire format varint
    626     '\x03',                    // chunk_number varint 3
    627     '\x10',                    // field 2, wire format varint
    628     '\x01',                    // enum ChunkType == SUB
    629     '\x22',                    // field 4, wire format length-delimited
    630     '\x04',                    // varint length 8
    631     'p', 'p', 'p', 'p',        // 4-byte prefix
    632     '\x2a',                    // field 5, wire format length-delimited
    633     '\x01',                    // varint length 1 (1 add-chunk numbers)
    634     '\x0B',                    // varint 11
    635   };
    636 
    637   EXPECT_TRUE(safe_browsing::ParseChunk(kSubChunks, sizeof(kSubChunks),
    638                                         &chunks));
    639   ASSERT_EQ(3U, chunks.size());
    640 
    641   EXPECT_EQ(1, chunks[0]->ChunkNumber());
    642   EXPECT_FALSE(chunks[0]->IsAdd());
    643   EXPECT_TRUE(chunks[0]->IsSub());
    644   EXPECT_TRUE(chunks[0]->IsPrefix());
    645   EXPECT_FALSE(chunks[0]->IsFullHash());
    646   ASSERT_EQ(2U, chunks[0]->PrefixCount());
    647   EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0));  // 1111
    648   EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0));
    649   EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1));  // 2222
    650   EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1));
    651 
    652   EXPECT_EQ(2, chunks[1]->ChunkNumber());
    653   EXPECT_FALSE(chunks[0]->IsAdd());
    654   EXPECT_TRUE(chunks[0]->IsSub());
    655   EXPECT_TRUE(chunks[1]->IsPrefix());
    656   EXPECT_FALSE(chunks[1]->IsFullHash());
    657   EXPECT_EQ(0U, chunks[1]->PrefixCount());
    658 
    659   EXPECT_EQ(3, chunks[2]->ChunkNumber());
    660   EXPECT_FALSE(chunks[0]->IsAdd());
    661   EXPECT_TRUE(chunks[0]->IsSub());
    662   EXPECT_TRUE(chunks[2]->IsPrefix());
    663   EXPECT_FALSE(chunks[2]->IsFullHash());
    664   ASSERT_EQ(1U, chunks[2]->PrefixCount());
    665   EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0));  // pppp
    666   EXPECT_EQ(11, chunks[2]->AddChunkNumberAt(0));
    667 }
    668