Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: chrome/browser/safe_browsing/protocol_parser.cc

Issue 8873004: Fix safe-browsing sub parsing for download whitelist. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/protocol_parser.h ('k') | chrome/browser/safe_browsing/protocol_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698