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.
7 #include "base/strings/stringprintf.h"
8 #include "base/time/time.h"
9 #include "chrome/browser/safe_browsing/protocol_parser.h"
10 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 #if defined(OS_ANDROID)
16 const char kDefaultPhishList
[] = "goog-mobilephish-shavar";
17 const char kDefaultMalwareList
[] = "goog-mobilemalware-shavar";
19 const char kDefaultPhishList
[] = "goog-phish-shavar";
20 const char kDefaultMalwareList
[] = "goog-malware-shavar";
23 // Test parsing one add chunk.
24 TEST(SafeBrowsingProtocolParsingTest
, TestAddChunk
) {
25 const char kRawAddChunk
[] = {
26 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order.
27 '\x08', // field 1, wire format varint
28 '\x01', // chunk_number varint 1
29 '\x22', // field 4, wire format length-delimited
30 '\x18', // varint length 24
31 '1', '1', '1', '1', // 4-byte prefixes
39 ScopedVector
<SBChunkData
> chunks
;
40 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
42 ASSERT_EQ(1U, chunks
.size());
43 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
44 EXPECT_TRUE(chunks
[0]->IsAdd());
45 EXPECT_FALSE(chunks
[0]->IsSub());
46 EXPECT_TRUE(chunks
[0]->IsPrefix());
47 EXPECT_FALSE(chunks
[0]->IsFullHash());
48 ASSERT_EQ(6U, chunks
[0]->PrefixCount());
49 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
50 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
51 EXPECT_EQ(0x33333333U
, chunks
[0]->PrefixAt(2)); // 3333
52 EXPECT_EQ(0x34343434U
, chunks
[0]->PrefixAt(3)); // 4444
53 EXPECT_EQ(0x38383838U
, chunks
[0]->PrefixAt(4)); // 8888
54 EXPECT_EQ(0x39393939U
, chunks
[0]->PrefixAt(5)); // 9999
57 // Test parsing one add chunk with full hashes.
58 TEST(SafeBrowsingProtocolParsingTest
, TestAddFullChunk
) {
59 const char kRawAddChunk
[] = {
60 '\0', '\0', '\0', '\x46', // 32-bit payload length in network byte order.
61 '\x08', // field 1, wire format varint
62 '\x01', // chunk_number varint 1
63 '\x18', // field 3, wire format varint
64 '\x01', // enum PrefixType == FULL_32B
65 '\x22', // field 4, wire format length-delimited
66 '\x40', // varint length 64 (2 full hashes)
68 '0', '1', '0', '1', '0', '1', '0', '1',
69 '0', '1', '0', '1', '0', '1', '0', '1',
70 '0', '1', '0', '1', '0', '1', '0', '1',
71 '0', '1', '0', '1', '0', '1', '0', '1',
73 '2', '3', '2', '3', '2', '3', '2', '3',
74 '2', '3', '2', '3', '2', '3', '2', '3',
75 '2', '3', '2', '3', '2', '3', '2', '3',
76 '2', '3', '2', '3', '2', '3', '2', '3',
79 SBFullHash full_hash1
, full_hash2
;
80 for (int i
= 0; i
< 32; ++i
) {
81 full_hash1
.full_hash
[i
] = (i
% 2) ? '1' : '0';
82 full_hash2
.full_hash
[i
] = (i
% 2) ? '3' : '2';
85 ScopedVector
<SBChunkData
> chunks
;
86 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
88 ASSERT_EQ(1U, chunks
.size());
89 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
90 EXPECT_TRUE(chunks
[0]->IsAdd());
91 EXPECT_FALSE(chunks
[0]->IsSub());
92 EXPECT_FALSE(chunks
[0]->IsPrefix());
93 EXPECT_TRUE(chunks
[0]->IsFullHash());
95 ASSERT_EQ(2U, chunks
[0]->FullHashCount());
96 EXPECT_TRUE(SBFullHashEqual(chunks
[0]->FullHashAt(0), full_hash1
));
97 EXPECT_TRUE(SBFullHashEqual(chunks
[0]->FullHashAt(1), full_hash2
));
100 // Test parsing multiple add chunks. We'll use the same chunk as above, and add
101 // one more after it.
102 TEST(SafeBrowsingProtocolParsingTest
, TestAddChunks
) {
103 const char kRawAddChunk
[] = {
104 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order.
105 '\x08', // field 1, wire format varint
106 '\x01', // chunk_number varint 1
107 '\x22', // field 4, wire format length-delimited
108 '\x18', // varint length 24
110 '1', '1', '1', '1', // 4-byte prefixes
117 '\0', '\0', '\0', '\x0C', // 32-bit payload length in network byte order.
118 '\x08', // field 1, wire format varint
119 '\x02', // chunk_number varint 1
120 '\x22', // field 4, wire format length-delimited
121 '\x08', // varint length 8
122 'p', 'p', 'p', 'p', // 4-byte prefixes
126 ScopedVector
<SBChunkData
> chunks
;
127 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
129 ASSERT_EQ(2U, chunks
.size());
131 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
132 EXPECT_TRUE(chunks
[0]->IsAdd());
133 EXPECT_FALSE(chunks
[0]->IsSub());
134 EXPECT_TRUE(chunks
[0]->IsPrefix());
135 EXPECT_FALSE(chunks
[0]->IsFullHash());
136 ASSERT_EQ(6U, chunks
[0]->PrefixCount());
137 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
138 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
139 EXPECT_EQ(0x33333333U
, chunks
[0]->PrefixAt(2)); // 3333
140 EXPECT_EQ(0x34343434U
, chunks
[0]->PrefixAt(3)); // 4444
141 EXPECT_EQ(0x38383838U
, chunks
[0]->PrefixAt(4)); // 8888
142 EXPECT_EQ(0x39393939U
, chunks
[0]->PrefixAt(5)); // 9999
144 EXPECT_EQ(2, chunks
[1]->ChunkNumber());
145 EXPECT_TRUE(chunks
[1]->IsAdd());
146 EXPECT_FALSE(chunks
[1]->IsSub());
147 EXPECT_TRUE(chunks
[1]->IsPrefix());
148 EXPECT_FALSE(chunks
[1]->IsFullHash());
149 ASSERT_EQ(2U, chunks
[1]->PrefixCount());
150 EXPECT_EQ(0x70707070U
, chunks
[1]->PrefixAt(0)); // pppp
151 EXPECT_EQ(0x67676767U
, chunks
[1]->PrefixAt(1)); // gggg
154 TEST(SafeBrowsingProtocolParsingTest
, TestTruncatedPrefixChunk
) {
155 // This chunk delares there are 6 prefixes but actually only contains 3.
156 const char kRawAddChunk
[] = {
157 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order.
158 '\x08', // field 1, wire format varint
159 '\x01', // chunk_number varint 1
160 '\x22', // field 4, wire format length-delimited
161 '\x18', // varint length 24
162 '1', '1', '1', '1', // 4-byte prefixes
167 ScopedVector
<SBChunkData
> chunks
;
168 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
172 TEST(SafeBrowsingProtocolParsingTest
, TestTruncatedFullHashChunk
) {
173 // This chunk delares there are two full hashes but there is only one.
174 const char kRawAddChunk
[] = {
175 '\0', '\0', '\0', '\x46', // 32-bit payload length in network byte order.
176 '\x08', // field 1, wire format varint
177 '\x01', // chunk_number varint 1
178 '\x18', // field 3, wire format varint
179 '\x01', // enum PrefixType == FULL_32B
180 '\x22', // field 4, wire format length-delimited
181 '\x40', // varint length 64 (2 full hashes)
183 '0', '1', '0', '1', '0', '1', '0', '1',
184 '0', '1', '0', '1', '0', '1', '0', '1',
185 '0', '1', '0', '1', '0', '1', '0', '1',
186 '0', '1', '0', '1', '0', '1', '0', '1',
189 ScopedVector
<SBChunkData
> chunks
;
190 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
194 TEST(SafeBrowsingProtocolParsingTest
, TestHugeChunk
) {
195 // This chunk delares there are 6 prefixes but actually only contains 3.
196 const char kRawAddChunk
[] = {
197 '\x1', '\0', '\0', '\0', // 32-bit payload length in network byte order.
198 '\x08', // field 1, wire format varint
199 '\x01', // chunk_number varint 1
200 '\x22', // field 4, wire format length-delimited
201 '\x18', // varint length 24
202 '1', '1', '1', '1', // 4-byte prefixes
207 ScopedVector
<SBChunkData
> chunks
;
208 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk
, sizeof(kRawAddChunk
),
212 // Test parsing one sub chunk.
213 TEST(SafeBrowsingProtocolParsingTest
, TestSubChunk
) {
214 const char kRawSubChunk
[] = {
215 '\0', '\0', '\0', '\x12', // 32-bit payload length in network byte order
216 '\x08', // field 1, wire format varint
217 '\x03', // chunk_number varint 3
218 '\x10', // field 2, wire format varint
219 '\x01', // enum ChunkType == SUB
220 '\x22', // field 4, wire format length-delimited
221 '\x08', // varint length 8 (2 prefixes)
222 '1', '1', '1', '1', // 4-byte prefixes
224 '\x2a', // field 5, wire format length-delimited
225 '\x02', // varint length 2 (2 add-chunk numbers)
226 '\x07', '\x09', // varint 7, varint 9
229 ScopedVector
<SBChunkData
> chunks
;
230 EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk
, sizeof(kRawSubChunk
),
232 ASSERT_EQ(1U, chunks
.size());
233 EXPECT_EQ(3, chunks
[0]->ChunkNumber());
234 EXPECT_FALSE(chunks
[0]->IsAdd());
235 EXPECT_TRUE(chunks
[0]->IsSub());
236 EXPECT_TRUE(chunks
[0]->IsPrefix());
237 EXPECT_FALSE(chunks
[0]->IsFullHash());
238 ASSERT_EQ(2U, chunks
[0]->PrefixCount());
239 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
240 EXPECT_EQ(7, chunks
[0]->AddChunkNumberAt(0));
241 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
242 EXPECT_EQ(9, chunks
[0]->AddChunkNumberAt(1));
245 // Test parsing one sub chunk with full hashes.
246 TEST(SafeBrowsingProtocolParsingTest
, TestSubFullChunk
) {
247 const char kRawSubChunk
[] = {
248 '\0', '\0', '\0', '\x4C', // 32-bit payload length in network byte order.
249 '\x08', // field 1, wire format varint
250 '\x02', // chunk_number varint 2
251 '\x10', // field 2, wire format varint
252 '\x01', // enum ChunkType == SUB
253 '\x18', // field 3, wire format varint
254 '\x01', // enum PrefixType == FULL_32B
255 '\x22', // field 4, wire format length-delimited
256 '\x40', // varint length 64 (2 full hashes)
258 '0', '1', '0', '1', '0', '1', '0', '1',
259 '0', '1', '0', '1', '0', '1', '0', '1',
260 '0', '1', '0', '1', '0', '1', '0', '1',
261 '0', '1', '0', '1', '0', '1', '0', '1',
263 '2', '3', '2', '3', '2', '3', '2', '3',
264 '2', '3', '2', '3', '2', '3', '2', '3',
265 '2', '3', '2', '3', '2', '3', '2', '3',
266 '2', '3', '2', '3', '2', '3', '2', '3',
268 '\x2a', // field 5, wire format length-delimited
269 '\x02', // varint length 2 (2 add-chunk numbers)
270 '\x07', '\x09', // varint 7, varint 9
273 SBFullHash full_hash1
, full_hash2
;
274 for (int i
= 0; i
< 32; ++i
) {
275 full_hash1
.full_hash
[i
] = i
% 2 ? '1' : '0';
276 full_hash2
.full_hash
[i
] = i
% 2 ? '3' : '2';
279 ScopedVector
<SBChunkData
> chunks
;
280 EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk
, sizeof(kRawSubChunk
),
282 ASSERT_EQ(1U, chunks
.size());
283 EXPECT_EQ(2, chunks
[0]->ChunkNumber());
284 EXPECT_FALSE(chunks
[0]->IsAdd());
285 EXPECT_TRUE(chunks
[0]->IsSub());
286 EXPECT_FALSE(chunks
[0]->IsPrefix());
287 EXPECT_TRUE(chunks
[0]->IsFullHash());
289 ASSERT_EQ(2U, chunks
[0]->FullHashCount());
290 EXPECT_TRUE(SBFullHashEqual(chunks
[0]->FullHashAt(0), full_hash1
));
291 EXPECT_EQ(7, chunks
[0]->AddChunkNumberAt(0));
292 EXPECT_TRUE(SBFullHashEqual(chunks
[0]->FullHashAt(1), full_hash2
));
293 EXPECT_EQ(9, chunks
[0]->AddChunkNumberAt(1));
296 // Test parsing the SafeBrowsing update response.
297 TEST(SafeBrowsingProtocolParsingTest
, TestChunkDelete
) {
298 std::string
add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n"
299 "i:malware\nsd:21-27,42,171717\n");
301 size_t next_query_sec
= 0;
303 std::vector
<SBChunkDelete
> deletes
;
304 std::vector
<ChunkUrl
> urls
;
305 EXPECT_TRUE(safe_browsing::ParseUpdate(add_del
.data(), add_del
.length(),
306 &next_query_sec
, &reset
,
309 EXPECT_TRUE(urls
.empty());
311 EXPECT_EQ(1700U, next_query_sec
);
312 ASSERT_EQ(2U, deletes
.size());
314 ASSERT_EQ(4U, deletes
[0].chunk_del
.size());
315 EXPECT_TRUE(deletes
[0].chunk_del
[0] == ChunkRange(1, 7));
316 EXPECT_TRUE(deletes
[0].chunk_del
[1] == ChunkRange(43, 597));
317 EXPECT_TRUE(deletes
[0].chunk_del
[2] == ChunkRange(44444));
318 EXPECT_TRUE(deletes
[0].chunk_del
[3] == ChunkRange(99999));
320 ASSERT_EQ(3U, deletes
[1].chunk_del
.size());
321 EXPECT_TRUE(deletes
[1].chunk_del
[0] == ChunkRange(21, 27));
322 EXPECT_TRUE(deletes
[1].chunk_del
[1] == ChunkRange(42));
323 EXPECT_TRUE(deletes
[1].chunk_del
[2] == ChunkRange(171717));
325 // An update response with missing list name.
329 add_del
= "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n";
330 EXPECT_FALSE(safe_browsing::ParseUpdate(add_del
.data(), add_del
.length(),
331 &next_query_sec
, &reset
,
335 // Test parsing the SafeBrowsing update response.
336 TEST(SafeBrowsingProtocolParsingTest
, TestRedirects
) {
337 const std::string
redirects(base::StringPrintf(
339 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n"
340 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n"
341 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n"
342 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689,"
343 "8691-8731,8733-8786\n",
344 kDefaultMalwareList
));
346 size_t next_query_sec
= 0;
348 std::vector
<SBChunkDelete
> deletes
;
349 std::vector
<ChunkUrl
> urls
;
350 EXPECT_TRUE(safe_browsing::ParseUpdate(redirects
.data(), redirects
.length(),
351 &next_query_sec
, &reset
,
354 EXPECT_EQ(0U, next_query_sec
);
355 EXPECT_TRUE(deletes
.empty());
357 ASSERT_EQ(4U, urls
.size());
358 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1",
360 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2",
362 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3",
364 EXPECT_EQ("s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:"
365 "8641-8689,8691-8731,8733-8786",
369 // Test parsing various SafeBrowsing protocol headers.
370 TEST(SafeBrowsingProtocolParsingTest
, TestNextQueryTime
) {
371 std::string
headers("n:1800\ni:goog-white-shavar\n");
372 size_t next_query_sec
= 0;
374 std::vector
<SBChunkDelete
> deletes
;
375 std::vector
<ChunkUrl
> urls
;
376 EXPECT_TRUE(safe_browsing::ParseUpdate(headers
.data(), headers
.length(),
377 &next_query_sec
, &reset
,
380 EXPECT_EQ(1800U, next_query_sec
);
382 EXPECT_TRUE(deletes
.empty());
383 EXPECT_TRUE(urls
.empty());
386 // Test parsing data from a GetHashRequest
387 TEST(SafeBrowsingProtocolParsingTest
, TestGetHash
) {
388 const std::string
get_hash(base::StringPrintf(
391 "00112233445566778899aabbccddeeff"
392 "00001111222233334444555566667777"
393 "ffffeeeeddddccccbbbbaaaa99998888",
395 std::vector
<SBFullHashResult
> full_hashes
;
396 base::TimeDelta cache_lifetime
;
397 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash
.data(), get_hash
.length(),
398 &cache_lifetime
, &full_hashes
));
400 ASSERT_EQ(3U, full_hashes
.size());
401 EXPECT_EQ(memcmp(&full_hashes
[0].hash
,
402 "00112233445566778899aabbccddeeff",
403 sizeof(SBFullHash
)), 0);
404 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
405 EXPECT_EQ(memcmp(&full_hashes
[1].hash
,
406 "00001111222233334444555566667777",
407 sizeof(SBFullHash
)), 0);
408 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[1].list_id
);
409 EXPECT_EQ(memcmp(&full_hashes
[2].hash
,
410 "ffffeeeeddddccccbbbbaaaa99998888",
411 sizeof(SBFullHash
)), 0);
412 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[2].list_id
);
414 // Test multiple lists in the GetHash results.
415 const std::string
get_hash2(base::StringPrintf(
418 "00112233445566778899aabbccddeeff"
420 "cafebeefcafebeefdeaddeaddeaddead"
421 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
423 kDefaultMalwareList
));
424 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash2
.data(), get_hash2
.length(),
425 &cache_lifetime
, &full_hashes
));
427 ASSERT_EQ(3U, full_hashes
.size());
428 EXPECT_EQ(memcmp(&full_hashes
[0].hash
,
429 "00112233445566778899aabbccddeeff",
430 sizeof(SBFullHash
)), 0);
431 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
432 EXPECT_EQ(memcmp(&full_hashes
[1].hash
,
433 "cafebeefcafebeefdeaddeaddeaddead",
434 sizeof(SBFullHash
)), 0);
435 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[1].list_id
);
436 EXPECT_EQ(memcmp(&full_hashes
[2].hash
,
437 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
438 sizeof(SBFullHash
)), 0);
439 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[2].list_id
);
441 // Test metadata parsing.
442 const std::string
get_hash3(base::StringPrintf(
445 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"
446 "00112233445566778899aabbccddeeff"
449 "cafebeefcafebeefdeaddeaddeaddead",
452 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3
.data(), get_hash3
.length(),
453 &cache_lifetime
, &full_hashes
));
455 ASSERT_EQ(3U, full_hashes
.size());
456 EXPECT_EQ(memcmp(&full_hashes
[0].hash
,
457 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
458 sizeof(SBFullHash
)), 0);
459 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[0].list_id
);
460 EXPECT_EQ(std::string("ab"), full_hashes
[0].metadata
);
461 EXPECT_EQ(memcmp(&full_hashes
[1].hash
,
462 "00112233445566778899aabbccddeeff",
463 sizeof(SBFullHash
)), 0);
464 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[1].list_id
);
465 EXPECT_EQ(std::string("xy"), full_hashes
[1].metadata
);
466 EXPECT_EQ(memcmp(&full_hashes
[2].hash
,
467 "cafebeefcafebeefdeaddeaddeaddead",
468 sizeof(SBFullHash
)), 0);
469 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[2].list_id
);
470 EXPECT_EQ(std::string(), full_hashes
[2].metadata
);
473 TEST(SafeBrowsingProtocolParsingTest
, TestGetHashWithUnknownList
) {
474 std::string
hash_response(base::StringPrintf(
477 "12345678901234567890123456789012"
478 "googpub-phish-shavar:32:1\n"
479 "09876543210987654321098765432109",
481 std::vector
<SBFullHashResult
> full_hashes
;
482 base::TimeDelta cache_lifetime
;
483 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response
.data(),
484 hash_response
.size(),
488 ASSERT_EQ(1U, full_hashes
.size());
489 EXPECT_EQ(memcmp("12345678901234567890123456789012",
490 &full_hashes
[0].hash
, sizeof(SBFullHash
)), 0);
491 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
493 hash_response
+= base::StringPrintf(
495 "abcdefghijklmnopqrstuvwxyz123457",
496 kDefaultMalwareList
);
498 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response
.data(),
499 hash_response
.size(),
503 EXPECT_EQ(2U, full_hashes
.size());
504 EXPECT_EQ(memcmp("12345678901234567890123456789012",
505 &full_hashes
[0].hash
, sizeof(SBFullHash
)), 0);
506 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
507 EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457",
508 &full_hashes
[1].hash
, sizeof(SBFullHash
)), 0);
509 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[1].list_id
);
512 TEST(SafeBrowsingProtocolParsingTest
, TestGetHashWithUnknownListAndMetadata
) {
513 std::vector
<SBFullHashResult
> full_hashes
;
514 base::TimeDelta cache_lifetime
;
515 // Test skipping over a hashentry with an unrecognized listname that also has
517 const std::string
get_hash3(base::StringPrintf(
519 "BADLISTNAME:32:1:m\n"
520 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
523 "0123456789hashhashhashhashhashha",
524 kDefaultMalwareList
));
525 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3
.data(), get_hash3
.length(),
526 &cache_lifetime
, &full_hashes
));
527 ASSERT_EQ(1U, full_hashes
.size());
528 EXPECT_EQ(memcmp(&full_hashes
[0].hash
,
529 "0123456789hashhashhashhashhashha",
530 sizeof(SBFullHash
)), 0);
531 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[0].list_id
);
532 EXPECT_EQ(std::string(), full_hashes
[0].metadata
);
535 TEST(SafeBrowsingProtocolParsingTest
, TestFormatHash
) {
536 std::vector
<SBPrefix
> prefixes
;
537 prefixes
.push_back(0x34333231);
538 prefixes
.push_back(0x64636261);
539 prefixes
.push_back(0x73727170);
541 EXPECT_EQ("4:12\n1234abcdpqrs", safe_browsing::FormatGetHash(prefixes
));
544 TEST(SafeBrowsingProtocolParsingTest
, TestReset
) {
545 std::string
update("n:1800\ni:phishy\nr:pleasereset\n");
548 size_t next_update
= 0;
549 std::vector
<SBChunkDelete
> deletes
;
550 std::vector
<ChunkUrl
> urls
;
551 EXPECT_TRUE(safe_browsing::ParseUpdate(update
.data(), update
.size(),
552 &next_update
, &reset
,
557 // The SafeBrowsing service will occasionally send zero length chunks so that
558 // client requests will have longer contiguous chunk number ranges, and thus
559 // reduce the request size.
560 TEST(SafeBrowsingProtocolParsingTest
, TestZeroSizeAddChunk
) {
561 const char kEmptyAddChunk
[] = {
562 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order.
563 '\x08', // field 1, wire format varint
564 '\x02', // chunk_number varint 2
567 ScopedVector
<SBChunkData
> chunks
;
568 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptyAddChunk
, sizeof(kEmptyAddChunk
),
570 ASSERT_EQ(1U, chunks
.size());
571 EXPECT_EQ(2, chunks
[0]->ChunkNumber());
572 EXPECT_TRUE(chunks
[0]->IsAdd());
573 EXPECT_FALSE(chunks
[0]->IsSub());
574 EXPECT_TRUE(chunks
[0]->IsPrefix());
575 EXPECT_FALSE(chunks
[0]->IsFullHash());
576 EXPECT_EQ(0U, chunks
[0]->PrefixCount());
578 // Now test a zero size chunk in between normal chunks.
580 const char kAddChunks
[] = {
581 '\0', '\0', '\0', '\x0C', // 32-bit payload length in network byte order.
582 '\x08', // field 1, wire format varint
583 '\x01', // chunk_number varint 1
584 '\x22', // field 4, wire format length-delimited
585 '\x08', // varint length 8
587 '1', '1', '1', '1', // 4-byte prefixes
590 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order.
591 '\x08', // field 1, wire format varint
592 '\x02', // chunk_number varint 2
594 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
595 '\x08', // field 1, wire format varint
596 '\x03', // chunk_number varint 3
597 '\x22', // field 4, wire format length-delimited
598 '\x04', // varint length 8
599 'p', 'p', 'p', 'p', // 4-byte prefixes
601 EXPECT_TRUE(safe_browsing::ParseChunk(kAddChunks
, sizeof(kAddChunks
),
603 ASSERT_EQ(3U, chunks
.size());
605 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
606 EXPECT_TRUE(chunks
[0]->IsAdd());
607 EXPECT_FALSE(chunks
[0]->IsSub());
608 EXPECT_TRUE(chunks
[0]->IsPrefix());
609 EXPECT_FALSE(chunks
[0]->IsFullHash());
610 ASSERT_EQ(2U, chunks
[0]->PrefixCount());
611 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
612 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
614 EXPECT_EQ(2, chunks
[1]->ChunkNumber());
615 EXPECT_TRUE(chunks
[1]->IsAdd());
616 EXPECT_FALSE(chunks
[1]->IsSub());
617 EXPECT_TRUE(chunks
[1]->IsPrefix());
618 EXPECT_FALSE(chunks
[1]->IsFullHash());
619 EXPECT_EQ(0U, chunks
[1]->PrefixCount());
621 EXPECT_EQ(3, chunks
[2]->ChunkNumber());
622 EXPECT_TRUE(chunks
[2]->IsAdd());
623 EXPECT_FALSE(chunks
[2]->IsSub());
624 EXPECT_TRUE(chunks
[2]->IsPrefix());
625 EXPECT_FALSE(chunks
[2]->IsFullHash());
626 ASSERT_EQ(1U, chunks
[2]->PrefixCount());
627 EXPECT_EQ(0x70707070U
, chunks
[2]->PrefixAt(0)); // pppp
630 // Test parsing a zero sized sub chunk.
631 TEST(SafeBrowsingProtocolParsingTest
, TestZeroSizeSubChunk
) {
632 const char kEmptySubChunk
[] = {
633 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order.
634 '\x08', // field 1, wire format varint
635 '\x02', // chunk_number varint 2
636 '\x10', // field 2, wire format varint
637 '\x01', // enum ChunkType == SUB
640 ScopedVector
<SBChunkData
> chunks
;
641 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptySubChunk
, sizeof(kEmptySubChunk
),
643 ASSERT_EQ(1U, chunks
.size());
644 EXPECT_EQ(2, chunks
[0]->ChunkNumber());
645 EXPECT_FALSE(chunks
[0]->IsAdd());
646 EXPECT_TRUE(chunks
[0]->IsSub());
647 EXPECT_TRUE(chunks
[0]->IsPrefix());
648 EXPECT_FALSE(chunks
[0]->IsFullHash());
649 EXPECT_EQ(0U, chunks
[0]->PrefixCount());
651 // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
653 const char kSubChunks
[] = {
654 '\0', '\0', '\0', '\x12', // 32-bit payload length in network byte order.
655 '\x08', // field 1, wire format varint
656 '\x01', // chunk_number varint 1
657 '\x10', // field 2, wire format varint
658 '\x01', // enum ChunkType == SUB
659 '\x22', // field 4, wire format length-delimited
660 '\x08', // varint length 8
661 '1', '1', '1', '1', // 4-byte prefixes
663 '\x2a', // field 5, wire format length-delimited
664 '\x02', // varint length 2 (2 add-chunk numbers)
665 '\x07', '\x09', // varint 7, varint 9
667 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order.
668 '\x08', // field 1, wire format varint
669 '\x02', // chunk_number varint 2
670 '\x10', // field 2, wire format varint
671 '\x01', // enum ChunkType == SUB
673 '\0', '\0', '\0', '\x0D', // 32-bit payload length in network byte order.
674 '\x08', // field 1, wire format varint
675 '\x03', // chunk_number varint 3
676 '\x10', // field 2, wire format varint
677 '\x01', // enum ChunkType == SUB
678 '\x22', // field 4, wire format length-delimited
679 '\x04', // varint length 8
680 'p', 'p', 'p', 'p', // 4-byte prefix
681 '\x2a', // field 5, wire format length-delimited
682 '\x01', // varint length 1 (1 add-chunk numbers)
686 EXPECT_TRUE(safe_browsing::ParseChunk(kSubChunks
, sizeof(kSubChunks
),
688 ASSERT_EQ(3U, chunks
.size());
690 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
691 EXPECT_FALSE(chunks
[0]->IsAdd());
692 EXPECT_TRUE(chunks
[0]->IsSub());
693 EXPECT_TRUE(chunks
[0]->IsPrefix());
694 EXPECT_FALSE(chunks
[0]->IsFullHash());
695 ASSERT_EQ(2U, chunks
[0]->PrefixCount());
696 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
697 EXPECT_EQ(7, chunks
[0]->AddChunkNumberAt(0));
698 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
699 EXPECT_EQ(9, chunks
[0]->AddChunkNumberAt(1));
701 EXPECT_EQ(2, chunks
[1]->ChunkNumber());
702 EXPECT_FALSE(chunks
[0]->IsAdd());
703 EXPECT_TRUE(chunks
[0]->IsSub());
704 EXPECT_TRUE(chunks
[1]->IsPrefix());
705 EXPECT_FALSE(chunks
[1]->IsFullHash());
706 EXPECT_EQ(0U, chunks
[1]->PrefixCount());
708 EXPECT_EQ(3, chunks
[2]->ChunkNumber());
709 EXPECT_FALSE(chunks
[0]->IsAdd());
710 EXPECT_TRUE(chunks
[0]->IsSub());
711 EXPECT_TRUE(chunks
[2]->IsPrefix());
712 EXPECT_FALSE(chunks
[2]->IsFullHash());
713 ASSERT_EQ(1U, chunks
[2]->PrefixCount());
714 EXPECT_EQ(0x70707070U
, chunks
[2]->PrefixAt(0)); // pppp
715 EXPECT_EQ(11, chunks
[2]->AddChunkNumberAt(0));