summaryrefslogtreecommitdiffstats
path: root/chrome/browser/nacl_host/nacl_validation_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/nacl_host/nacl_validation_cache.cc')
-rw-r--r--chrome/browser/nacl_host/nacl_validation_cache.cc128
1 files changed, 85 insertions, 43 deletions
diff --git a/chrome/browser/nacl_host/nacl_validation_cache.cc b/chrome/browser/nacl_host/nacl_validation_cache.cc
index 84c45ab..669fe94 100644
--- a/chrome/browser/nacl_host/nacl_validation_cache.cc
+++ b/chrome/browser/nacl_host/nacl_validation_cache.cc
@@ -4,7 +4,7 @@
#include "chrome/browser/nacl_host/nacl_validation_cache.h"
-#include "base/metrics/histogram.h"
+#include "base/pickle.h"
#include "base/rand_util.h"
namespace {
@@ -16,37 +16,16 @@ const size_t kValidationCacheKeySize = 64;
// Entry size is equal to the digest size of SHA256.
const size_t kValidationCacheEntrySize = 32;
-enum ValidationCacheStatus {
- CACHE_MISS = 0,
- CACHE_HIT,
- CACHE_ERROR,
- CACHE_MAX
-};
-
-void LogCacheQuery(ValidationCacheStatus status) {
- UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status, CACHE_MAX);
-}
-
-void LogCacheSet(ValidationCacheStatus status) {
- // Bucket zero is reserved for future use.
- UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, CACHE_MAX);
-}
-
-bool CheckEnvVar(const char* name, bool default_value) {
- bool result = default_value;
- const char* var = getenv(name);
- if (var && strlen(var) > 0) {
- result = var[0] != '0';
- }
- return result;
-}
+const char kValidationCacheBeginMagic[] = "NaCl";
+const char kValidationCacheEndMagic[] = "Done";
} // namespace
NaClValidationCache::NaClValidationCache()
- : validation_cache_(kValidationCacheCacheSize),
- validation_cache_key_(base::RandBytesAsString(kValidationCacheKeySize)),
- enabled_(CheckEnvVar("NACL_VALIDATION_CACHE", false)){
+ : validation_cache_(kValidationCacheCacheSize) {
+ // Make sure the cache key is unpredictable, even if the cache has not
+ // been loaded.
+ Reset();
}
NaClValidationCache::~NaClValidationCache() {
@@ -54,28 +33,91 @@ NaClValidationCache::~NaClValidationCache() {
}
bool NaClValidationCache::QueryKnownToValidate(const std::string& signature) {
- bool result = false;
- if (signature.length() != kValidationCacheEntrySize) {
- // Signature is the wrong size, something is wrong.
- LogCacheQuery(CACHE_ERROR);
- } else {
+ if (signature.length() == kValidationCacheEntrySize) {
ValidationCacheType::iterator iter = validation_cache_.Get(signature);
if (iter != validation_cache_.end()) {
- result = iter->second;
+ return iter->second;
}
- LogCacheQuery(result ? CACHE_HIT : CACHE_MISS);
}
- return result;
+ return false;
}
void NaClValidationCache::SetKnownToValidate(const std::string& signature) {
- if (signature.length() != kValidationCacheEntrySize) {
- // Signature is the wrong size, something is wrong.
- LogCacheSet(CACHE_ERROR);
- } else {
+ if (signature.length() == kValidationCacheEntrySize) {
validation_cache_.Put(signature, true);
- // The number of sets should be equal to the number of cache misses, minus
- // validation failures and successful validations where stubout occurs.
- LogCacheSet(CACHE_HIT);
}
}
+
+void NaClValidationCache::Serialize(Pickle* pickle) const {
+ // Mark the beginning of the data stream.
+ pickle->WriteString(kValidationCacheBeginMagic);
+ pickle->WriteString(validation_cache_key_);
+ pickle->WriteInt(validation_cache_.size());
+
+ // Serialize the cache in reverse order so that deserializing it can easily
+ // preserve the MRU order. (Last item deserialized => most recently used.)
+ ValidationCacheType::const_reverse_iterator iter;
+ for (iter = validation_cache_.rbegin();
+ iter != validation_cache_.rend();
+ ++iter) {
+ pickle->WriteString(iter->first);
+ }
+
+ // Mark the end of the data stream.
+ pickle->WriteString(kValidationCacheEndMagic);
+}
+
+void NaClValidationCache::Reset() {
+ validation_cache_key_ = base::RandBytesAsString(kValidationCacheKeySize);
+ validation_cache_.Clear();
+}
+
+bool NaClValidationCache::Deserialize(const Pickle* pickle) {
+ bool success = DeserializeImpl(pickle);
+ if (!success) {
+ Reset();
+ }
+ return success;
+}
+
+bool NaClValidationCache::DeserializeImpl(const Pickle* pickle) {
+ PickleIterator iter(*pickle);
+ std::string buffer;
+ int count;
+
+ // Magic
+ if (!iter.ReadString(&buffer))
+ return false;
+ if (0 != buffer.compare(kValidationCacheBeginMagic))
+ return false;
+
+ // Key
+ if (!iter.ReadString(&buffer))
+ return false;
+ if (buffer.size() != kValidationCacheKeySize)
+ return false;
+
+ validation_cache_key_ = buffer;
+ validation_cache_.Clear();
+
+ // Cache entries
+ if (!iter.ReadInt(&count))
+ return false;
+ for (int i = 0; i < count; ++i) {
+ if (!iter.ReadString(&buffer))
+ return false;
+ if (buffer.size() != kValidationCacheEntrySize)
+ return false;
+ validation_cache_.Put(buffer, true);
+ }
+
+ // Magic
+ if (!iter.ReadString(&buffer))
+ return false;
+ if (0 != buffer.compare(kValidationCacheEndMagic))
+ return false;
+
+ // Success!
+ return true;
+}
+