Bug 926069 - CacheFile must not create new entry when key is a hash, r=honzab

This commit is contained in:
Michal Novotny 2013-12-16 18:01:54 +01:00
Родитель 1fe0bdd132
Коммит 7e1a2214c6
3 изменённых файлов: 138 добавлений и 26 удалений

Просмотреть файл

@ -405,6 +405,8 @@ CacheFile::Init(const nsACString &aKey,
{
MOZ_ASSERT(!mListener);
MOZ_ASSERT(!mHandle);
MOZ_ASSERT(!(aCreateNew && aKeyIsHash));
MOZ_ASSERT(!(aMemoryOnly && aKeyIsHash));
nsresult rv;
@ -706,6 +708,13 @@ CacheFile::OnMetadataRead(nsresult aResult)
bool isNew = false;
if (NS_SUCCEEDED(aResult)) {
MOZ_ASSERT(!mMetadata->KeyIsHash());
if (mKeyIsHash) {
mMetadata->GetKey(mKey);
mKeyIsHash = false;
}
mReady = true;
mDataSize = mMetadata->Offset();
if (mDataSize == 0 && mMetadata->ElementsSize() == 0) {

Просмотреть файл

@ -101,6 +101,19 @@ CacheFileMetadata::SetHandle(CacheFileHandle *aHandle)
mHandle = aHandle;
}
nsresult
CacheFileMetadata::GetKey(nsACString &_retval)
{
_retval = mKey;
return NS_OK;
}
bool
CacheFileMetadata::KeyIsHash()
{
return mKeyIsHash;
}
nsresult
CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
{
@ -117,6 +130,14 @@ CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
MOZ_ASSERT(size != -1);
if (size == 0) {
if (mKeyIsHash) {
LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, cannot create "
"empty metadata since key is a hash. [this=%p]", this));
CacheFileIOManager::DoomFile(mHandle, nullptr);
return NS_ERROR_NOT_AVAILABLE;
}
// this is a new entry
LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, creating empty "
"metadata. [this=%p]", this));
@ -127,6 +148,15 @@ CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
}
if (size < int64_t(sizeof(CacheFileMetadataHeader) + 2*sizeof(uint32_t))) {
if (mKeyIsHash) {
LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, cannot "
"create empty metadata since key is a hash. [this=%p, "
"filesize=%lld]", this, size));
CacheFileIOManager::DoomFile(mHandle, nullptr);
return NS_ERROR_FILE_CORRUPTED;
}
// there must be at least checksum, header and offset
LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, creating "
"empty metadata. [this=%p, filesize=%lld]", this, size));
@ -153,6 +183,15 @@ CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
mListener = aListener;
rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, this);
if (NS_FAILED(rv)) {
if (mKeyIsHash) {
LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() "
"failed synchronously, cannot create empty metadata since key is "
"a hash. [this=%p, rv=0x%08x]", this, rv));
CacheFileIOManager::DoomFile(mHandle, nullptr);
return rv;
}
LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() failed"
" synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
this, rv));
@ -175,6 +214,7 @@ CacheFileMetadata::WriteMetadata(uint32_t aOffset,
MOZ_ASSERT(!mListener);
MOZ_ASSERT(!mWriteBuf);
MOZ_ASSERT(!mKeyIsHash);
nsresult rv;
@ -433,16 +473,28 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
MOZ_ASSERT(mListener);
nsresult rv;
nsresult rv, retval;
nsCOMPtr<CacheFileMetadataListener> listener;
if (NS_FAILED(aResult)) {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed, "
"creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
if (mKeyIsHash) {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
"failed, cannot create empty metadata since key is a hash. [this=%p,"
" rv=0x%08x]", this, aResult));
CacheFileIOManager::DoomFile(mHandle, nullptr);
retval = aResult;
}
else {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
InitEmptyMetadata();
retval = NS_OK;
}
InitEmptyMetadata();
mListener.swap(listener);
listener->OnMetadataRead(NS_OK);
listener->OnMetadataRead(retval);
return NS_OK;
}
@ -454,13 +506,25 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
MOZ_ASSERT(size != -1);
if (realOffset >= size) {
LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating empty "
"metadata. [this=%p, realOffset=%d, size=%lld]", this, realOffset,
size));
if (mKeyIsHash) {
LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, cannot create"
"empty metadata since key is a hash. [this=%p, realOffset=%d, "
"size=%lld]", this, realOffset, size));
CacheFileIOManager::DoomFile(mHandle, nullptr);
retval = NS_ERROR_FILE_CORRUPTED;
}
else {
LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating "
"empty metadata. [this=%p, realOffset=%d, size=%lld]", this,
realOffset, size));
InitEmptyMetadata();
retval = NS_OK;
}
InitEmptyMetadata();
mListener.swap(listener);
listener->OnMetadataRead(NS_OK);
listener->OnMetadataRead(retval);
return NS_OK;
}
@ -480,13 +544,25 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this);
if (NS_FAILED(rv)) {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
" synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
this, rv));
if (mKeyIsHash) {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
"failed synchronously, cannot create empty metadata since key is "
"a hash. [this=%p, rv=0x%08x]", this, rv));
CacheFileIOManager::DoomFile(mHandle, nullptr);
retval = rv;
}
else {
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
"failed synchronously, creating empty metadata. [this=%p, "
"rv=0x%08x]", this, rv));
InitEmptyMetadata();
retval = NS_OK;
}
InitEmptyMetadata();
mListener.swap(listener);
listener->OnMetadataRead(rv);
listener->OnMetadataRead(retval);
return NS_OK;
}
@ -497,13 +573,26 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
// Try to parse it.
rv = ParseMetadata(realOffset, realOffset - usedOffset);
if (NS_FAILED(rv)) {
LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
"empty metadata. [this=%p]", this));
InitEmptyMetadata();
if (mKeyIsHash) {
LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, cannot "
"create empty metadata since key is a hash. [this=%p]", this));
CacheFileIOManager::DoomFile(mHandle, nullptr);
retval = rv;
}
else {
LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
"empty metadata. [this=%p]", this));
InitEmptyMetadata();
retval = NS_OK;
}
}
else {
retval = NS_OK;
}
mListener.swap(listener);
listener->OnMetadataRead(NS_OK);
listener->OnMetadataRead(retval);
return NS_OK;
}
@ -582,19 +671,25 @@ CacheFileMetadata::ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset)
return NS_ERROR_FILE_CORRUPTED;
}
if (!mKeyIsHash) {
uint32_t keySize = reinterpret_cast<CacheFileMetadataHeader *>(
mBuf + hdrOffset)->mKeySize;
nsAutoCString origKey;
uint32_t keySize = reinterpret_cast<CacheFileMetadataHeader *>(
mBuf + hdrOffset)->mKeySize;
if (mKeyIsHash) {
// get the original key
origKey.Assign(mBuf + keyOffset, keySize);
}
else {
if (keySize != mKey.Length()) {
LOG(("CacheFileMetadata::ParseMetadata() - Key collision (1), key=%s [this=%p]",
nsCString(mBuf + keyOffset, keySize).get(), this));
LOG(("CacheFileMetadata::ParseMetadata() - Key collision (1), key=%s "
"[this=%p]", nsCString(mBuf + keyOffset, keySize).get(), this));
return NS_ERROR_FILE_CORRUPTED;
}
if (memcmp(mKey.get(), mBuf + keyOffset, mKey.Length()) != 0) {
LOG(("CacheFileMetadata::ParseMetadata() - Key collision (2), key=%s [this=%p]",
nsCString(mBuf + keyOffset, keySize).get(), this));
LOG(("CacheFileMetadata::ParseMetadata() - Key collision (2), key=%s "
"[this=%p]", nsCString(mBuf + keyOffset, keySize).get(), this));
return NS_ERROR_FILE_CORRUPTED;
}
}
@ -632,6 +727,11 @@ CacheFileMetadata::ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset)
memmove(mBuf, mBuf + elementsOffset, mElementsSize);
mOffset = aMetaOffset;
if (mKeyIsHash) {
mKey = origKey;
mKeyIsHash = false;
}
// TODO: shrink memory if buffer is too big
DoMemoryReport(MemoryUsage());

Просмотреть файл

@ -56,6 +56,9 @@ public:
void SetHandle(CacheFileHandle *aHandle);
nsresult GetKey(nsACString &_retval);
bool KeyIsHash();
nsresult ReadMetadata(CacheFileMetadataListener *aListener);
nsresult WriteMetadata(uint32_t aOffset,
CacheFileMetadataListener *aListener);