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 // TODO(shess): Currently the code doesn't actually put the metadata anywhere,
443 // this is just testing that metadata doesn't break parsing.
444 const std::string
get_hash3(base::StringPrintf(
447 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"
448 "00112233445566778899aabbccddeeff"
451 "cafebeefcafebeefdeaddeaddeaddead",
454 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3
.data(), get_hash3
.length(),
455 &cache_lifetime
, &full_hashes
));
457 ASSERT_EQ(3U, full_hashes
.size());
458 EXPECT_EQ(memcmp(&full_hashes
[0].hash
,
459 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss",
460 sizeof(SBFullHash
)), 0);
461 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[0].list_id
);
462 EXPECT_EQ(memcmp(&full_hashes
[1].hash
,
463 "00112233445566778899aabbccddeeff",
464 sizeof(SBFullHash
)), 0);
465 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[1].list_id
);
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
);
472 TEST(SafeBrowsingProtocolParsingTest
, TestGetHashWithUnknownList
) {
473 std::string
hash_response(base::StringPrintf(
476 "12345678901234567890123456789012"
477 "googpub-phish-shavar:32:1\n"
478 "09876543210987654321098765432109",
480 std::vector
<SBFullHashResult
> full_hashes
;
481 base::TimeDelta cache_lifetime
;
482 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response
.data(),
483 hash_response
.size(),
487 ASSERT_EQ(1U, full_hashes
.size());
488 EXPECT_EQ(memcmp("12345678901234567890123456789012",
489 &full_hashes
[0].hash
, sizeof(SBFullHash
)), 0);
490 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
492 hash_response
+= base::StringPrintf(
494 "abcdefghijklmnopqrstuvwxyz123457",
495 kDefaultMalwareList
);
497 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response
.data(),
498 hash_response
.size(),
502 EXPECT_EQ(2U, full_hashes
.size());
503 EXPECT_EQ(memcmp("12345678901234567890123456789012",
504 &full_hashes
[0].hash
, sizeof(SBFullHash
)), 0);
505 EXPECT_EQ(safe_browsing_util::PHISH
, full_hashes
[0].list_id
);
506 EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457",
507 &full_hashes
[1].hash
, sizeof(SBFullHash
)), 0);
508 EXPECT_EQ(safe_browsing_util::MALWARE
, full_hashes
[1].list_id
);
511 TEST(SafeBrowsingProtocolParsingTest
, TestFormatHash
) {
512 std::vector
<SBPrefix
> prefixes
;
513 prefixes
.push_back(0x34333231);
514 prefixes
.push_back(0x64636261);
515 prefixes
.push_back(0x73727170);
517 EXPECT_EQ("4:12\n1234abcdpqrs", safe_browsing::FormatGetHash(prefixes
));
520 TEST(SafeBrowsingProtocolParsingTest
, TestReset
) {
521 std::string
update("n:1800\ni:phishy\nr:pleasereset\n");
524 size_t next_update
= 0;
525 std::vector
<SBChunkDelete
> deletes
;
526 std::vector
<ChunkUrl
> urls
;
527 EXPECT_TRUE(safe_browsing::ParseUpdate(update
.data(), update
.size(),
528 &next_update
, &reset
,
533 // The SafeBrowsing service will occasionally send zero length chunks so that
534 // client requests will have longer contiguous chunk number ranges, and thus
535 // reduce the request size.
536 TEST(SafeBrowsingProtocolParsingTest
, TestZeroSizeAddChunk
) {
537 const char kEmptyAddChunk
[] = {
538 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order.
539 '\x08', // field 1, wire format varint
540 '\x02', // chunk_number varint 2
543 ScopedVector
<SBChunkData
> chunks
;
544 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptyAddChunk
, sizeof(kEmptyAddChunk
),
546 ASSERT_EQ(1U, chunks
.size());
547 EXPECT_EQ(2, chunks
[0]->ChunkNumber());
548 EXPECT_TRUE(chunks
[0]->IsAdd());
549 EXPECT_FALSE(chunks
[0]->IsSub());
550 EXPECT_TRUE(chunks
[0]->IsPrefix());
551 EXPECT_FALSE(chunks
[0]->IsFullHash());
552 EXPECT_EQ(0U, chunks
[0]->PrefixCount());
554 // Now test a zero size chunk in between normal chunks.
556 const char kAddChunks
[] = {
557 '\0', '\0', '\0', '\x0C', // 32-bit payload length in network byte order.
558 '\x08', // field 1, wire format varint
559 '\x01', // chunk_number varint 1
560 '\x22', // field 4, wire format length-delimited
561 '\x08', // varint length 8
563 '1', '1', '1', '1', // 4-byte prefixes
566 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order.
567 '\x08', // field 1, wire format varint
568 '\x02', // chunk_number varint 2
570 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
571 '\x08', // field 1, wire format varint
572 '\x03', // chunk_number varint 3
573 '\x22', // field 4, wire format length-delimited
574 '\x04', // varint length 8
575 'p', 'p', 'p', 'p', // 4-byte prefixes
577 EXPECT_TRUE(safe_browsing::ParseChunk(kAddChunks
, sizeof(kAddChunks
),
579 ASSERT_EQ(3U, chunks
.size());
581 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
582 EXPECT_TRUE(chunks
[0]->IsAdd());
583 EXPECT_FALSE(chunks
[0]->IsSub());
584 EXPECT_TRUE(chunks
[0]->IsPrefix());
585 EXPECT_FALSE(chunks
[0]->IsFullHash());
586 ASSERT_EQ(2U, chunks
[0]->PrefixCount());
587 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
588 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
590 EXPECT_EQ(2, chunks
[1]->ChunkNumber());
591 EXPECT_TRUE(chunks
[1]->IsAdd());
592 EXPECT_FALSE(chunks
[1]->IsSub());
593 EXPECT_TRUE(chunks
[1]->IsPrefix());
594 EXPECT_FALSE(chunks
[1]->IsFullHash());
595 EXPECT_EQ(0U, chunks
[1]->PrefixCount());
597 EXPECT_EQ(3, chunks
[2]->ChunkNumber());
598 EXPECT_TRUE(chunks
[2]->IsAdd());
599 EXPECT_FALSE(chunks
[2]->IsSub());
600 EXPECT_TRUE(chunks
[2]->IsPrefix());
601 EXPECT_FALSE(chunks
[2]->IsFullHash());
602 ASSERT_EQ(1U, chunks
[2]->PrefixCount());
603 EXPECT_EQ(0x70707070U
, chunks
[2]->PrefixAt(0)); // pppp
606 // Test parsing a zero sized sub chunk.
607 TEST(SafeBrowsingProtocolParsingTest
, TestZeroSizeSubChunk
) {
608 const char kEmptySubChunk
[] = {
609 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order.
610 '\x08', // field 1, wire format varint
611 '\x02', // chunk_number varint 2
612 '\x10', // field 2, wire format varint
613 '\x01', // enum ChunkType == SUB
616 ScopedVector
<SBChunkData
> chunks
;
617 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptySubChunk
, sizeof(kEmptySubChunk
),
619 ASSERT_EQ(1U, chunks
.size());
620 EXPECT_EQ(2, chunks
[0]->ChunkNumber());
621 EXPECT_FALSE(chunks
[0]->IsAdd());
622 EXPECT_TRUE(chunks
[0]->IsSub());
623 EXPECT_TRUE(chunks
[0]->IsPrefix());
624 EXPECT_FALSE(chunks
[0]->IsFullHash());
625 EXPECT_EQ(0U, chunks
[0]->PrefixCount());
627 // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
629 const char kSubChunks
[] = {
630 '\0', '\0', '\0', '\x12', // 32-bit payload length in network byte order.
631 '\x08', // field 1, wire format varint
632 '\x01', // chunk_number varint 1
633 '\x10', // field 2, wire format varint
634 '\x01', // enum ChunkType == SUB
635 '\x22', // field 4, wire format length-delimited
636 '\x08', // varint length 8
637 '1', '1', '1', '1', // 4-byte prefixes
639 '\x2a', // field 5, wire format length-delimited
640 '\x02', // varint length 2 (2 add-chunk numbers)
641 '\x07', '\x09', // varint 7, varint 9
643 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order.
644 '\x08', // field 1, wire format varint
645 '\x02', // chunk_number varint 2
646 '\x10', // field 2, wire format varint
647 '\x01', // enum ChunkType == SUB
649 '\0', '\0', '\0', '\x0D', // 32-bit payload length in network byte order.
650 '\x08', // field 1, wire format varint
651 '\x03', // chunk_number varint 3
652 '\x10', // field 2, wire format varint
653 '\x01', // enum ChunkType == SUB
654 '\x22', // field 4, wire format length-delimited
655 '\x04', // varint length 8
656 'p', 'p', 'p', 'p', // 4-byte prefix
657 '\x2a', // field 5, wire format length-delimited
658 '\x01', // varint length 1 (1 add-chunk numbers)
662 EXPECT_TRUE(safe_browsing::ParseChunk(kSubChunks
, sizeof(kSubChunks
),
664 ASSERT_EQ(3U, chunks
.size());
666 EXPECT_EQ(1, chunks
[0]->ChunkNumber());
667 EXPECT_FALSE(chunks
[0]->IsAdd());
668 EXPECT_TRUE(chunks
[0]->IsSub());
669 EXPECT_TRUE(chunks
[0]->IsPrefix());
670 EXPECT_FALSE(chunks
[0]->IsFullHash());
671 ASSERT_EQ(2U, chunks
[0]->PrefixCount());
672 EXPECT_EQ(0x31313131U
, chunks
[0]->PrefixAt(0)); // 1111
673 EXPECT_EQ(7, chunks
[0]->AddChunkNumberAt(0));
674 EXPECT_EQ(0x32323232U
, chunks
[0]->PrefixAt(1)); // 2222
675 EXPECT_EQ(9, chunks
[0]->AddChunkNumberAt(1));
677 EXPECT_EQ(2, chunks
[1]->ChunkNumber());
678 EXPECT_FALSE(chunks
[0]->IsAdd());
679 EXPECT_TRUE(chunks
[0]->IsSub());
680 EXPECT_TRUE(chunks
[1]->IsPrefix());
681 EXPECT_FALSE(chunks
[1]->IsFullHash());
682 EXPECT_EQ(0U, chunks
[1]->PrefixCount());
684 EXPECT_EQ(3, chunks
[2]->ChunkNumber());
685 EXPECT_FALSE(chunks
[0]->IsAdd());
686 EXPECT_TRUE(chunks
[0]->IsSub());
687 EXPECT_TRUE(chunks
[2]->IsPrefix());
688 EXPECT_FALSE(chunks
[2]->IsFullHash());
689 ASSERT_EQ(1U, chunks
[2]->PrefixCount());
690 EXPECT_EQ(0x70707070U
, chunks
[2]->PrefixAt(0)); // pppp
691 EXPECT_EQ(11, chunks
[2]->AddChunkNumberAt(0));