OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "chrome/browser/safe_browsing/prefix_set.h" | 5 #include "chrome/browser/safe_browsing/prefix_set.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 | 9 |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 namespace safe_browsing { | 31 namespace safe_browsing { |
32 | 32 |
33 class PrefixSetTest : public PlatformTest { | 33 class PrefixSetTest : public PlatformTest { |
34 protected: | 34 protected: |
35 // Constants for the v1 format. | 35 // Constants for the v1 format. |
36 static const size_t kMagicOffset = 0 * sizeof(uint32); | 36 static const size_t kMagicOffset = 0 * sizeof(uint32); |
37 static const size_t kVersionOffset = 1 * sizeof(uint32); | 37 static const size_t kVersionOffset = 1 * sizeof(uint32); |
38 static const size_t kIndexSizeOffset = 2 * sizeof(uint32); | 38 static const size_t kIndexSizeOffset = 2 * sizeof(uint32); |
39 static const size_t kDeltasSizeOffset = 3 * sizeof(uint32); | 39 static const size_t kDeltasSizeOffset = 3 * sizeof(uint32); |
40 static const size_t kPayloadOffset = 4 * sizeof(uint32); | 40 static const size_t kFullHashesSizeOffset = 4 * sizeof(uint32); |
| 41 static const size_t kPayloadOffset = 5 * sizeof(uint32); |
41 | 42 |
42 // Generate a set of random prefixes to share between tests. For | 43 // Generate a set of random prefixes to share between tests. For |
43 // most tests this generation was a large fraction of the test time. | 44 // most tests this generation was a large fraction of the test time. |
44 // | 45 // |
45 // The set should contain sparse areas where adjacent items are more | 46 // The set should contain sparse areas where adjacent items are more |
46 // than 2^16 apart, and dense areas where adjacent items are less | 47 // than 2^16 apart, and dense areas where adjacent items are less |
47 // than 2^16 apart. | 48 // than 2^16 apart. |
48 static void SetUpTestCase() { | 49 static void SetUpTestCase() { |
49 // Distribute clusters of prefixes. | 50 // Distribute clusters of prefixes. |
50 for (size_t i = 0; i < 250; ++i) { | 51 for (size_t i = 0; i < 250; ++i) { |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 // Test writing and reading an empty set. | 392 // Test writing and reading an empty set. |
392 { | 393 { |
393 std::vector<SBPrefix> prefixes; | 394 std::vector<SBPrefix> prefixes; |
394 PrefixSetBuilder builder(prefixes); | 395 PrefixSetBuilder builder(prefixes); |
395 ASSERT_TRUE(builder.GetPrefixSetNoHashes()->WriteFile(filename)); | 396 ASSERT_TRUE(builder.GetPrefixSetNoHashes()->WriteFile(filename)); |
396 | 397 |
397 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); | 398 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); |
398 ASSERT_TRUE(prefix_set.get()); | 399 ASSERT_TRUE(prefix_set.get()); |
399 CheckPrefixes(*prefix_set, prefixes); | 400 CheckPrefixes(*prefix_set, prefixes); |
400 } | 401 } |
| 402 |
| 403 // Test that full hashes are persisted. |
| 404 { |
| 405 std::vector<SBFullHash> hashes; |
| 406 hashes.push_back(SBFullHashForString("one")); |
| 407 hashes.push_back(SBFullHashForString("two")); |
| 408 hashes.push_back(SBFullHashForString("three")); |
| 409 |
| 410 std::vector<SBPrefix> prefixes(shared_prefixes_); |
| 411 |
| 412 // Remove any collisions from the prefixes. |
| 413 for (size_t i = 0; i < hashes.size(); ++i) { |
| 414 std::vector<SBPrefix>::iterator iter = |
| 415 std::lower_bound(prefixes.begin(), prefixes.end(), hashes[i].prefix); |
| 416 if (iter != prefixes.end() && *iter == hashes[i].prefix) |
| 417 prefixes.erase(iter); |
| 418 } |
| 419 |
| 420 PrefixSetBuilder builder(prefixes); |
| 421 ASSERT_TRUE(builder.GetPrefixSet(hashes)->WriteFile(filename)); |
| 422 |
| 423 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); |
| 424 ASSERT_TRUE(prefix_set.get()); |
| 425 CheckPrefixes(*prefix_set, prefixes); |
| 426 |
| 427 EXPECT_TRUE(prefix_set->Exists(hashes[0])); |
| 428 EXPECT_TRUE(prefix_set->Exists(hashes[1])); |
| 429 EXPECT_TRUE(prefix_set->Exists(hashes[2])); |
| 430 EXPECT_FALSE(prefix_set->PrefixExists(hashes[0].prefix)); |
| 431 EXPECT_FALSE(prefix_set->PrefixExists(hashes[1].prefix)); |
| 432 EXPECT_FALSE(prefix_set->PrefixExists(hashes[2].prefix)); |
| 433 } |
401 } | 434 } |
402 | 435 |
403 // Check that |CleanChecksum()| makes an acceptable checksum. | 436 // Check that |CleanChecksum()| makes an acceptable checksum. |
404 TEST_F(PrefixSetTest, CorruptionHelpers) { | 437 TEST_F(PrefixSetTest, CorruptionHelpers) { |
405 base::FilePath filename; | 438 base::FilePath filename; |
406 ASSERT_TRUE(GetPrefixSetFile(&filename)); | 439 ASSERT_TRUE(GetPrefixSetFile(&filename)); |
407 | 440 |
408 // This will modify data in |index_|, which will fail the digest check. | 441 // This will modify data in |index_|, which will fail the digest check. |
409 base::ScopedFILE file(base::OpenFile(filename, "r+b")); | 442 base::ScopedFILE file(base::OpenFile(filename, "r+b")); |
410 IncrementIntAt(file.get(), kPayloadOffset, 1); | 443 IncrementIntAt(file.get(), kPayloadOffset, 1); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 TEST_F(PrefixSetTest, CorruptionDeltasSize) { | 491 TEST_F(PrefixSetTest, CorruptionDeltasSize) { |
459 base::FilePath filename; | 492 base::FilePath filename; |
460 ASSERT_TRUE(GetPrefixSetFile(&filename)); | 493 ASSERT_TRUE(GetPrefixSetFile(&filename)); |
461 | 494 |
462 ASSERT_NO_FATAL_FAILURE( | 495 ASSERT_NO_FATAL_FAILURE( |
463 ModifyAndCleanChecksum(filename, kDeltasSizeOffset, 1)); | 496 ModifyAndCleanChecksum(filename, kDeltasSizeOffset, 1)); |
464 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); | 497 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); |
465 ASSERT_FALSE(prefix_set.get()); | 498 ASSERT_FALSE(prefix_set.get()); |
466 } | 499 } |
467 | 500 |
| 501 // Bad |full_hashes_| size is caught by the sanity check. |
| 502 TEST_F(PrefixSetTest, CorruptionFullHashesSize) { |
| 503 base::FilePath filename; |
| 504 ASSERT_TRUE(GetPrefixSetFile(&filename)); |
| 505 |
| 506 ASSERT_NO_FATAL_FAILURE( |
| 507 ModifyAndCleanChecksum(filename, kFullHashesSizeOffset, 1)); |
| 508 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); |
| 509 ASSERT_FALSE(prefix_set.get()); |
| 510 } |
| 511 |
468 // Test that the digest catches corruption in the middle of the file | 512 // Test that the digest catches corruption in the middle of the file |
469 // (in the payload between the header and the digest). | 513 // (in the payload between the header and the digest). |
470 TEST_F(PrefixSetTest, CorruptionPayload) { | 514 TEST_F(PrefixSetTest, CorruptionPayload) { |
471 base::FilePath filename; | 515 base::FilePath filename; |
472 ASSERT_TRUE(GetPrefixSetFile(&filename)); | 516 ASSERT_TRUE(GetPrefixSetFile(&filename)); |
473 | 517 |
474 base::ScopedFILE file(base::OpenFile(filename, "r+b")); | 518 base::ScopedFILE file(base::OpenFile(filename, "r+b")); |
475 ASSERT_NO_FATAL_FAILURE(IncrementIntAt(file.get(), 666, 1)); | 519 ASSERT_NO_FATAL_FAILURE(IncrementIntAt(file.get(), 666, 1)); |
476 file.reset(); | 520 file.reset(); |
477 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); | 521 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(filename); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path)); | 704 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path)); |
661 golden_path = golden_path.AppendASCII("SafeBrowsing"); | 705 golden_path = golden_path.AppendASCII("SafeBrowsing"); |
662 golden_path = golden_path.AppendASCII(kBasename); | 706 golden_path = golden_path.AppendASCII(kBasename); |
663 | 707 |
664 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(golden_path); | 708 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(golden_path); |
665 ASSERT_TRUE(prefix_set.get()); | 709 ASSERT_TRUE(prefix_set.get()); |
666 CheckPrefixes(*prefix_set, ref_prefixes); | 710 CheckPrefixes(*prefix_set, ref_prefixes); |
667 } | 711 } |
668 #endif | 712 #endif |
669 | 713 |
| 714 // Test that a golden v3 file can be read by the current code. All platforms |
| 715 // generating v3 files are little-endian, so there is no point to testing this |
| 716 // transition if/when a big-endian port is added. |
| 717 #if defined(ARCH_CPU_LITTLE_ENDIAN) |
| 718 TEST_F(PrefixSetTest, Version3) { |
| 719 std::vector<SBPrefix> ref_prefixes; |
| 720 ASSERT_TRUE(ReadReferencePrefixes(&ref_prefixes)); |
| 721 |
| 722 const char kBasename[] = "PrefixSetVersion3"; |
| 723 base::FilePath golden_path; |
| 724 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path)); |
| 725 golden_path = golden_path.AppendASCII("SafeBrowsing"); |
| 726 golden_path = golden_path.AppendASCII(kBasename); |
| 727 |
| 728 scoped_ptr<PrefixSet> prefix_set = PrefixSet::LoadFile(golden_path); |
| 729 ASSERT_TRUE(prefix_set.get()); |
| 730 CheckPrefixes(*prefix_set, ref_prefixes); |
| 731 |
| 732 const SBFullHash kHash1 = SBFullHashForString("www.evil.com/malware.html"); |
| 733 const SBFullHash kHash2 = SBFullHashForString("www.evil.com/phishing.html"); |
| 734 |
| 735 EXPECT_TRUE(prefix_set->Exists(kHash1)); |
| 736 EXPECT_TRUE(prefix_set->Exists(kHash2)); |
| 737 EXPECT_FALSE(prefix_set->PrefixExists(kHash1.prefix)); |
| 738 EXPECT_FALSE(prefix_set->PrefixExists(kHash2.prefix)); |
| 739 } |
| 740 #endif |
| 741 |
670 } // namespace safe_browsing | 742 } // namespace safe_browsing |
OLD | NEW |