Chromium Code Reviews| Index: chrome/browser/safe_browsing/protocol_parser.cc |
| diff --git a/chrome/browser/safe_browsing/protocol_parser.cc b/chrome/browser/safe_browsing/protocol_parser.cc |
| index f09a26fbebed18f29da5ea25e700d9c27cea9e57..00756dd302011be1494382952fb3d9aa5b4520dc 100644 |
| --- a/chrome/browser/safe_browsing/protocol_parser.cc |
| +++ b/chrome/browser/safe_browsing/protocol_parser.cc |
| @@ -346,11 +346,16 @@ bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name, |
| hosts->push_back(chunk_host); |
| if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) |
| return false; |
| + DCHECK_GE(remaining, 0); |
| } else { |
| SBPrefix host; |
| const int min_size = sizeof(SBPrefix) + 1; |
| while (remaining >= min_size) { |
| - ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); |
| + if (!ReadHostAndPrefixCount(&chunk_data, &remaining, |
| + &host, &prefix_count)) { |
| + return false; |
| + } |
| + DCHECK_GE(remaining, 0); |
| SBChunkHost chunk_host; |
| chunk_host.host = host; |
| chunk_host.entry = SBEntry::Create(type, prefix_count); |
| @@ -358,6 +363,7 @@ bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name, |
| if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, |
| prefix_count)) |
| return false; |
| + DCHECK_GE(remaining, 0); |
| } |
| } |
| return remaining == 0; |
| @@ -374,7 +380,8 @@ bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name, |
| SBEntry::Type type = hash_len == sizeof(SBPrefix) ? |
| SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH; |
| - if (list_name == safe_browsing_util::kBinHashList) { |
| + if (list_name == safe_browsing_util::kBinHashList || |
| + list_name == safe_browsing_util::kDownloadWhiteList) { |
| SBChunkHost chunk_host; |
| // Set host to 0 and it won't be used for kBinHashList. |
| chunk_host.host = 0; |
| @@ -384,31 +391,43 @@ bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name, |
| chunk_host.entry = SBEntry::Create(type, prefix_count); |
| if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) |
| return false; |
| + DCHECK_GE(remaining, 0); |
| hosts->push_back(chunk_host); |
| } else { |
| SBPrefix host; |
| const int min_size = 2 * sizeof(SBPrefix) + 1; |
| while (remaining >= min_size) { |
| - ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); |
| + if (!ReadHostAndPrefixCount(&chunk_data, &remaining, |
| + &host, &prefix_count)) { |
| + return false; |
| + } |
| + DCHECK_GE(remaining, 0); |
| 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)); |
| + int chunk_id; |
| + if (!ReadChunkId(&chunk_data, &remaining, &chunk_id)) |
| + return false; |
| + DCHECK_GE(remaining, 0); |
| + chunk_host.entry->set_chunk_id(chunk_id); |
| continue; |
| } |
| if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, |
| prefix_count)) |
| return false; |
| + DCHECK_GE(remaining, 0); |
| } |
| } |
| return remaining == 0; |
| } |
| -void SafeBrowsingProtocolParser::ReadHostAndPrefixCount( |
| +bool SafeBrowsingProtocolParser::ReadHostAndPrefixCount( |
| const char** data, int* remaining, SBPrefix* host, int* count) { |
| + if (static_cast<size_t>(*remaining) < sizeof(SBPrefix) + 1) |
| + return false; |
| // Next 4 bytes are the host prefix. |
| memcpy(host, *data, sizeof(SBPrefix)); |
| *data += sizeof(SBPrefix); |
| @@ -418,15 +437,23 @@ void SafeBrowsingProtocolParser::ReadHostAndPrefixCount( |
| *count = static_cast<unsigned char>(**data); |
| *data += 1; |
| *remaining -= 1; |
| + DCHECK_GE(*remaining, 0); |
| + return true; |
| } |
| -int SafeBrowsingProtocolParser::ReadChunkId( |
| - const char** data, int* remaining) { |
| - int chunk_number; |
| - memcpy(&chunk_number, *data, sizeof(chunk_number)); |
| - *data += sizeof(chunk_number); |
| - *remaining -= sizeof(chunk_number); |
| - return htonl(chunk_number); |
| +bool SafeBrowsingProtocolParser::ReadChunkId( |
| + const char** data, int* remaining, int* chunk_id) { |
| + // Protocol says four bytes, not sizeof(int). Make sure those |
| + // values are the same. |
| + DCHECK_EQ(sizeof(*chunk_id), 4u); |
|
noelutz
2011/12/08 03:26:54
good call.
Scott Hess - ex-Googler
2011/12/08 04:12:44
For all that I said "I don't have time to rewrite
|
| + if (static_cast<size_t>(*remaining) < sizeof(*chunk_id)) |
| + return false; |
| + memcpy(chunk_id, *data, sizeof(*chunk_id)); |
| + *data += sizeof(*chunk_id); |
| + *remaining -= sizeof(*chunk_id); |
| + *chunk_id = htonl(*chunk_id); |
| + DCHECK_GE(*remaining, 0); |
| + return true; |
| } |
| bool SafeBrowsingProtocolParser::ReadPrefixes( |
| @@ -434,20 +461,25 @@ bool SafeBrowsingProtocolParser::ReadPrefixes( |
| int hash_len = entry->HashLen(); |
| for (int i = 0; i < count; ++i) { |
| if (entry->IsSub()) { |
| - entry->SetChunkIdAtPrefix(i, ReadChunkId(data, remaining)); |
| - if (*remaining <= 0) |
| + int chunk_id; |
| + if (!ReadChunkId(data, remaining, &chunk_id)) |
| return false; |
| + DCHECK_GE(*remaining, 0); |
| + entry->SetChunkIdAtPrefix(i, chunk_id); |
| } |
| + if (*remaining < hash_len) |
| + return false; |
| if (entry->IsPrefix()) { |
| + DCHECK_EQ(hash_len, (int)sizeof(SBPrefix)); |
| entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data)); |
| } else { |
| + DCHECK_EQ(hash_len, (int)sizeof(SBFullHash)); |
| entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data)); |
| } |
| *data += hash_len; |
| *remaining -= hash_len; |
| - if (*remaining < 0) |
| - return false; |
| + DCHECK_GE(*remaining, 0); |
| } |
| return true; |