Index: services/url_response_disk_cache/url_response_disk_cache_impl.cc |
diff --git a/services/url_response_disk_cache/url_response_disk_cache_impl.cc b/services/url_response_disk_cache/url_response_disk_cache_impl.cc |
index 9804c917b8ed607f81c5ab6a3e0678e55dd3dcaf..f510ed89d3c5c82e871882f112c15c973d0ba1cb 100644 |
--- a/services/url_response_disk_cache/url_response_disk_cache_impl.cc |
+++ b/services/url_response_disk_cache/url_response_disk_cache_impl.cc |
@@ -4,6 +4,8 @@ |
#include "services/url_response_disk_cache/url_response_disk_cache_impl.h" |
+#include <type_traits> |
+ |
#include "base/bind.h" |
#include "base/files/file_util.h" |
#include "base/files/important_file_writer.h" |
@@ -22,6 +24,10 @@ namespace mojo { |
namespace { |
+// The current version of the cache. This should only be incremented. When this |
+// is incremented, all current cache entries will be invalidated. |
+const uint32_t kCurrentVersion = 1; |
+ |
const char kEtagHeader[] = "etag"; |
template <typename T> |
@@ -39,12 +45,18 @@ void Serialize(T input, std::string* output) { |
} |
template <typename T> |
-void Deserialize(std::string input, T* output) { |
+bool Deserialize(std::string input, T* output) { |
typedef typename mojo::internal::WrapperTraits<T>::DataType DataType; |
+ mojo::internal::BoundsChecker bounds_checker(&input[0], input.size(), 0); |
+ if (!std::remove_pointer<DataType>::type::Validate(&input[0], |
+ &bounds_checker)) { |
+ return false; |
+ } |
DataType data_type = reinterpret_cast<DataType>(&input[0]); |
std::vector<Handle> handles; |
data_type->DecodePointersAndHandles(&handles); |
Deserialize_(data_type, output); |
+ return true; |
} |
Array<uint8_t> PathToArray(const base::FilePath& path) { |
@@ -169,7 +181,12 @@ bool IsCacheEntryValid(const base::FilePath& dir, |
if (!ReadFileToString(entry_path, &serialized_entry)) |
return false; |
CacheEntryPtr entry; |
- Deserialize(serialized_entry, &entry); |
+ if (!Deserialize(serialized_entry, &entry)) |
+ return false; |
+ |
+ // Obsolete entries are invalidated. |
+ if (entry->version != kCurrentVersion) |
+ return false; |
// If |entry| or |response| has not headers, it is not possible to check if |
// the entry is valid, so returns |false|. |
@@ -228,7 +245,8 @@ void URLResponseDiskCacheImpl::GetExtractedContent( |
base::FilePath extracted_dir = dir.Append("extracted"); |
if (IsCacheEntryValid(dir, response.get(), nullptr) && |
PathExists(GetExtractedSentinel(dir))) { |
- callback.Run(PathToArray(extracted_dir), PathToArray(dir)); |
+ callback.Run(PathToArray(extracted_dir), |
+ PathToArray(GetConsumerCacheDirectory(dir))); |
return; |
} |
@@ -236,7 +254,7 @@ void URLResponseDiskCacheImpl::GetExtractedContent( |
response.Pass(), |
base::Bind(&URLResponseDiskCacheImpl::GetExtractedContentInternal, |
base::Unretained(this), base::Bind(&RunMojoCallback, callback), |
- extracted_dir)); |
+ dir, extracted_dir)); |
} |
void URLResponseDiskCacheImpl::GetFileInternal( |
@@ -280,6 +298,7 @@ void URLResponseDiskCacheImpl::GetFileInternal( |
base::FilePath content; |
CHECK(CreateTemporaryFileInDir(dir, &content)); |
entry = CacheEntry::New(); |
+ entry->version = kCurrentVersion; |
entry->url = response->url; |
entry->content_path = content.value(); |
entry->headers = response->headers.Pass(); |
@@ -294,9 +313,10 @@ void URLResponseDiskCacheImpl::GetFileInternal( |
void URLResponseDiskCacheImpl::GetExtractedContentInternal( |
const FilePathPairCallback& callback, |
+ const base::FilePath& base_dir, |
const base::FilePath& extracted_dir, |
const base::FilePath& content, |
- const base::FilePath& dir) { |
+ const base::FilePath& cache_dir) { |
// If it is not possible to get the cached file, returns an error. |
if (content.empty()) { |
callback.Run(base::FilePath(), base::FilePath()); |
@@ -321,8 +341,8 @@ void URLResponseDiskCacheImpl::GetExtractedContentInternal( |
} |
// We can ignore write error, as it will just force to clear the cache on the |
// next request. |
- WriteFile(GetExtractedSentinel(dir), nullptr, 0); |
- callback.Run(extracted_dir, GetConsumerCacheDirectory(dir)); |
+ WriteFile(GetExtractedSentinel(base_dir), nullptr, 0); |
+ callback.Run(extracted_dir, cache_dir); |
} |
} // namespace mojo |