Index: chrome/browser/safe_browsing/bloom_filter.cc |
diff --git a/chrome/browser/safe_browsing/bloom_filter.cc b/chrome/browser/safe_browsing/bloom_filter.cc |
index 859d32011dabfd1a94857fcb2faca3bb4a382808..747a86f62b1715d36b3e76c726a4bf2fe0a1faba 100644 |
--- a/chrome/browser/safe_browsing/bloom_filter.cc |
+++ b/chrome/browser/safe_browsing/bloom_filter.cc |
@@ -30,6 +30,24 @@ uint32 HashMix(BloomFilter::HashKey hash_key, uint32 c) { |
return c; |
} |
+uint32 CalculateChecksum(const char* data, size_t size, |
+ const BloomFilter::HashKeys& keys) { |
+ uint32 checksum = 0; |
+ for (size_t i = 0; i < keys.size(); ++i) { |
+ checksum ^= static_cast<uint32>(keys[i]); |
+ checksum ^= static_cast<uint32>(keys[i]>>32); |
+ } |
+ |
+ // Watch out for sign-extension in the calculation. |
+ // TODO(shess): Bit manipulation of signed chars is insane. |
+ const unsigned char* udata = reinterpret_cast<const unsigned char*>(data); |
+ for (size_t i = 0; i < size; ++i) { |
+ checksum ^= udata[i] << ((i * 8) % 32); |
+ } |
+ |
+ return checksum; |
+} |
+ |
} // namespace |
// static |
@@ -56,6 +74,7 @@ BloomFilter::BloomFilter(int bit_size) { |
DCHECK_LE(bit_size, bit_size_); // strictly more bits. |
data_.reset(new char[byte_size_]); |
memset(data_.get(), 0, byte_size_); |
+ checksum_ = CalculateChecksum(data_.get(), 0, hash_keys_); |
} |
BloomFilter::BloomFilter(char* data, int size, const HashKeys& keys) |
@@ -63,6 +82,7 @@ BloomFilter::BloomFilter(char* data, int size, const HashKeys& keys) |
byte_size_ = size; |
bit_size_ = byte_size_ * 8; |
data_.reset(data); |
+ checksum_ = CalculateChecksum(data_.get(), byte_size_, hash_keys_); |
} |
BloomFilter::~BloomFilter() { |
@@ -72,7 +92,12 @@ void BloomFilter::Insert(SBPrefix hash) { |
uint32 hash_uint32 = static_cast<uint32>(hash); |
for (size_t i = 0; i < hash_keys_.size(); ++i) { |
uint32 index = HashMix(hash_keys_[i], hash_uint32) % bit_size_; |
- data_[index / 8] |= 1 << (index % 8); |
+ // Checksum needs to track the transition. Remove the if() when |
+ // the checksum goes away. |
+ if (!(data_[index / 8] & (1 << (index % 8)))) { |
+ data_[index / 8] |= 1 << (index % 8); |
+ checksum_ ^= 1u << (index % 32); |
+ } |
} |
} |
@@ -190,3 +215,9 @@ bool BloomFilter::WriteFile(const FilePath& filter_name) const { |
return true; |
} |
+ |
+bool BloomFilter::CheckChecksum() const { |
+ const uint32 checksum = CalculateChecksum(data_.get(), byte_size_, |
+ hash_keys_); |
+ return checksum_ == checksum; |
+} |