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 |