Bug 1290293 - Part 2d. Make nsJPEGDecoder clear unwritten pixels if the image is truncated. r=tnikkel

This commit is contained in:
Andrew Osmond 2016-08-18 09:55:45 -04:00
parent bd54fc7365
commit f6a09f3997
4 changed files with 59 additions and 1 deletions

View File

@ -31,6 +31,7 @@ Downscaler::Downscaler(const nsIntSize& aTargetSize)
, mXFilter(MakeUnique<skia::ConvolutionFilter1D>())
, mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
, mWindowCapacity(0)
, mClearValue(0)
, mHasAlpha(true)
, mFlipVertically(false)
{
@ -99,6 +100,7 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
double(mOriginalSize.height) / mTargetSize.height);
mOutputBuffer = aOutputBuffer;
mClearValue = aHasAlpha ? 0 : 0xFF;
mHasAlpha = aHasAlpha;
mFlipVertically = aFlipVertically;
@ -206,6 +208,15 @@ GetFilterOffsetAndLength(UniquePtr<skia::ConvolutionFilter1D>& aFilter,
aFilterLengthOut);
}
void
Downscaler::ClearRemainingRows()
{
while (!IsFrameComplete()) {
ClearRow();
CommitRow();
}
}
void
Downscaler::ClearRestOfRow(uint32_t aStartingAtCol)
{
@ -213,7 +224,7 @@ Downscaler::ClearRestOfRow(uint32_t aStartingAtCol)
uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
* sizeof(uint32_t);
memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
0, bytesToClear);
mClearValue, bytesToClear);
}
void

View File

@ -93,6 +93,9 @@ public:
return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
}
/// Clears the remaining unset rows.
void ClearRemainingRows();
/// Clears the current row buffer.
void ClearRow() { ClearRestOfRow(0); }
@ -139,6 +142,7 @@ private:
int32_t mPrevInvalidatedLine;
int32_t mCurrentOutLine;
int32_t mCurrentInLine;
uint8_t mClearValue;
bool mHasAlpha : 1;
bool mFlipVertically : 1;

View File

@ -169,9 +169,51 @@ nsJPEGDecoder::InitInternal()
return NS_OK;
}
void
nsJPEGDecoder::ClearRemainingRows()
{
if (mDownscaler) {
mDownscaler->ClearRemainingRows();
return;
}
if (!mImageData) {
return;
}
uint32_t offset = 0;
switch (mState) {
case JPEG_DECOMPRESS_PROGRESSIVE:
// If we already made one progressive pass, then we know we have written
// something valid to the output buffer.
if (mInfo.output_scan_number > 0) {
return;
}
MOZ_FALLTHROUGH;
case JPEG_DECOMPRESS_SEQUENTIAL:
case JPEG_HEADER:
case JPEG_START_DECOMPRESS:
offset = mInfo.output_scanline * mInfo.output_width * sizeof(uint32_t);
if (offset < mImageDataLength) {
break;
}
MOZ_FALLTHROUGH;
default:
return;
}
uint32_t length = mImageDataLength - offset;
MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
("nsJPEGDecoder::ClearRemainingRows: %p clear %u unset bytes",
this, length));
memset(mImageData + offset, 0xFF, length);
}
nsresult
nsJPEGDecoder::FinishInternal()
{
ClearRemainingRows();
// If we're not in any sort of error case, force our state to JPEG_DONE.
if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
(mState != JPEG_ERROR) &&

View File

@ -80,6 +80,7 @@ private:
LexerTransition<State> ReadJPEGData(const char* aData, size_t aLength);
LexerTransition<State> FinishedJPEGData();
void ClearRemainingRows();
StreamingLexer<State> mLexer;