Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Parse the data returned from the SafeBrowsing v2.1 protocol response. | 5 // Parse the data returned from the SafeBrowsing v2.1 protocol response. |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 list_name == safe_browsing_util::kDownloadWhiteList) { | 339 list_name == safe_browsing_util::kDownloadWhiteList) { |
| 340 // These lists only contain prefixes, no HOSTKEY and COUNT. | 340 // These lists only contain prefixes, no HOSTKEY and COUNT. |
| 341 DCHECK_EQ(0, remaining % hash_len); | 341 DCHECK_EQ(0, remaining % hash_len); |
| 342 prefix_count = remaining / hash_len; | 342 prefix_count = remaining / hash_len; |
| 343 SBChunkHost chunk_host; | 343 SBChunkHost chunk_host; |
| 344 chunk_host.host = 0; | 344 chunk_host.host = 0; |
| 345 chunk_host.entry = SBEntry::Create(type, prefix_count); | 345 chunk_host.entry = SBEntry::Create(type, prefix_count); |
| 346 hosts->push_back(chunk_host); | 346 hosts->push_back(chunk_host); |
| 347 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) | 347 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) |
| 348 return false; | 348 return false; |
| 349 DCHECK_GE(remaining, 0); | |
| 349 } else { | 350 } else { |
| 350 SBPrefix host; | 351 SBPrefix host; |
| 351 const int min_size = sizeof(SBPrefix) + 1; | 352 const int min_size = sizeof(SBPrefix) + 1; |
| 352 while (remaining >= min_size) { | 353 while (remaining >= min_size) { |
| 353 ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); | 354 if (!ReadHostAndPrefixCount(&chunk_data, &remaining, |
| 355 &host, &prefix_count)) { | |
| 356 return false; | |
| 357 } | |
| 358 DCHECK_GE(remaining, 0); | |
| 354 SBChunkHost chunk_host; | 359 SBChunkHost chunk_host; |
| 355 chunk_host.host = host; | 360 chunk_host.host = host; |
| 356 chunk_host.entry = SBEntry::Create(type, prefix_count); | 361 chunk_host.entry = SBEntry::Create(type, prefix_count); |
| 357 hosts->push_back(chunk_host); | 362 hosts->push_back(chunk_host); |
| 358 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, | 363 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, |
| 359 prefix_count)) | 364 prefix_count)) |
| 360 return false; | 365 return false; |
| 366 DCHECK_GE(remaining, 0); | |
| 361 } | 367 } |
| 362 } | 368 } |
| 363 return remaining == 0; | 369 return remaining == 0; |
| 364 } | 370 } |
| 365 | 371 |
| 366 bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name, | 372 bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name, |
| 367 const char* data, | 373 const char* data, |
| 368 int data_len, | 374 int data_len, |
| 369 int hash_len, | 375 int hash_len, |
| 370 std::deque<SBChunkHost>* hosts) { | 376 std::deque<SBChunkHost>* hosts) { |
| 371 int remaining = data_len; | 377 int remaining = data_len; |
| 372 const char* chunk_data = data; | 378 const char* chunk_data = data; |
| 373 int prefix_count; | 379 int prefix_count; |
| 374 SBEntry::Type type = hash_len == sizeof(SBPrefix) ? | 380 SBEntry::Type type = hash_len == sizeof(SBPrefix) ? |
| 375 SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH; | 381 SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH; |
| 376 | 382 |
| 377 if (list_name == safe_browsing_util::kBinHashList) { | 383 if (list_name == safe_browsing_util::kBinHashList || |
| 384 list_name == safe_browsing_util::kDownloadWhiteList) { | |
| 378 SBChunkHost chunk_host; | 385 SBChunkHost chunk_host; |
| 379 // Set host to 0 and it won't be used for kBinHashList. | 386 // Set host to 0 and it won't be used for kBinHashList. |
| 380 chunk_host.host = 0; | 387 chunk_host.host = 0; |
| 381 // kBinHashList only contains (add_chunk_number, prefix) pairs, no HOSTKEY | 388 // kBinHashList only contains (add_chunk_number, prefix) pairs, no HOSTKEY |
| 382 // and COUNT. |add_chunk_number| is int32. | 389 // and COUNT. |add_chunk_number| is int32. |
| 383 prefix_count = remaining / (sizeof(int32) + hash_len); | 390 prefix_count = remaining / (sizeof(int32) + hash_len); |
| 384 chunk_host.entry = SBEntry::Create(type, prefix_count); | 391 chunk_host.entry = SBEntry::Create(type, prefix_count); |
| 385 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) | 392 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) |
| 386 return false; | 393 return false; |
| 394 DCHECK_GE(remaining, 0); | |
| 387 hosts->push_back(chunk_host); | 395 hosts->push_back(chunk_host); |
| 388 } else { | 396 } else { |
| 389 SBPrefix host; | 397 SBPrefix host; |
| 390 const int min_size = 2 * sizeof(SBPrefix) + 1; | 398 const int min_size = 2 * sizeof(SBPrefix) + 1; |
| 391 while (remaining >= min_size) { | 399 while (remaining >= min_size) { |
| 392 ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); | 400 if (!ReadHostAndPrefixCount(&chunk_data, &remaining, |
| 401 &host, &prefix_count)) { | |
| 402 return false; | |
| 403 } | |
| 404 DCHECK_GE(remaining, 0); | |
| 393 SBChunkHost chunk_host; | 405 SBChunkHost chunk_host; |
| 394 chunk_host.host = host; | 406 chunk_host.host = host; |
| 395 chunk_host.entry = SBEntry::Create(type, prefix_count); | 407 chunk_host.entry = SBEntry::Create(type, prefix_count); |
| 396 hosts->push_back(chunk_host); | 408 hosts->push_back(chunk_host); |
| 397 if (prefix_count == 0) { | 409 if (prefix_count == 0) { |
| 398 // There is only an add chunk number (no prefixes). | 410 // There is only an add chunk number (no prefixes). |
| 399 chunk_host.entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining)); | 411 int chunk_id; |
| 412 if (!ReadChunkId(&chunk_data, &remaining, &chunk_id)) | |
| 413 return false; | |
| 414 DCHECK_GE(remaining, 0); | |
| 415 chunk_host.entry->set_chunk_id(chunk_id); | |
| 400 continue; | 416 continue; |
| 401 } | 417 } |
| 402 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, | 418 if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, |
| 403 prefix_count)) | 419 prefix_count)) |
| 404 return false; | 420 return false; |
| 421 DCHECK_GE(remaining, 0); | |
| 405 } | 422 } |
| 406 } | 423 } |
| 407 return remaining == 0; | 424 return remaining == 0; |
| 408 } | 425 } |
| 409 | 426 |
| 410 void SafeBrowsingProtocolParser::ReadHostAndPrefixCount( | 427 bool SafeBrowsingProtocolParser::ReadHostAndPrefixCount( |
| 411 const char** data, int* remaining, SBPrefix* host, int* count) { | 428 const char** data, int* remaining, SBPrefix* host, int* count) { |
| 429 if (static_cast<size_t>(*remaining) < sizeof(SBPrefix) + 1) | |
| 430 return false; | |
| 412 // Next 4 bytes are the host prefix. | 431 // Next 4 bytes are the host prefix. |
| 413 memcpy(host, *data, sizeof(SBPrefix)); | 432 memcpy(host, *data, sizeof(SBPrefix)); |
| 414 *data += sizeof(SBPrefix); | 433 *data += sizeof(SBPrefix); |
| 415 *remaining -= sizeof(SBPrefix); | 434 *remaining -= sizeof(SBPrefix); |
| 416 | 435 |
| 417 // Next 1 byte is the prefix count (could be zero, but never negative). | 436 // Next 1 byte is the prefix count (could be zero, but never negative). |
| 418 *count = static_cast<unsigned char>(**data); | 437 *count = static_cast<unsigned char>(**data); |
| 419 *data += 1; | 438 *data += 1; |
| 420 *remaining -= 1; | 439 *remaining -= 1; |
| 440 DCHECK_GE(*remaining, 0); | |
| 441 return true; | |
| 421 } | 442 } |
| 422 | 443 |
| 423 int SafeBrowsingProtocolParser::ReadChunkId( | 444 bool SafeBrowsingProtocolParser::ReadChunkId( |
| 424 const char** data, int* remaining) { | 445 const char** data, int* remaining, int* chunk_id) { |
| 425 int chunk_number; | 446 // Protocol says four bytes, not sizeof(int). Make sure those |
| 426 memcpy(&chunk_number, *data, sizeof(chunk_number)); | 447 // values are the same. |
| 427 *data += sizeof(chunk_number); | 448 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
| |
| 428 *remaining -= sizeof(chunk_number); | 449 if (static_cast<size_t>(*remaining) < sizeof(*chunk_id)) |
| 429 return htonl(chunk_number); | 450 return false; |
| 451 memcpy(chunk_id, *data, sizeof(*chunk_id)); | |
| 452 *data += sizeof(*chunk_id); | |
| 453 *remaining -= sizeof(*chunk_id); | |
| 454 *chunk_id = htonl(*chunk_id); | |
| 455 DCHECK_GE(*remaining, 0); | |
| 456 return true; | |
| 430 } | 457 } |
| 431 | 458 |
| 432 bool SafeBrowsingProtocolParser::ReadPrefixes( | 459 bool SafeBrowsingProtocolParser::ReadPrefixes( |
| 433 const char** data, int* remaining, SBEntry* entry, int count) { | 460 const char** data, int* remaining, SBEntry* entry, int count) { |
| 434 int hash_len = entry->HashLen(); | 461 int hash_len = entry->HashLen(); |
| 435 for (int i = 0; i < count; ++i) { | 462 for (int i = 0; i < count; ++i) { |
| 436 if (entry->IsSub()) { | 463 if (entry->IsSub()) { |
| 437 entry->SetChunkIdAtPrefix(i, ReadChunkId(data, remaining)); | 464 int chunk_id; |
| 438 if (*remaining <= 0) | 465 if (!ReadChunkId(data, remaining, &chunk_id)) |
| 439 return false; | 466 return false; |
| 467 DCHECK_GE(*remaining, 0); | |
| 468 entry->SetChunkIdAtPrefix(i, chunk_id); | |
| 440 } | 469 } |
| 441 | 470 |
| 471 if (*remaining < hash_len) | |
| 472 return false; | |
| 442 if (entry->IsPrefix()) { | 473 if (entry->IsPrefix()) { |
| 474 DCHECK_EQ(hash_len, (int)sizeof(SBPrefix)); | |
| 443 entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data)); | 475 entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data)); |
| 444 } else { | 476 } else { |
| 477 DCHECK_EQ(hash_len, (int)sizeof(SBFullHash)); | |
| 445 entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data)); | 478 entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data)); |
| 446 } | 479 } |
| 447 *data += hash_len; | 480 *data += hash_len; |
| 448 *remaining -= hash_len; | 481 *remaining -= hash_len; |
| 449 if (*remaining < 0) | 482 DCHECK_GE(*remaining, 0); |
| 450 return false; | |
| 451 } | 483 } |
| 452 | 484 |
| 453 return true; | 485 return true; |
| 454 } | 486 } |
| 455 | 487 |
| 456 bool SafeBrowsingProtocolParser::ParseNewKey(const char* chunk_data, | 488 bool SafeBrowsingProtocolParser::ParseNewKey(const char* chunk_data, |
| 457 int chunk_length, | 489 int chunk_length, |
| 458 std::string* client_key, | 490 std::string* client_key, |
| 459 std::string* wrapped_key) { | 491 std::string* wrapped_key) { |
| 460 DCHECK(client_key && wrapped_key); | 492 DCHECK(client_key && wrapped_key); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 487 | 519 |
| 488 data += line.size() + 1; | 520 data += line.size() + 1; |
| 489 remaining -= static_cast<int>(line.size()) + 1; | 521 remaining -= static_cast<int>(line.size()) + 1; |
| 490 } | 522 } |
| 491 | 523 |
| 492 if (client_key->empty() || wrapped_key->empty()) | 524 if (client_key->empty() || wrapped_key->empty()) |
| 493 return false; | 525 return false; |
| 494 | 526 |
| 495 return true; | 527 return true; |
| 496 } | 528 } |
| OLD | NEW |