Bug 1007071 - Check cache entry size in CacheFileOutputStream::Write(), r=honzab

This commit is contained in:
Michal Novotny 2014-05-19 14:21:18 +02:00
parent 216f503246
commit 2266d17f80
6 changed files with 58 additions and 12 deletions

View File

@ -732,11 +732,19 @@ CacheFile::SetMemoryOnly()
nsresult
CacheFile::Doom(CacheFileListener *aCallback)
{
LOG(("CacheFile::Doom() [this=%p, listener=%p]", this, aCallback));
CacheFileAutoLock lock(this);
return DoomLocked(aCallback);
}
nsresult
CacheFile::DoomLocked(CacheFileListener *aCallback)
{
MOZ_ASSERT(mHandle || mMemoryOnly || mOpeningFile);
LOG(("CacheFile::Doom() [this=%p, listener=%p]", this, aCallback));
LOG(("CacheFile::DoomLocked() [this=%p, listener=%p]", this, aCallback));
nsresult rv = NS_OK;

View File

@ -127,6 +127,8 @@ private:
PRELOADER = 2
};
nsresult DoomLocked(CacheFileListener *aCallback);
nsresult GetChunk(uint32_t aIndex, ECallerType aCaller,
CacheFileChunkListener *aCallback,
CacheFileChunk **_retval);

View File

@ -229,11 +229,21 @@ NS_IMETHODIMP
CacheFileInputStream::CloseWithStatus(nsresult aStatus)
{
CacheFileAutoLock lock(mFile);
MOZ_ASSERT(!mInReadSegments);
LOG(("CacheFileInputStream::CloseWithStatus() [this=%p, aStatus=0x%08x]",
this, aStatus));
return CloseWithStatusLocked(aStatus);
}
nsresult
CacheFileInputStream::CloseWithStatusLocked(nsresult aStatus)
{
LOG(("CacheFileInputStream::CloseWithStatusLocked() [this=%p, "
"aStatus=0x%08x]", this, aStatus));
MOZ_ASSERT(!mInReadSegments);
if (mClosed) {
MOZ_ASSERT(!mCallback);
return NS_OK;
@ -242,8 +252,9 @@ CacheFileInputStream::CloseWithStatus(nsresult aStatus)
mClosed = true;
mStatus = NS_FAILED(aStatus) ? aStatus : NS_BASE_STREAM_CLOSED;
if (mChunk)
if (mChunk) {
ReleaseChunk();
}
// TODO propagate error from input stream to other streams ???
@ -400,12 +411,14 @@ CacheFileInputStream::OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx,
if (NS_SUCCEEDED(aResult)) {
mChunk = aChunk;
} else if (aResult != NS_ERROR_NOT_AVAILABLE) {
// We store the error in mStatus, so we can propagate it later to consumer
// Close the stream with error. The consumer will receive this error later
// in Read(), Available() etc. We need to handle NS_ERROR_NOT_AVAILABLE
// differently since it is returned when the requested chunk is not
// available and there is no writer that could create it, i.e. it means that
// we've reached the end of the file.
mStatus = aResult;
CloseWithStatusLocked(aResult);
return NS_OK;
}
MaybeNotifyListener();
@ -502,15 +515,16 @@ CacheFileInputStream::EnsureCorrectChunk(bool aReleaseOnly)
LOG(("CacheFileInputStream::EnsureCorrectChunk() - GetChunkLocked failed. "
"[this=%p, idx=%d, rv=0x%08x]", this, chunkIdx, rv));
if (rv != NS_ERROR_NOT_AVAILABLE) {
// We store the error in mStatus, so we can propagate it later to consumer
// Close the stream with error. The consumer will receive this error later
// in Read(), Available() etc. We need to handle NS_ERROR_NOT_AVAILABLE
// differently since it is returned when the requested chunk is not
// available and there is no writer that could create it, i.e. it means
// that we've reached the end of the file.
mStatus = rv;
CloseWithStatusLocked(rv);
return;
}
}
else if (!mChunk) {
} else if (!mChunk) {
mListeningForChunk = static_cast<int64_t>(chunkIdx);
}

View File

@ -43,6 +43,7 @@ public:
private:
virtual ~CacheFileInputStream();
nsresult CloseWithStatusLocked(nsresult aStatus);
void ReleaseChunk();
void EnsureCorrectChunk(bool aReleaseOnly);
void CanRead(int64_t *aCanRead, const char **aBuf);

View File

@ -94,6 +94,15 @@ CacheFileOutputStream::Write(const char * aBuf, uint32_t aCount,
return NS_FAILED(mStatus) ? mStatus : NS_BASE_STREAM_CLOSED;
}
if (CacheObserver::EntryIsTooBig(mPos + aCount, !mFile->mMemoryOnly)) {
LOG(("CacheFileOutputStream::Write() - Entry is too big, failing and "
"dooming the entry. [this=%p]", this));
mFile->DoomLocked(nullptr);
CloseWithStatusLocked(NS_ERROR_FILE_TOO_BIG);
return NS_ERROR_FILE_TOO_BIG;
}
*_retval = aCount;
while (aCount) {
@ -160,6 +169,15 @@ CacheFileOutputStream::CloseWithStatus(nsresult aStatus)
LOG(("CacheFileOutputStream::CloseWithStatus() [this=%p, aStatus=0x%08x]",
this, aStatus));
return CloseWithStatusLocked(aStatus);
}
nsresult
CacheFileOutputStream::CloseWithStatusLocked(nsresult aStatus)
{
LOG(("CacheFileOutputStream::CloseWithStatusLocked() [this=%p, "
"aStatus=0x%08x]", this, aStatus));
if (mClosed) {
MOZ_ASSERT(!mCallback);
return NS_OK;
@ -168,11 +186,13 @@ CacheFileOutputStream::CloseWithStatus(nsresult aStatus)
mClosed = true;
mStatus = NS_FAILED(aStatus) ? aStatus : NS_BASE_STREAM_CLOSED;
if (mChunk)
if (mChunk) {
ReleaseChunk();
}
if (mCallback)
if (mCallback) {
NotifyListener();
}
mFile->RemoveOutput(this);
@ -350,7 +370,7 @@ CacheFileOutputStream::EnsureCorrectChunk(bool aReleaseOnly)
if (NS_FAILED(rv)) {
LOG(("CacheFileOutputStream::EnsureCorrectChunk() - GetChunkLocked failed. "
"[this=%p, idx=%d, rv=0x%08x]", this, chunkIdx, rv));
mStatus = rv;
CloseWithStatusLocked(rv);
}
}

View File

@ -44,6 +44,7 @@ public:
private:
virtual ~CacheFileOutputStream();
nsresult CloseWithStatusLocked(nsresult aStatus);
void ReleaseChunk();
void EnsureCorrectChunk(bool aReleaseOnly);
void FillHole();