summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-30 09:57:48 +0000
committergavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-30 09:57:48 +0000
commitf8e60d5306b24acfb6148cf66ebda571f99c8373 (patch)
tree3f69d40c143acfbd7ffec99deb46d3b9f2853d8f
parentdb3f7fa375d1639cde008869db20aaad50756804 (diff)
downloadchromium_src-f8e60d5306b24acfb6148cf66ebda571f99c8373.zip
chromium_src-f8e60d5306b24acfb6148cf66ebda571f99c8373.tar.gz
chromium_src-f8e60d5306b24acfb6148cf66ebda571f99c8373.tar.bz2
Do not open clearly invalid entries in the SimpleCache.
In the case of premature kill, the SimpleCache backend can leave invalid entries on disk without EOF records. Now let's catch these early and fail to open the entries. R=pasko@google.com, rdsmith@chromium.org BUG=236390 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=197172 Review URL: https://codereview.chromium.org/13844016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@197329 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/disk_cache/entry_unittest.cc44
-rw-r--r--net/disk_cache/simple/simple_entry_impl.cc14
-rw-r--r--net/disk_cache/simple/simple_synchronous_entry.cc17
3 files changed, 68 insertions, 7 deletions
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
index 68794b2..610ec22 100644
--- a/net/disk_cache/entry_unittest.cc
+++ b/net/disk_cache/entry_unittest.cc
@@ -19,6 +19,7 @@
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/disk_cache/entry_impl.h"
#include "net/disk_cache/mem_entry_impl.h"
+#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -2381,6 +2382,49 @@ TEST_F(DiskCacheEntryTest, SimpleCacheErrorThenDoom) {
entry->Close();
}
+bool TruncatePath(const base::FilePath& file_path, int64 length) {
+ const int flags = base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_OPEN;
+ base::PlatformFile file =
+ base::CreatePlatformFile(file_path, flags, NULL, NULL);
+ if (base::kInvalidPlatformFileValue == file)
+ return false;
+ const bool result = base::TruncatePlatformFile(file, length);
+ base::ClosePlatformFile(file);
+ return result;
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheNoEOF) {
+ SetSimpleCacheMode();
+ InitCache();
+
+ const char key[] = "the first key";
+
+ disk_cache::Entry* entry = NULL;
+ ASSERT_EQ(net::OK, CreateEntry(key, &entry));
+ disk_cache::Entry* null = NULL;
+ EXPECT_NE(null, entry);
+ entry->Close();
+ entry = NULL;
+
+ // Force the entry to flush to disk, so subsequent platform file operations
+ // succed.
+ ASSERT_EQ(net::OK, OpenEntry(key, &entry));
+ entry->Close();
+ entry = NULL;
+
+ // Truncate the file such that the length isn't sufficient to have an EOF
+ // record.
+ int kTruncationBytes = -implicit_cast<int>(sizeof(disk_cache::SimpleFileEOF));
+ const base::FilePath entry_path = cache_path_.AppendASCII(
+ disk_cache::simple_util::GetFilenameFromKeyAndIndex(key, 0));
+ const int64 invalid_size =
+ disk_cache::simple_util::GetFileSizeFromKeyAndDataSize(key,
+ kTruncationBytes);
+ EXPECT_TRUE(TruncatePath(entry_path, invalid_size));
+ EXPECT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
+ DisableIntegrityCheck();
+}
+
// Tests that old entries are evicted while new entries remain in the index.
// This test relies on non-mandatory properties of the simple Cache Backend:
// LRU eviction, specific values of high-watermark and low-watermark etc.
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 6847e02..df1125c 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -368,6 +368,10 @@ void SimpleEntryImpl::CreateEntryInternal(Entry** out_entry,
state_ = STATE_IO_PENDING;
+ // If creation succeeds, we should mark all streams to be saved on close.
+ for (int i = 0; i < kSimpleEntryFileCount; ++i)
+ have_written_[i] = true;
+
// We insert the entry in the index before creating the entry files in the
// SimpleSynchronousEntry, because this way the worst scenario is when we
// have the entry in the index but we don't have the created files yet, this
@@ -401,10 +405,12 @@ void SimpleEntryImpl::CloseInternal() {
crc32s_to_write(new std::vector<CRCRecord>());
for (int i = 0; i < kSimpleEntryFileCount; ++i) {
if (have_written_[i]) {
- if (data_size_[i] == crc32s_end_offset_[i])
- crc32s_to_write->push_back(CRCRecord(i, true, crc32s_[i]));
- else
+ if (data_size_[i] == crc32s_end_offset_[i]) {
+ int32 crc = data_size_[i] == 0 ? crc32(0, Z_NULL, 0) : crc32s_[i];
+ crc32s_to_write->push_back(CRCRecord(i, true, crc));
+ } else {
crc32s_to_write->push_back(CRCRecord(i, false, 0));
+ }
}
}
Closure task = base::Bind(&SimpleSynchronousEntry::Close,
@@ -493,7 +499,7 @@ void SimpleEntryImpl::CreationOperationComplete(
if (creation_failed) {
completion_callback.Run(net::ERR_FAILED);
MarkAsDoomed();
- state_ = STATE_UNINITIALIZED;
+ MakeUninitialized();
return;
}
state_ = STATE_READY;
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index d4bd45e..83133f2 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -326,6 +326,14 @@ bool SimpleSynchronousEntry::OpenOrCreateFiles(bool create) {
}
}
+ have_open_files_ = true;
+ if (create) {
+ last_modified_ = last_used_ = Time::Now();
+ for (int i = 0; i < kSimpleEntryFileCount; ++i)
+ data_size_[i] = 0;
+ return true;
+ }
+
for (int i = 0; i < kSimpleEntryFileCount; ++i) {
PlatformFileInfo file_info;
bool success = GetPlatformFileInfo(files_[i], &file_info);
@@ -335,11 +343,14 @@ bool SimpleSynchronousEntry::OpenOrCreateFiles(bool create) {
}
last_used_ = std::max(last_used_, file_info.last_accessed);
last_modified_ = std::max(last_modified_, file_info.last_modified);
- data_size_[i] = create ? 0 : GetDataSizeFromKeyAndFileSize(key_,
- file_info.size);
+ data_size_[i] = GetDataSizeFromKeyAndFileSize(key_, file_info.size);
+ if (data_size_[i] < 0) {
+ // This entry can't possibly be valid, as it does not enough space to
+ // store a valid SimpleFileEOF record.
+ return false;
+ }
}
- have_open_files_ = true;
return true;
}