Index: chrome/browser/safe_browsing/safe_browsing_store_file.cc |
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.cc b/chrome/browser/safe_browsing/safe_browsing_store_file.cc |
index 7f1924dba3e6d6f3ed8bc672a3bafb76f247d0c6..025ea2fdf6e33705b650b87394cfd1814ec4f542 100644 |
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.cc |
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.cc |
@@ -243,6 +243,59 @@ bool SafeBrowsingStoreFile::Delete() { |
return true; |
} |
+bool SafeBrowsingStoreFile::CheckValidity() { |
+ if (empty_) |
+ return true; |
+ |
+ // If the file was not empty, it should be open. |
+ DCHECK(file_.get()); |
+ |
+ if (!FileRewind(file_.get())) |
+ return OnCorruptDatabase(); |
+ |
+ int64 size = 0; |
+ if (!file_util::GetFileSize(filename_, &size)) |
+ return OnCorruptDatabase(); |
+ |
+ base::MD5Context context; |
+ base::MD5Init(&context); |
+ |
+ // Read everything except the final digest. |
+ size_t bytes_left = static_cast<size_t>(size); |
+ CHECK(size == static_cast<int64>(bytes_left)); |
+ if (bytes_left < sizeof(base::MD5Digest)) |
+ return OnCorruptDatabase(); |
+ bytes_left -= sizeof(base::MD5Digest); |
+ |
+ // Fold the contents of the file into the checksum. |
+ while (bytes_left > 0) { |
+ char buf[4096]; |
+ const size_t c = std::min(sizeof(buf), bytes_left); |
+ const size_t ret = fread(buf, 1, c, file_.get()); |
+ |
+ // The file's size changed while reading, give up. |
+ if (ret != c) |
+ return OnCorruptDatabase(); |
+ base::MD5Update(&context, base::StringPiece(buf, c)); |
+ bytes_left -= c; |
+ } |
+ |
+ // Calculate the digest to this point. |
+ base::MD5Digest calculated_digest; |
+ base::MD5Final(&calculated_digest, &context); |
+ |
+ // Read the stored digest and verify it. |
+ base::MD5Digest file_digest; |
+ if (!ReadItem(&file_digest, file_.get(), NULL)) |
+ return OnCorruptDatabase(); |
+ if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) { |
+ RecordFormatEvent(FORMAT_EVENT_VALIDITY_CHECKSUM_FAILURE); |
+ return OnCorruptDatabase(); |
+ } |
+ |
+ return true; |
+} |
+ |
void SafeBrowsingStoreFile::Init( |
const FilePath& filename, |
const base::Closure& corruption_callback |
@@ -503,8 +556,10 @@ bool SafeBrowsingStoreFile::DoUpdate( |
if (!ReadItem(&file_digest, file_.get(), NULL)) |
return OnCorruptDatabase(); |
- if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) |
+ if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) { |
+ RecordFormatEvent(FORMAT_EVENT_UPDATE_CHECKSUM_FAILURE); |
return OnCorruptDatabase(); |
+ } |
// Close the file so we can later rename over it. |
file_.reset(); |