summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-12 19:24:21 +0000
committerlzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-12 19:24:21 +0000
commitf5ce36af4ed345203bed9312bb2a2f16a900a6c9 (patch)
tree81bdf7ba1f3de41fb999fb315188b43ce6fbccd2
parent9cb116d30b6d6a52f11270abf7cea80bfa7fc738 (diff)
downloadchromium_src-f5ce36af4ed345203bed9312bb2a2f16a900a6c9.zip
chromium_src-f5ce36af4ed345203bed9312bb2a2f16a900a6c9.tar.gz
chromium_src-f5ce36af4ed345203bed9312bb2a2f16a900a6c9.tar.bz2
Parse binhash sent from safebrowsing server.
The binhash will be in this format for add-data ans sub-data: ADD-DATA = (PREFIX)+ PREFIX = <HASHLEN unsigned bytes> SUB-DATA = (ADDCHUNKNUM PREFIX)+ ADDCHUNKNUM = <4 byte unsigned integer in network byte order> PREFIX = <HASHLEN unsigned bytes> BUG=60822 TEST=safe_browsing_database_unittest.cc,protocol_parser_unittest.cc Review URL: http://codereview.chromium.org/6025002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71213 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/safe_browsing/protocol_manager.cc2
-rw-r--r--chrome/browser/safe_browsing/protocol_parser.cc140
-rw-r--r--chrome/browser/safe_browsing/protocol_parser.h18
-rw-r--r--chrome/browser/safe_browsing/protocol_parser_unittest.cc301
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database_unittest.cc133
5 files changed, 443 insertions, 151 deletions
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index 69f8583..26abb9a 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -417,7 +417,7 @@ bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url,
scoped_ptr<SBChunkList> chunks(new SBChunkList);
UMA_HISTOGRAM_COUNTS("SB2.ChunkSize", length);
update_size_ += length;
- if (!parser.ParseChunk(data, length,
+ if (!parser.ParseChunk(chunk_url.list_name, data, length,
client_key_, chunk_url.mac,
&re_key, chunks.get())) {
#ifndef NDEBUG
diff --git a/chrome/browser/safe_browsing/protocol_parser.cc b/chrome/browser/safe_browsing/protocol_parser.cc
index 681253a..c8d1691 100644
--- a/chrome/browser/safe_browsing/protocol_parser.cc
+++ b/chrome/browser/safe_browsing/protocol_parser.cc
@@ -5,6 +5,7 @@
// Parse the data returned from the SafeBrowsing v2.1 protocol response.
#include "chrome/browser/safe_browsing/protocol_parser.h"
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "build/build_config.h"
@@ -245,7 +246,8 @@ bool SafeBrowsingProtocolParser::ParseUpdate(
return true;
}
-bool SafeBrowsingProtocolParser::ParseChunk(const char* data,
+bool SafeBrowsingProtocolParser::ParseChunk(const std::string& list_name,
+ const char* data,
int length,
const std::string& key,
const std::string& mac,
@@ -299,12 +301,12 @@ bool SafeBrowsingProtocolParser::ParseChunk(const char* data,
if (cmd_parts[0] == "a") {
chunks->back().is_add = true;
- if (!ParseAddChunk(chunk_data, chunk_len, hash_len,
+ if (!ParseAddChunk(list_name, chunk_data, chunk_len, hash_len,
&chunks->back().hosts))
return false; // Parse error.
} else if (cmd_parts[0] == "s") {
chunks->back().is_add = false;
- if (!ParseSubChunk(chunk_data, chunk_len, hash_len,
+ if (!ParseSubChunk(list_name, chunk_data, chunk_len, hash_len,
&chunks->back().hosts))
return false; // Parse error.
} else {
@@ -322,85 +324,88 @@ bool SafeBrowsingProtocolParser::ParseChunk(const char* data,
return true;
}
-bool SafeBrowsingProtocolParser::ParseAddChunk(
- const char* data, int data_len, int hash_len,
- std::deque<SBChunkHost>* hosts) {
-
- int remaining = data_len;
+bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name,
+ const char* data,
+ int data_len,
+ int hash_len,
+ std::deque<SBChunkHost>* hosts) {
const char* chunk_data = data;
- const int min_size = sizeof(SBPrefix) + 1;
-
- while (remaining >= min_size) {
+ int remaining = data_len;
+ int prefix_count;
+ SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
+ SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH;
+
+ if (list_name == safe_browsing_util::kBinHashList) {
+ // kBinHashList only contains prefixes, no HOSTKEY and COUNT.
+ DCHECK_EQ(0, remaining % hash_len);
+ prefix_count = remaining / hash_len;
+ SBChunkHost chunk_host;
+ chunk_host.host = 0;
+ chunk_host.entry = SBEntry::Create(type, prefix_count);
+ hosts->push_back(chunk_host);
+ if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count))
+ return false;
+ } else {
SBPrefix host;
- int prefix_count;
- ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
- SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
- SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH;
- SBEntry* entry;
- int index_start = 0;
-
- // If a host has more than 255 prefixes, then subsequent entries are used.
- // Check if this is the case, and if so put them in one SBEntry since the
- // database code assumes that all prefixes from the same host and chunk are
- // in one SBEntry.
- if (!hosts->empty() && hosts->back().host == host &&
- hosts->back().entry->HashLen() == hash_len) {
- // Reuse the SBChunkHost, but need to create a new SBEntry since we have
- // more prefixes.
- index_start = hosts->back().entry->prefix_count();
- entry = hosts->back().entry->Enlarge(prefix_count);
- hosts->back().entry = entry;
- } else {
- entry = SBEntry::Create(type, prefix_count);
+ const int min_size = sizeof(SBPrefix) + 1;
+ while (remaining >= min_size) {
+ ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
SBChunkHost chunk_host;
chunk_host.host = host;
- chunk_host.entry = entry;
+ chunk_host.entry = SBEntry::Create(type, prefix_count);
hosts->push_back(chunk_host);
+ if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry,
+ prefix_count))
+ return false;
}
-
- if (!ReadPrefixes(&chunk_data, &remaining, entry, prefix_count,
- index_start))
- return false;
}
-
return remaining == 0;
}
-bool SafeBrowsingProtocolParser::ParseSubChunk(
- const char* data, int data_len, int hash_len,
- std::deque<SBChunkHost>* hosts) {
-
+bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name,
+ const char* data,
+ int data_len,
+ int hash_len,
+ std::deque<SBChunkHost>* hosts) {
int remaining = data_len;
const char* chunk_data = data;
- const int min_size = 2 * sizeof(SBPrefix) + 1;
-
- while (remaining >= min_size) {
- SBPrefix host;
- int prefix_count;
- ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
- SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
- SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH;
- SBEntry* entry = SBEntry::Create(type, prefix_count);
+ int prefix_count;
+ SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
+ SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH;
+ if (list_name == safe_browsing_util::kBinHashList) {
SBChunkHost chunk_host;
- chunk_host.host = host;
- chunk_host.entry = entry;
+ // Set host to 0 and it won't be used for kBinHashList.
+ chunk_host.host = 0;
+ // kBinHashList only contains (add_chunk_number, prefix) pairs, no HOSTKEY
+ // and COUNT. |add_chunk_number| is int32.
+ prefix_count = remaining / (sizeof(int32) + hash_len);
+ chunk_host.entry = SBEntry::Create(type, prefix_count);
+ if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count))
+ return false;
hosts->push_back(chunk_host);
-
- if (prefix_count == 0) {
- // There is only an add chunk number (no prefixes).
- entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining));
- continue;
+ } else {
+ SBPrefix host;
+ const int min_size = 2 * sizeof(SBPrefix) + 1;
+ while (remaining >= min_size) {
+ ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
+ SBChunkHost chunk_host;
+ chunk_host.host = host;
+ chunk_host.entry = SBEntry::Create(type, prefix_count);
+ hosts->push_back(chunk_host);
+ if (prefix_count == 0) {
+ // There is only an add chunk number (no prefixes).
+ chunk_host.entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining));
+ continue;
+ }
+ if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry,
+ prefix_count))
+ return false;
}
-
- if (!ReadPrefixes(&chunk_data, &remaining, entry, prefix_count, 0))
- return false;
}
-
return remaining == 0;
}
-
void SafeBrowsingProtocolParser::ReadHostAndPrefixCount(
const char** data, int* remaining, SBPrefix* host, int* count) {
// Next 4 bytes are the host prefix.
@@ -424,22 +429,19 @@ int SafeBrowsingProtocolParser::ReadChunkId(
}
bool SafeBrowsingProtocolParser::ReadPrefixes(
- const char** data, int* remaining, SBEntry* entry, int count,
- int index_start) {
+ const char** data, int* remaining, SBEntry* entry, int count) {
int hash_len = entry->HashLen();
for (int i = 0; i < count; ++i) {
if (entry->IsSub()) {
- entry->SetChunkIdAtPrefix(index_start + i, ReadChunkId(data, remaining));
+ entry->SetChunkIdAtPrefix(i, ReadChunkId(data, remaining));
if (*remaining <= 0)
return false;
}
if (entry->IsPrefix()) {
- entry->SetPrefixAt(index_start + i,
- *reinterpret_cast<const SBPrefix*>(*data));
+ entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data));
} else {
- entry->SetFullHashAt(index_start + i,
- *reinterpret_cast<const SBFullHash*>(*data));
+ entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data));
}
*data += hash_len;
*remaining -= hash_len;
diff --git a/chrome/browser/safe_browsing/protocol_parser.h b/chrome/browser/safe_browsing/protocol_parser.h
index 9384f07..d074f2a 100644
--- a/chrome/browser/safe_browsing/protocol_parser.h
+++ b/chrome/browser/safe_browsing/protocol_parser.h
@@ -75,7 +75,8 @@ class SafeBrowsingProtocolParser {
// Parse the response from a chunk URL request and returns the hosts/prefixes
// for adds and subs in "chunks". Returns 'true' on successful parsing,
// 'false' otherwise. Any result should be ignored when a parse has failed.
- bool ParseChunk(const char* chunk_data,
+ bool ParseChunk(const std::string& list_name,
+ const char* chunk_data,
int chunk_len,
const std::string& key,
const std::string& mac,
@@ -102,22 +103,25 @@ class SafeBrowsingProtocolParser {
std::string* wrapped_key);
private:
- bool ParseAddChunk(const char* data,
+ bool ParseAddChunk(const std::string& list_name,
+ const char* data,
int data_len,
int hash_len,
std::deque<SBChunkHost>* hosts);
- bool ParseSubChunk(const char* data,
+ bool ParseSubChunk(const std::string& list_name,
+ const char* data,
int data_len,
int hash_len,
std::deque<SBChunkHost>* hosts);
// Helper functions used by ParseAddChunk and ParseSubChunk.
- static void ReadHostAndPrefixCount(
- const char** data, int* remaining, SBPrefix* host, int* count);
+ static void ReadHostAndPrefixCount(const char** data,
+ int* remaining,
+ SBPrefix* host,
+ int* count);
static int ReadChunkId(const char** data, int* remaining);
static bool ReadPrefixes(
- const char** data, int* remaining, SBEntry* entry, int count,
- int index_start);
+ const char** data, int* remaining, SBEntry* entry, int count);
// The name of the current list
std::string list_name_;
diff --git a/chrome/browser/safe_browsing/protocol_parser_unittest.cc b/chrome/browser/safe_browsing/protocol_parser_unittest.cc
index f32a21c..d52b3d6 100644
--- a/chrome/browser/safe_browsing/protocol_parser_unittest.cc
+++ b/chrome/browser/safe_browsing/protocol_parser_unittest.cc
@@ -6,9 +6,9 @@
#include "base/string_util.h"
#include "chrome/browser/safe_browsing/protocol_parser.h"
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-
// Test parsing one add chunk.
TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) {
std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999");
@@ -18,14 +18,16 @@ TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(add_chunk.data(),
- static_cast<int>(add_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+ EXPECT_EQ(chunks[0].hosts.size(), 3U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
SBEntry* entry = chunks[0].hosts[0].entry;
@@ -69,14 +71,16 @@ TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(add_chunk.data(),
- static_cast<int>(add_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
SBEntry* entry = chunks[0].hosts[0].entry;
@@ -98,14 +102,16 @@ TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(add_chunk.data(),
- static_cast<int>(add_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(2));
+ EXPECT_EQ(chunks.size(), 2U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+ EXPECT_EQ(chunks[0].hosts.size(), 3U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
SBEntry* entry = chunks[0].hosts[0].entry;
@@ -132,7 +138,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) {
EXPECT_EQ(chunks[1].chunk_number, 2);
- EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[1].hosts.size(), 1U);
EXPECT_EQ(chunks[1].hosts[0].host, 0x35353535);
entry = chunks[1].hosts[0].entry;
@@ -158,34 +164,77 @@ TEST(SafeBrowsingProtocolParsingTest, TestAddBigChunk) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(add_chunk.data(),
- static_cast<int>(add_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[0].hosts.size(), 2U);
+
+ const SBChunkHost& host0 = chunks[0].hosts[0];
+ EXPECT_EQ(host0.host, 0x61616161);
+ EXPECT_EQ(host0.entry->prefix_count(), 255);
- const SBChunkHost& host = chunks[0].hosts[0];
- EXPECT_EQ(host.host, 0x61616161);
- EXPECT_EQ(host.entry->prefix_count(), 260);
+ const SBChunkHost& host1 = chunks[0].hosts[1];
+ EXPECT_EQ(host1.host, 0x61616161);
+ EXPECT_EQ(host1.entry->prefix_count(), 5);
}
-// Test to make sure we could deal with truncated chunk.
-TEST(SafeBrowsingProtocolParsingTest, TestTruncatedChunk) {
+// Test to make sure we could deal with truncated bin hash chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestTruncatedBinHashChunk) {
+ // This chunk delares there are 4 prefixes but actually only contains 2.
+ const char add_chunk[] = "a:1:4:16\n11112222";
+ SafeBrowsingProtocolParser parser;
+ bool re_key = false;
+ SBChunkList chunks;
+ bool result = parser.ParseChunk(add_chunk,
+ safe_browsing_util::kBinHashList,
+ static_cast<int>(sizeof(add_chunk)),
+ "", "", &re_key, &chunks);
+ EXPECT_FALSE(result);
+ EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 0U);
+}
+
+// Test to make sure we could deal with truncated malwarelist chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestTruncatedUrlHashChunk) {
// This chunk delares there are 4 prefixes but actually only contains 2.
const char add_chunk[] = "a:1:4:21\naaaa\00411112222";
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
+
+ // For safe_browsing_util::kMalwareList.
bool result = parser.ParseChunk(add_chunk,
+ safe_browsing_util::kMalwareList,
static_cast<int>(sizeof(add_chunk)),
"", "", &re_key, &chunks);
EXPECT_FALSE(result);
EXPECT_FALSE(re_key);
EXPECT_EQ(chunks.size(), 0U);
+
+ // For safe_browsing_util::kPhishingList.
+ result = parser.ParseChunk(add_chunk,
+ safe_browsing_util::kPhishingList,
+ static_cast<int>(sizeof(add_chunk)),
+ "", "", &re_key, &chunks);
+ EXPECT_FALSE(result);
+ EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 0U);
+
+ // For safe_browsing_util::kBinUrlList.
+ result = parser.ParseChunk(add_chunk,
+ safe_browsing_util::kBinUrlList,
+ static_cast<int>(sizeof(add_chunk)),
+ "", "", &re_key, &chunks);
+ EXPECT_FALSE(result);
+ EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 0U);
}
// Test parsing one sub chunk.
@@ -199,14 +248,16 @@ TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(sub_chunk.data(),
- static_cast<int>(sub_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ sub_chunk.data(),
+ static_cast<int>(sub_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 9);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+ EXPECT_EQ(chunks[0].hosts.size(), 3U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
SBEntry* entry = chunks[0].hosts[0].entry;
@@ -258,14 +309,16 @@ TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) {
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(sub_chunk.data(),
- static_cast<int>(sub_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ sub_chunk.data(),
+ static_cast<int>(sub_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
SBEntry* entry = chunks[0].hosts[0].entry;
@@ -298,15 +351,15 @@ TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) {
EXPECT_FALSE(re_key);
EXPECT_FALSE(reset);
EXPECT_EQ(next_query_sec, 1700);
- EXPECT_EQ(deletes.size(), static_cast<size_t>(2));
+ EXPECT_EQ(deletes.size(), 2U);
- EXPECT_EQ(deletes[0].chunk_del.size(), static_cast<size_t>(4));
+ EXPECT_EQ(deletes[0].chunk_del.size(), 4U);
EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7));
EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597));
EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444));
EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999));
- EXPECT_EQ(deletes[1].chunk_del.size(), static_cast<size_t>(3));
+ EXPECT_EQ(deletes[1].chunk_del.size(), 3U);
EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27));
EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42));
EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717));
@@ -345,7 +398,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestRedirects) {
EXPECT_FALSE(re_key);
EXPECT_FALSE(reset);
- EXPECT_EQ(urls.size(), static_cast<size_t>(4));
+ EXPECT_EQ(urls.size(), 4U);
EXPECT_EQ(urls[0].url,
"cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1");
EXPECT_EQ(urls[1].url,
@@ -381,7 +434,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestRedirectsWithMac) {
EXPECT_FALSE(re_key);
EXPECT_FALSE(reset);
- EXPECT_EQ(urls.size(), static_cast<size_t>(2));
+ EXPECT_EQ(urls.size(), 2U);
EXPECT_EQ(urls[0].url,
"s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6501-6505:6501-6505");
EXPECT_EQ(urls[0].mac, "pcY6iVeT9-CBQ3fdAF0rpnKjR1Y=");
@@ -427,7 +480,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestGetHash) {
&full_hashes));
EXPECT_FALSE(re_key);
- EXPECT_EQ(full_hashes.size(), static_cast<size_t>(3));
+ EXPECT_EQ(full_hashes.size(), 3U);
EXPECT_EQ(memcmp(&full_hashes[0].hash,
"00112233445566778899aabbccddeeff",
sizeof(SBFullHash)), 0);
@@ -453,7 +506,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestGetHash) {
&full_hashes));
EXPECT_FALSE(re_key);
- EXPECT_EQ(full_hashes.size(), static_cast<size_t>(3));
+ EXPECT_EQ(full_hashes.size(), 3U);
EXPECT_EQ(memcmp(&full_hashes[0].hash,
"00112233445566778899aabbccddeeff",
sizeof(SBFullHash)), 0);
@@ -500,7 +553,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithMac) {
&re_key,
&full_hashes));
EXPECT_FALSE(re_key);
- EXPECT_EQ(full_hashes.size(), static_cast<size_t>(1));
+ EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_EQ(memcmp(hash_result, &full_hashes[0].hash, sizeof(SBFullHash)), 0);
}
@@ -519,7 +572,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) {
&re_key,
&full_hashes));
- EXPECT_EQ(full_hashes.size(), static_cast<size_t>(1));
+ EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_EQ(memcmp("12345678901234567890123456789012",
&full_hashes[0].hash, sizeof(SBFullHash)), 0);
EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
@@ -534,7 +587,7 @@ TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) {
&re_key,
&full_hashes));
- EXPECT_EQ(full_hashes.size(), static_cast<size_t>(2));
+ EXPECT_EQ(full_hashes.size(), 2U);
EXPECT_EQ(memcmp("12345678901234567890123456789012",
&full_hashes[0].hash, sizeof(SBFullHash)), 0);
EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
@@ -614,38 +667,42 @@ TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) {
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(add_chunk.data(),
- static_cast<int>(add_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(0));
+ EXPECT_EQ(chunks[0].hosts.size(), 0U);
// Now test a zero size chunk in between normal chunks.
chunks.clear();
std::string add_chunks("a:1:4:18\n1234\001abcd5678\001wxyz"
"a:2:4:0\n"
"a:3:4:9\ncafe\001beef");
- result = parser.ParseChunk(add_chunks.data(),
- static_cast<int>(add_chunks.length()),
- "", "", &re_key, &chunks);
+ result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ add_chunks.data(),
+ static_cast<int>(add_chunks.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(3));
+ EXPECT_EQ(chunks.size(), 3U);
// See that each chunk has the right content.
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(2));
+ EXPECT_EQ(chunks[0].hosts.size(), 2U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x34333231);
EXPECT_EQ(chunks[0].hosts[0].entry->PrefixAt(0), 0x64636261);
EXPECT_EQ(chunks[0].hosts[1].host, 0x38373635);
EXPECT_EQ(chunks[0].hosts[1].entry->PrefixAt(0), 0x7a797877);
EXPECT_EQ(chunks[1].chunk_number, 2);
- EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(0));
+ EXPECT_EQ(chunks[1].hosts.size(), 0U);
EXPECT_EQ(chunks[2].chunk_number, 3);
- EXPECT_EQ(chunks[2].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[2].hosts.size(), 1U);
EXPECT_EQ(chunks[2].hosts[0].host, 0x65666163);
EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x66656562);
}
@@ -657,13 +714,15 @@ TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) {
bool re_key = false;
SBChunkList chunks;
- bool result = parser.ParseChunk(sub_chunk.data(),
- static_cast<int>(sub_chunk.length()),
- "", "", &re_key, &chunks);
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ sub_chunk.data(),
+ static_cast<int>(sub_chunk.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
- EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks.size(), 1U);
EXPECT_EQ(chunks[0].chunk_number, 9);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(0));
+ EXPECT_EQ(chunks[0].hosts.size(), 0U);
chunks.clear();
// Test parsing a zero sized sub chunk mixed in with content carrying chunks.
@@ -672,21 +731,23 @@ TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) {
"s:3:4:26\nefgh\0011234pqrscafe\0015678lmno");
sub_chunks[12] = '\0';
- result = parser.ParseChunk(sub_chunks.data(),
- static_cast<int>(sub_chunks.length()),
- "", "", &re_key, &chunks);
+ result = parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ sub_chunks.data(),
+ static_cast<int>(sub_chunks.length()),
+ "", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_EQ(chunks[0].chunk_number, 1);
- EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
EXPECT_EQ(chunks[0].hosts[0].host, 0x64636261);
EXPECT_EQ(chunks[0].hosts[0].entry->prefix_count(), 0);
EXPECT_EQ(chunks[1].chunk_number, 2);
- EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(0));
+ EXPECT_EQ(chunks[1].hosts.size(), 0U);
EXPECT_EQ(chunks[2].chunk_number, 3);
- EXPECT_EQ(chunks[2].hosts.size(), static_cast<size_t>(2));
+ EXPECT_EQ(chunks[2].hosts.size(), 2U);
EXPECT_EQ(chunks[2].hosts[0].host, 0x68676665);
EXPECT_EQ(chunks[2].hosts[0].entry->prefix_count(), 1);
EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x73727170);
@@ -764,8 +825,102 @@ TEST(SafeBrowsingProtocolParsingTest, TestVerifyChunkMac) {
const std::string key("v_aDSz6jI92WeHCOoZ07QA==");
const std::string mac("W9Xp2fUcQ9V66If6Cvsrstpa4Kk=");
- EXPECT_TRUE(parser.ParseChunk(reinterpret_cast<const char*>(chunk),
- sizeof(chunk), key, mac,
- &re_key, &chunks));
+ EXPECT_TRUE(parser.ParseChunk(
+ safe_browsing_util::kMalwareList,
+ reinterpret_cast<const char*>(chunk),
+ sizeof(chunk), key, mac,
+ &re_key, &chunks));
+ EXPECT_FALSE(re_key);
+}
+
+TEST(SafeBrowsingProtocolParsingTest, TestAddBinHashChunks) {
+ std::string add_chunk("a:1:4:16\naaaabbbbccccdddd"
+ "a:2:4:8\n11112222");
+ // Run the parse.
+ SafeBrowsingProtocolParser parser;
+ bool re_key = false;
+ SBChunkList chunks;
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kBinHashList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
+ EXPECT_TRUE(result);
+ EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 2U);
+ EXPECT_EQ(chunks[0].chunk_number, 1);
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+ EXPECT_EQ(chunks[0].hosts[0].host, 0);
+ SBEntry* entry = chunks[0].hosts[0].entry;
+ EXPECT_TRUE(entry->IsAdd());
+ EXPECT_TRUE(entry->IsPrefix());
+ EXPECT_EQ(entry->prefix_count(), 4);
+
+ EXPECT_EQ(chunks[1].chunk_number, 2);
+ EXPECT_EQ(chunks[1].hosts.size(), 1U);
+
+ EXPECT_EQ(chunks[1].hosts[0].host, 0);
+ entry = chunks[1].hosts[0].entry;
+ EXPECT_TRUE(entry->IsAdd());
+ EXPECT_TRUE(entry->IsPrefix());
+ EXPECT_EQ(entry->prefix_count(), 2);
+ EXPECT_EQ(entry->PrefixAt(0), 0x31313131);
+ EXPECT_EQ(entry->PrefixAt(1), 0x32323232);
+}
+
+// Test parsing one add chunk where a hostkey spans several entries.
+TEST(SafeBrowsingProtocolParsingTest, TestAddBigBinHashChunk) {
+ std::string add_chunk("a:1:4:1028\n");
+ for (int i = 0; i < 257; ++i)
+ add_chunk.append(StringPrintf("%04d", i));
+
+ SafeBrowsingProtocolParser parser;
+ bool re_key = false;
+ SBChunkList chunks;
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kBinHashList,
+ add_chunk.data(),
+ static_cast<int>(add_chunk.length()),
+ "", "", &re_key, &chunks);
+ EXPECT_TRUE(result);
+ EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 1U);
+ EXPECT_EQ(chunks[0].chunk_number, 1);
+
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+ const SBChunkHost& host0 = chunks[0].hosts[0];
+ EXPECT_EQ(host0.host, 0);
+ EXPECT_EQ(host0.entry->prefix_count(), 257);
+}
+
+// Test parsing one sub chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) {
+ std::string sub_chunk("s:9:4:16\n1111mmmm2222nnnn");
+
+ // Run the parser.
+ SafeBrowsingProtocolParser parser;
+ bool re_key = false;
+ SBChunkList chunks;
+ bool result = parser.ParseChunk(
+ safe_browsing_util::kBinHashList,
+ sub_chunk.data(),
+ static_cast<int>(sub_chunk.length()),
+ "", "", &re_key, &chunks);
+ EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
+ EXPECT_EQ(chunks.size(), 1U);
+ EXPECT_EQ(chunks[0].chunk_number, 9);
+ EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+ EXPECT_EQ(chunks[0].hosts[0].host, 0);
+ SBEntry* entry = chunks[0].hosts[0].entry;
+ EXPECT_TRUE(entry->IsSub());
+ EXPECT_TRUE(entry->IsPrefix());
+ EXPECT_EQ(entry->prefix_count(), 2);
+ EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131);
+ EXPECT_EQ(entry->PrefixAt(0), 0x6d6d6d6d);
+ EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232);
+ EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e);
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index 249c44c..2b754ef 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -431,7 +431,6 @@ TEST_F(SafeBrowsingDatabaseTest, ListNameForBrowseAndDownload) {
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.push_back(chunk);
-
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
@@ -1290,3 +1289,135 @@ TEST_F(SafeBrowsingDatabaseTest, ContainsDownloadUrl) {
EXPECT_EQ(prefix_hits.size(), 0U);
database_.reset();
}
+
+// Test to make sure we could insert chunk list that
+// contains entries for the same host.
+TEST_F(SafeBrowsingDatabaseTest, SameHostEntriesOkay) {
+ SBChunk chunk;
+
+ // Add a malware add chunk with two entries of the same host.
+ InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
+ "www.evil.com/malware1.html");
+ InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
+ "www.evil.com/malware2.html");
+ SBChunkList chunks;
+ chunks.push_back(chunk);
+
+ // Insert the testing chunks into database.
+ std::vector<SBListChunkRanges> lists;
+ EXPECT_TRUE(database_->UpdateStarted(&lists));
+ database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+ database_->UpdateFinished(true);
+
+ GetListsInfo(&lists);
+ EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
+ EXPECT_EQ("1", lists[0].adds);
+ EXPECT_TRUE(lists[0].subs.empty());
+
+ // Add a phishing add chunk with two entries of the same host.
+ chunk.hosts.clear();
+ InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
+ "www.evil.com/phishing1.html");
+ InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
+ "www.evil.com/phishing2.html");
+ chunks.clear();
+ chunks.push_back(chunk);
+
+ EXPECT_TRUE(database_->UpdateStarted(&lists));
+ database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
+ database_->UpdateFinished(true);
+
+ GetListsInfo(&lists);
+ EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
+ EXPECT_EQ("1", lists[0].adds);
+ EXPECT_EQ(std::string(safe_browsing_util::kPhishingList), lists[1].name);
+ EXPECT_EQ("47", lists[1].adds);
+
+ const Time now = Time::Now();
+ std::vector<SBPrefix> prefixes;
+ std::vector<SBFullHashResult> full_hashes;
+ std::vector<SBPrefix> prefix_hits;
+ std::string matching_list;
+ std::string listname;
+
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/malware1.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/malware2.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/phishing1.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/phishing2.html"),
+ &listname, &prefixes, &full_hashes, now));
+
+ // Test removing a single prefix from the add chunk.
+ // Remove the prefix that added first.
+ chunk.hosts.clear();
+ InsertSubChunkHostPrefixUrl(&chunk, 4, 1, "www.evil.com/",
+ "www.evil.com/malware1.html");
+ chunks.clear();
+ chunks.push_back(chunk);
+ EXPECT_TRUE(database_->UpdateStarted(&lists));
+ database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+ database_->UpdateFinished(true);
+
+ // Remove the prefix that added last.
+ chunk.hosts.clear();
+ InsertSubChunkHostPrefixUrl(&chunk, 5, 47, "www.evil.com/",
+ "www.evil.com/phishing2.html");
+ chunks.clear();
+ chunks.push_back(chunk);
+ EXPECT_TRUE(database_->UpdateStarted(&lists));
+ database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
+ database_->UpdateFinished(true);
+
+ // Verify that the database contains urls expected.
+ EXPECT_FALSE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/malware1.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/malware2.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_TRUE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/phishing1.html"),
+ &listname, &prefixes, &full_hashes, now));
+ EXPECT_FALSE(database_->ContainsBrowseUrl(
+ GURL("http://www.evil.com/phishing2.html"),
+ &listname, &prefixes, &full_hashes, now));
+}
+
+TEST_F(SafeBrowsingDatabaseTest, BinHashEntries) {
+ database_.reset();
+ MessageLoop loop(MessageLoop::TYPE_DEFAULT);
+ SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
+ SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
+ database_.reset(new SafeBrowsingDatabaseNew(browse_store, download_store));
+ database_->Init(database_filename_);
+
+ SBChunkList chunks;
+ SBChunk chunk;
+ // Insert one host.
+ InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x31313131);
+ // Insert a second host, which has the same host prefix as the first one.
+ InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x32323232);
+ chunks.push_back(chunk);
+
+ // Insert the testing chunks into database.
+ std::vector<SBListChunkRanges> lists;
+ EXPECT_TRUE(database_->UpdateStarted(&lists));
+ database_->InsertChunks(safe_browsing_util::kBinHashList, chunks);
+ database_->UpdateFinished(true);
+
+ GetListsInfo(&lists);
+ ASSERT_EQ(4U, lists.size());
+ EXPECT_EQ(std::string(safe_browsing_util::kBinHashList), lists[3].name);
+ EXPECT_EQ("1", lists[3].adds);
+ EXPECT_TRUE(lists[3].subs.empty());
+
+ // TODO(lzheng): Query database and verifies the prefixes once that API
+ // database is available in database.
+ database_.reset();
+}