| 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/safe_browsing_store_file.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h" |
| 6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
| 7 #include "base/bind.h" | 10 #include "base/bind.h" |
| 8 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 9 #include "base/files/scoped_file.h" | 12 #include "base/files/scoped_file.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 13 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/md5.h" | 14 #include "base/md5.h" |
| 12 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 13 #include "base/test/test_simple_task_runner.h" | 16 #include "base/test/test_simple_task_runner.h" |
| 17 #include "build/build_config.h" |
| 14 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
| 15 #include "components/safe_browsing_db/prefix_set.h" | 19 #include "components/safe_browsing_db/prefix_set.h" |
| 16 #include "components/safe_browsing_db/util.h" | 20 #include "components/safe_browsing_db/util.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "testing/platform_test.h" | 22 #include "testing/platform_test.h" |
| 19 | 23 |
| 20 namespace safe_browsing { | 24 namespace safe_browsing { |
| 21 | 25 |
| 22 namespace { | 26 namespace { |
| 23 | 27 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 EXPECT_FALSE(store_->CheckSubChunk(kAddChunk1)); | 106 EXPECT_FALSE(store_->CheckSubChunk(kAddChunk1)); |
| 103 EXPECT_FALSE(store_->CheckSubChunk(kAddChunk2)); | 107 EXPECT_FALSE(store_->CheckSubChunk(kAddChunk2)); |
| 104 | 108 |
| 105 PrefixSetBuilder builder; | 109 PrefixSetBuilder builder; |
| 106 std::vector<SBAddFullHash> add_full_hashes_result; | 110 std::vector<SBAddFullHash> add_full_hashes_result; |
| 107 | 111 |
| 108 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); | 112 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); |
| 109 } | 113 } |
| 110 | 114 |
| 111 // Manually read the shard stride info from the file. | 115 // Manually read the shard stride info from the file. |
| 112 uint32 ReadStride() { | 116 uint32_t ReadStride() { |
| 113 base::ScopedFILE file(base::OpenFile(filename_, "rb")); | 117 base::ScopedFILE file(base::OpenFile(filename_, "rb")); |
| 114 const long kOffset = 4 * sizeof(uint32); | 118 const long kOffset = 4 * sizeof(uint32_t); |
| 115 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); | 119 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); |
| 116 uint32 shard_stride = 0; | 120 uint32_t shard_stride = 0; |
| 117 EXPECT_EQ(fread(&shard_stride, sizeof(shard_stride), 1, file.get()), 1U); | 121 EXPECT_EQ(fread(&shard_stride, sizeof(shard_stride), 1, file.get()), 1U); |
| 118 return shard_stride; | 122 return shard_stride; |
| 119 } | 123 } |
| 120 | 124 |
| 121 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | 125 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| 122 base::ScopedTempDir temp_dir_; | 126 base::ScopedTempDir temp_dir_; |
| 123 base::FilePath filename_; | 127 base::FilePath filename_; |
| 124 scoped_ptr<SafeBrowsingStoreFile> store_; | 128 scoped_ptr<SafeBrowsingStoreFile> store_; |
| 125 bool corruption_detected_; | 129 bool corruption_detected_; |
| 126 }; | 130 }; |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 builder.GetPrefixSetNoHashes()->GetPrefixes(&orig_prefixes); | 503 builder.GetPrefixSetNoHashes()->GetPrefixes(&orig_prefixes); |
| 500 EXPECT_GT(orig_prefixes.size(), 0U); | 504 EXPECT_GT(orig_prefixes.size(), 0U); |
| 501 EXPECT_GT(orig_hashes.size(), 0U); | 505 EXPECT_GT(orig_hashes.size(), 0U); |
| 502 EXPECT_FALSE(corruption_detected_); | 506 EXPECT_FALSE(corruption_detected_); |
| 503 } | 507 } |
| 504 | 508 |
| 505 // Corrupt the store. | 509 // Corrupt the store. |
| 506 base::ScopedFILE file(base::OpenFile(filename_, "rb+")); | 510 base::ScopedFILE file(base::OpenFile(filename_, "rb+")); |
| 507 const long kOffset = 60; | 511 const long kOffset = 60; |
| 508 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); | 512 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); |
| 509 const uint32 kZero = 0; | 513 const uint32_t kZero = 0; |
| 510 uint32 previous = kZero; | 514 uint32_t previous = kZero; |
| 511 EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U); | 515 EXPECT_EQ(fread(&previous, sizeof(previous), 1, file.get()), 1U); |
| 512 EXPECT_NE(previous, kZero); | 516 EXPECT_NE(previous, kZero); |
| 513 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); | 517 EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0); |
| 514 EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U); | 518 EXPECT_EQ(fwrite(&kZero, sizeof(kZero), 1, file.get()), 1U); |
| 515 file.reset(); | 519 file.reset(); |
| 516 | 520 |
| 517 // Update fails and corruption callback is called. | 521 // Update fails and corruption callback is called. |
| 518 std::vector<SBAddFullHash> add_hashes; | 522 std::vector<SBAddFullHash> add_hashes; |
| 519 corruption_detected_ = false; | 523 corruption_detected_ = false; |
| 520 { | 524 { |
| 521 PrefixSetBuilder builder; | 525 PrefixSetBuilder builder; |
| 522 ASSERT_TRUE(store_->BeginUpdate()); | 526 ASSERT_TRUE(store_->BeginUpdate()); |
| 523 EXPECT_FALSE(store_->FinishUpdate(&builder, &add_hashes)); | 527 EXPECT_FALSE(store_->FinishUpdate(&builder, &add_hashes)); |
| 524 EXPECT_TRUE(corruption_detected_); | 528 EXPECT_TRUE(corruption_detected_); |
| 525 } | 529 } |
| 526 | 530 |
| 527 // Make it look like there is a lot of add-chunks-seen data. | 531 // Make it look like there is a lot of add-chunks-seen data. |
| 528 const long kAddChunkCountOffset = 2 * sizeof(int32); | 532 const long kAddChunkCountOffset = 2 * sizeof(int32_t); |
| 529 const int32 kLargeCount = 1000 * 1000 * 1000; | 533 const int32_t kLargeCount = 1000 * 1000 * 1000; |
| 530 file.reset(base::OpenFile(filename_, "rb+")); | 534 file.reset(base::OpenFile(filename_, "rb+")); |
| 531 EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0); | 535 EXPECT_EQ(fseek(file.get(), kAddChunkCountOffset, SEEK_SET), 0); |
| 532 EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U); | 536 EXPECT_EQ(fwrite(&kLargeCount, sizeof(kLargeCount), 1, file.get()), 1U); |
| 533 file.reset(); | 537 file.reset(); |
| 534 | 538 |
| 535 // Detects corruption and fails to even begin the update. | 539 // Detects corruption and fails to even begin the update. |
| 536 corruption_detected_ = false; | 540 corruption_detected_ = false; |
| 537 EXPECT_FALSE(store_->BeginUpdate()); | 541 EXPECT_FALSE(store_->BeginUpdate()); |
| 538 EXPECT_TRUE(corruption_detected_); | 542 EXPECT_TRUE(corruption_detected_); |
| 539 } | 543 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes)); | 675 EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes)); |
| 672 ASSERT_EQ(1U, add_hashes.size()); | 676 ASSERT_EQ(1U, add_hashes.size()); |
| 673 EXPECT_EQ(kAddChunk2, add_hashes[0].chunk_id); | 677 EXPECT_EQ(kAddChunk2, add_hashes[0].chunk_id); |
| 674 EXPECT_TRUE(SBFullHashEqual(kHash4, add_hashes[0].full_hash)); | 678 EXPECT_TRUE(SBFullHashEqual(kHash4, add_hashes[0].full_hash)); |
| 675 } | 679 } |
| 676 | 680 |
| 677 // Test that the database handles resharding correctly, both when growing and | 681 // Test that the database handles resharding correctly, both when growing and |
| 678 // which shrinking. | 682 // which shrinking. |
| 679 TEST_F(SafeBrowsingStoreFileTest, Resharding) { | 683 TEST_F(SafeBrowsingStoreFileTest, Resharding) { |
| 680 // Loop through multiple stride boundaries (1<<32, 1<<31, 1<<30, 1<<29). | 684 // Loop through multiple stride boundaries (1<<32, 1<<31, 1<<30, 1<<29). |
| 681 const uint32 kTargetStride = 1 << 29; | 685 const uint32_t kTargetStride = 1 << 29; |
| 682 | 686 |
| 683 // Each chunk will require 8 bytes per prefix, plus 4 bytes for chunk | 687 // Each chunk will require 8 bytes per prefix, plus 4 bytes for chunk |
| 684 // information. It should be less than |kTargetFootprint| in the | 688 // information. It should be less than |kTargetFootprint| in the |
| 685 // implementation, but high enough to keep the number of rewrites modest (to | 689 // implementation, but high enough to keep the number of rewrites modest (to |
| 686 // keep the test fast). | 690 // keep the test fast). |
| 687 const size_t kPrefixesPerChunk = 10000; | 691 const size_t kPrefixesPerChunk = 10000; |
| 688 | 692 |
| 689 uint32 shard_stride = 0; | 693 uint32_t shard_stride = 0; |
| 690 int chunk_id = 1; | 694 int chunk_id = 1; |
| 691 | 695 |
| 692 // Add a series of chunks, tracking that the stride size changes in a | 696 // Add a series of chunks, tracking that the stride size changes in a |
| 693 // direction appropriate to increasing file size. | 697 // direction appropriate to increasing file size. |
| 694 do { | 698 do { |
| 695 ASSERT_TRUE(store_->BeginUpdate()); | 699 ASSERT_TRUE(store_->BeginUpdate()); |
| 696 | 700 |
| 697 EXPECT_TRUE(store_->BeginChunk()); | 701 EXPECT_TRUE(store_->BeginChunk()); |
| 698 store_->SetAddChunk(chunk_id); | 702 store_->SetAddChunk(chunk_id); |
| 699 EXPECT_TRUE(store_->CheckAddChunk(chunk_id)); | 703 EXPECT_TRUE(store_->CheckAddChunk(chunk_id)); |
| 700 for (size_t i = 0; i < kPrefixesPerChunk; ++i) { | 704 for (size_t i = 0; i < kPrefixesPerChunk; ++i) { |
| 701 EXPECT_TRUE(store_->WriteAddPrefix(chunk_id, static_cast<SBPrefix>(i))); | 705 EXPECT_TRUE(store_->WriteAddPrefix(chunk_id, static_cast<SBPrefix>(i))); |
| 702 } | 706 } |
| 703 EXPECT_TRUE(store_->FinishChunk()); | 707 EXPECT_TRUE(store_->FinishChunk()); |
| 704 | 708 |
| 705 PrefixSetBuilder builder; | 709 PrefixSetBuilder builder; |
| 706 std::vector<SBAddFullHash> add_full_hashes_result; | 710 std::vector<SBAddFullHash> add_full_hashes_result; |
| 707 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); | 711 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); |
| 708 | 712 |
| 709 SBAddPrefixes add_prefixes; | 713 SBAddPrefixes add_prefixes; |
| 710 EXPECT_TRUE(store_->GetAddPrefixes(&add_prefixes)); | 714 EXPECT_TRUE(store_->GetAddPrefixes(&add_prefixes)); |
| 711 ASSERT_EQ(chunk_id * kPrefixesPerChunk, add_prefixes.size()); | 715 ASSERT_EQ(chunk_id * kPrefixesPerChunk, add_prefixes.size()); |
| 712 | 716 |
| 713 // New stride should be the same, or shifted one right. | 717 // New stride should be the same, or shifted one right. |
| 714 const uint32 new_shard_stride = ReadStride(); | 718 const uint32_t new_shard_stride = ReadStride(); |
| 715 EXPECT_TRUE((new_shard_stride == shard_stride) || | 719 EXPECT_TRUE((new_shard_stride == shard_stride) || |
| 716 ((new_shard_stride << 1) == shard_stride)); | 720 ((new_shard_stride << 1) == shard_stride)); |
| 717 shard_stride = new_shard_stride; | 721 shard_stride = new_shard_stride; |
| 718 ++chunk_id; | 722 ++chunk_id; |
| 719 } while (!shard_stride || shard_stride > kTargetStride); | 723 } while (!shard_stride || shard_stride > kTargetStride); |
| 720 | 724 |
| 721 // Guard against writing too many chunks. If this gets too big, adjust | 725 // Guard against writing too many chunks. If this gets too big, adjust |
| 722 // |kPrefixesPerChunk|. | 726 // |kPrefixesPerChunk|. |
| 723 EXPECT_LT(chunk_id, 20); | 727 EXPECT_LT(chunk_id, 20); |
| 724 | 728 |
| 725 // Remove each chunk and check that the stride goes back to 0. | 729 // Remove each chunk and check that the stride goes back to 0. |
| 726 while (--chunk_id) { | 730 while (--chunk_id) { |
| 727 ASSERT_TRUE(store_->BeginUpdate()); | 731 ASSERT_TRUE(store_->BeginUpdate()); |
| 728 EXPECT_TRUE(store_->CheckAddChunk(chunk_id)); | 732 EXPECT_TRUE(store_->CheckAddChunk(chunk_id)); |
| 729 EXPECT_FALSE(store_->CheckAddChunk(chunk_id + 1)); | 733 EXPECT_FALSE(store_->CheckAddChunk(chunk_id + 1)); |
| 730 store_->DeleteAddChunk(chunk_id); | 734 store_->DeleteAddChunk(chunk_id); |
| 731 | 735 |
| 732 PrefixSetBuilder builder; | 736 PrefixSetBuilder builder; |
| 733 std::vector<SBAddFullHash> add_full_hashes_result; | 737 std::vector<SBAddFullHash> add_full_hashes_result; |
| 734 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); | 738 EXPECT_TRUE(store_->FinishUpdate(&builder, &add_full_hashes_result)); |
| 735 | 739 |
| 736 // New stride should be the same, or shifted one left. | 740 // New stride should be the same, or shifted one left. |
| 737 const uint32 new_shard_stride = ReadStride(); | 741 const uint32_t new_shard_stride = ReadStride(); |
| 738 EXPECT_TRUE((new_shard_stride == shard_stride) || | 742 EXPECT_TRUE((new_shard_stride == shard_stride) || |
| 739 (new_shard_stride == (shard_stride << 1))); | 743 (new_shard_stride == (shard_stride << 1))); |
| 740 shard_stride = new_shard_stride; | 744 shard_stride = new_shard_stride; |
| 741 } | 745 } |
| 742 EXPECT_EQ(0u, shard_stride); | 746 EXPECT_EQ(0u, shard_stride); |
| 743 } | 747 } |
| 744 | 748 |
| 745 // Test that a golden v7 file can no longer be read. All platforms generating | 749 // Test that a golden v7 file can no longer be read. All platforms generating |
| 746 // v7 files were little-endian, so there is no point to testing this transition | 750 // v7 files were little-endian, so there is no point to testing this transition |
| 747 // if/when a big-endian port is added. | 751 // if/when a big-endian port is added. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 std::vector<SBPrefix> prefixes_result; | 853 std::vector<SBPrefix> prefixes_result; |
| 850 builder.GetPrefixSetNoHashes()->GetPrefixes(&prefixes_result); | 854 builder.GetPrefixSetNoHashes()->GetPrefixes(&prefixes_result); |
| 851 ASSERT_EQ(1U, prefixes_result.size()); | 855 ASSERT_EQ(1U, prefixes_result.size()); |
| 852 EXPECT_EQ(kHash1.prefix, prefixes_result[0]); | 856 EXPECT_EQ(kHash1.prefix, prefixes_result[0]); |
| 853 EXPECT_TRUE(add_full_hashes_result.empty()); | 857 EXPECT_TRUE(add_full_hashes_result.empty()); |
| 854 } | 858 } |
| 855 } | 859 } |
| 856 #endif | 860 #endif |
| 857 | 861 |
| 858 } // namespace safe_browsing | 862 } // namespace safe_browsing |
| OLD | NEW |