Bug 514033 - Error recovery for imagelib - part 2 - Notify the superclass error reporting framework when an error occurs.r=joe

This commit is contained in:
Bobby Holley 2010-09-12 08:22:27 -07:00
Родитель d90e859bc8
Коммит 7b91b495f6
11 изменённых файлов: 69 добавлений и 58 удалений

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

@ -71,7 +71,6 @@ nsBMPDecoder::nsBMPDecoder()
mState = eRLEStateInitial; mState = eRLEStateInitial;
mStateData = 0; mStateData = 0;
mLOH = WIN_HEADER_LENGTH; mLOH = WIN_HEADER_LENGTH;
mError = PR_FALSE;
} }
nsBMPDecoder::~nsBMPDecoder() nsBMPDecoder::~nsBMPDecoder()
@ -100,7 +99,7 @@ nsBMPDecoder::FinishInternal()
NS_ABORT_IF_FALSE(GetFrameCount() <= 1, "Multiple BMP frames?"); NS_ABORT_IF_FALSE(GetFrameCount() <= 1, "Multiple BMP frames?");
// Send notifications if appropriate // Send notifications if appropriate
if (!IsSizeDecode() && !mError && (GetFrameCount() == 1)) { if (!IsSizeDecode() && !IsError() && (GetFrameCount() == 1)) {
PostFrameStop(); PostFrameStop();
mImage->DecodingComplete(); mImage->DecodingComplete();
if (mObserver) { if (mObserver) {
@ -155,7 +154,7 @@ nsresult
nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount) nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
{ {
// No forgiveness // No forgiveness
if (mError) if (IsError())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// aCount=0 means EOF, mCurLine=0 means we're past end of image // aCount=0 means EOF, mCurLine=0 means we're past end of image
@ -175,7 +174,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
if (mPos == BFH_LENGTH) { if (mPos == BFH_LENGTH) {
ProcessFileHeader(); ProcessFileHeader();
if (mBFH.signature[0] != 'B' || mBFH.signature[1] != 'M') { if (mBFH.signature[0] != 'B' || mBFH.signature[1] != 'M') {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (mBFH.bihsize == OS2_BIH_LENGTH) if (mBFH.bihsize == OS2_BIH_LENGTH)
@ -197,7 +196,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// Verify we support this bit depth // Verify we support this bit depth
if (mBIH.bpp != 1 && mBIH.bpp != 4 && mBIH.bpp != 8 && if (mBIH.bpp != 1 && mBIH.bpp != 4 && mBIH.bpp != 8 &&
mBIH.bpp != 16 && mBIH.bpp != 24 && mBIH.bpp != 32) { mBIH.bpp != 16 && mBIH.bpp != 24 && mBIH.bpp != 32) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
@ -205,7 +204,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// Reject extremely wide images to keep the math sane // Reject extremely wide images to keep the math sane
const PRInt32 k64KWidth = 0x0000FFFF; const PRInt32 k64KWidth = 0x0000FFFF;
if (mBIH.width < 0 || mBIH.width > k64KWidth) { if (mBIH.width < 0 || mBIH.width > k64KWidth) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -230,7 +229,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// Always allocate 256 even though mNumColors might be smaller // Always allocate 256 even though mNumColors might be smaller
mColors = new colorTable[256]; mColors = new colorTable[256];
if (!mColors) { if (!mColors) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -255,7 +254,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// to make exact calculations here, that's unnecessary. // to make exact calculations here, that's unnecessary.
// Also, it compensates rounding error. // Also, it compensates rounding error.
if (!mRow) { if (!mRow) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
rv = mImage->AppendFrame(0, 0, mBIH.width, real_height, gfxASurface::ImageFormatRGB24, rv = mImage->AppendFrame(0, 0, mBIH.width, real_height, gfxASurface::ImageFormatRGB24,
@ -263,7 +262,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
} }
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (!mImageData) { if (!mImageData) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_FAILURE);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -272,7 +271,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8)) if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8))
|| ((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) && (mBIH.bpp != 1))) { || ((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) && (mBIH.bpp != 1))) {
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n")); PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n"));
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Clear the image, as the RLE may jump over areas // Clear the image, as the RLE may jump over areas
@ -416,7 +415,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8)) if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8))
|| ((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) && (mBIH.bpp != 1))) { || ((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) && (mBIH.bpp != 1))) {
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n")); PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n"));
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -484,7 +483,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// pixel too many, but only if their width is odd. // pixel too many, but only if their width is odd.
mStateData -= mBIH.width & 1; mStateData -= mBIH.width & 1;
if (mCurPos + mStateData > (PRUint32)mBIH.width) { if (mCurPos + mStateData > (PRUint32)mBIH.width) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
} }
@ -569,8 +568,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
continue; continue;
default : default :
NS_NOTREACHED("BMP RLE decompression: unknown state!"); NS_ABORT_IF_FALSE(0, "BMP RLE decompression: unknown state!");
mError = PR_TRUE; PostDecoderError(NS_ERROR_UNEXPECTED);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Because of the use of the continue statement // Because of the use of the continue statement

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

@ -178,7 +178,6 @@ private:
ERLEState mState; ///< Maintains the current state of the RLE decoding ERLEState mState; ///< Maintains the current state of the RLE decoding
PRUint32 mStateData;///< Decoding information that is needed depending on mState PRUint32 mStateData;///< Decoding information that is needed depending on mState
PRBool mError; ///< Did we hit an error?
/** Set mBFH from the raw data in mRawBuf, converting from little-endian /** Set mBFH from the raw data in mRawBuf, converting from little-endian
* data to native data as necessary */ * data to native data as necessary */

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

@ -117,7 +117,6 @@ nsGIFDecoder2::nsGIFDecoder2()
, mLastFlushedPass(0) , mLastFlushedPass(0)
, mGIFOpen(PR_FALSE) , mGIFOpen(PR_FALSE)
, mSawTransparency(PR_FALSE) , mSawTransparency(PR_FALSE)
, mError(PR_FALSE)
, mEnded(PR_FALSE) , mEnded(PR_FALSE)
{ {
// Clear out the structure, excluding the arrays // Clear out the structure, excluding the arrays
@ -147,7 +146,7 @@ nsresult
nsGIFDecoder2::FinishInternal() nsGIFDecoder2::FinishInternal()
{ {
// Send notifications if appropriate // Send notifications if appropriate
if (!IsSizeDecode() && !mError) { if (!IsSizeDecode() && !IsError()) {
if (mCurrentFrame == mGIFStruct.images_decoded) if (mCurrentFrame == mGIFStruct.images_decoded)
EndImageFrame(); EndImageFrame();
EndGIF(/* aSuccess = */ PR_TRUE); EndGIF(/* aSuccess = */ PR_TRUE);
@ -194,7 +193,7 @@ nsresult
nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount) nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount)
{ {
// Don't forgive previously flagged errors // Don't forgive previously flagged errors
if (mError) if (IsError())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// Push the data to the GIF decoder // Push the data to the GIF decoder
@ -212,7 +211,7 @@ nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount)
// of an animated gif, we still want to display it (mostly for legacy reasons). // of an animated gif, we still want to display it (mostly for legacy reasons).
// libpr0n code is strict, so we have to lie and tell it we were successful. So // libpr0n code is strict, so we have to lie and tell it we were successful. So
// if we have something to salvage, we send off final decode notifications, and // if we have something to salvage, we send off final decode notifications, and
// pretend that we're decoded. Otherwise, we set mError. // pretend that we're decoded. Otherwise, we set a data error.
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// Determine if we want to salvage the situation. // Determine if we want to salvage the situation.
@ -223,12 +222,12 @@ nsGIFDecoder2::WriteInternal(const char *aBuffer, PRUint32 aCount)
EndGIF(/* aSuccess = */ PR_TRUE); EndGIF(/* aSuccess = */ PR_TRUE);
} }
// Otherwise, set mError // Otherwise, set an error
else else
mError = PR_TRUE; PostDataError();
} }
return mError ? NS_ERROR_FAILURE : NS_OK; return IsError() ? NS_ERROR_FAILURE : NS_OK;
} }
//****************************************************************************** //******************************************************************************

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

@ -99,7 +99,6 @@ private:
PRUint8 mColorMask; // Apply this to the pixel to keep within colormap PRUint8 mColorMask; // Apply this to the pixel to keep within colormap
PRPackedBool mGIFOpen; PRPackedBool mGIFOpen;
PRPackedBool mSawTransparency; PRPackedBool mSawTransparency;
PRPackedBool mError;
PRPackedBool mEnded; PRPackedBool mEnded;
gif_struct mGIFStruct; gif_struct mGIFStruct;

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

@ -79,7 +79,6 @@ nsICODecoder::nsICODecoder()
mColors = nsnull; mColors = nsnull;
mRow = nsnull; mRow = nsnull;
mHaveAlphaData = mDecodingAndMask = PR_FALSE; mHaveAlphaData = mDecodingAndMask = PR_FALSE;
mError = PR_FALSE;
} }
nsICODecoder::~nsICODecoder() nsICODecoder::~nsICODecoder()
@ -120,7 +119,7 @@ nsICODecoder::FinishInternal()
NS_ABORT_IF_FALSE(GetFrameCount() <= 1, "Multiple ICO frames?"); NS_ABORT_IF_FALSE(GetFrameCount() <= 1, "Multiple ICO frames?");
// Send notifications if appropriate // Send notifications if appropriate
if (!IsSizeDecode() && !mError && (GetFrameCount() == 1)) { if (!IsSizeDecode() && !IsError() && (GetFrameCount() == 1)) {
// Invalidate // Invalidate
nsIntRect r(0, 0, mDirEntry.mWidth, mDirEntry.mHeight); nsIntRect r(0, 0, mDirEntry.mWidth, mDirEntry.mHeight);
@ -141,7 +140,7 @@ nsresult
nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount) nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
{ {
// No forgiveness // No forgiveness
if (mError) if (IsError())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
if (!aCount) // aCount=0 means EOF if (!aCount) // aCount=0 means EOF
@ -150,7 +149,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons. while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons.
if (mPos == 2) { // if the third byte is 1: This is an icon, 2: a cursor if (mPos == 2) { // if the third byte is 1: This is an icon, 2: a cursor
if ((*aBuffer != 1) && (*aBuffer != 2)) { if ((*aBuffer != 1) && (*aBuffer != 2)) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mIsCursor = (*aBuffer == 2); mIsCursor = (*aBuffer == 2);
@ -194,7 +193,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// ensure mImageOffset is >= the size of the direntry headers (bug #245631) // ensure mImageOffset is >= the size of the direntry headers (bug #245631)
PRUint32 minImageOffset = DIRENTRYOFFSET + mNumIcons*sizeof(mDirEntryArray); PRUint32 minImageOffset = DIRENTRYOFFSET + mNumIcons*sizeof(mDirEntryArray);
if (mImageOffset < minImageOffset) { if (mImageOffset < minImageOffset) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -248,13 +247,13 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
mNumColors = 256; mNumColors = 256;
break; break;
default: default:
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mColors = new colorTable[mNumColors]; mColors = new colorTable[mNumColors];
if (!mColors) { if (!mColors) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
} }
@ -278,7 +277,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// to make exact calculations here, that's unnecessary. // to make exact calculations here, that's unnecessary.
// Also, it compensates rounding error. // Also, it compensates rounding error.
if (!mRow) { if (!mRow) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -325,10 +324,12 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
// Ensure memory has been allocated before decoding. If we get this far // Ensure memory has been allocated before decoding. If we get this far
// without allocated memory, the file is most likely invalid. // without allocated memory, the file is most likely invalid.
// XXXbholley - If null values can be triggered by bad input, why are we
// asserting here?
NS_ASSERTION(mRow, "mRow is null"); NS_ASSERTION(mRow, "mRow is null");
NS_ASSERTION(mImageData, "mImageData is null"); NS_ASSERTION(mImageData, "mImageData is null");
if (!mRow || !mImageData) { if (!mRow || !mImageData) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -414,7 +415,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
break; break;
default: default:
// This is probably the wrong place to check this... // This is probably the wrong place to check this...
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -436,7 +437,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
mCurLine = mDirEntry.mHeight; mCurLine = mDirEntry.mHeight;
mRow = (PRUint8*)realloc(mRow, rowSize); mRow = (PRUint8*)realloc(mRow, rowSize);
if (!mRow) { if (!mRow) {
mError = PR_TRUE; PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
} }
@ -445,7 +446,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
NS_ASSERTION(mRow, "mRow is null"); NS_ASSERTION(mRow, "mRow is null");
NS_ASSERTION(mImageData, "mImageData is null"); NS_ASSERTION(mImageData, "mImageData is null");
if (!mRow || !mImageData) { if (!mRow || !mImageData) {
mError = PR_TRUE; PostDataError();
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

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

@ -112,7 +112,6 @@ private:
PRPackedBool mHaveAlphaData; PRPackedBool mHaveAlphaData;
PRPackedBool mIsCursor; PRPackedBool mIsCursor;
PRPackedBool mDecodingAndMask; PRPackedBool mDecodingAndMask;
PRPackedBool mError;
}; };
} // namespace imagelib } // namespace imagelib

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

@ -92,6 +92,9 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
{ {
nsresult rv; nsresult rv;
if (IsError())
return NS_IMAGELIB_ERROR_FAILURE;
// We put this here to avoid errors about crossing initialization with case // We put this here to avoid errors about crossing initialization with case
// jumps on linux. // jumps on linux.
PRUint32 bytesToRead = 0; PRUint32 bytesToRead = 0;
@ -133,7 +136,7 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
gfxASurface::ImageFormatARGB32, gfxASurface::ImageFormatARGB32,
&mImageData, &mPixBytesTotal); &mImageData, &mPixBytesTotal);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mState = iconStateError; PostDecoderError(rv);
return rv; return rv;
} }
@ -175,10 +178,6 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
aCount = 0; aCount = 0;
break; break;
case iconStateError:
return NS_IMAGELIB_ERROR_FAILURE;
break;
} }
} }

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

@ -96,8 +96,7 @@ enum {
iconStateStart = 0, iconStateStart = 0,
iconStateHaveHeight = 1, iconStateHaveHeight = 1,
iconStateReadPixels = 2, iconStateReadPixels = 2,
iconStateFinished = 3, iconStateFinished = 3
iconStateError = 4
}; };
} // namespace imagelib } // namespace imagelib

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

@ -155,6 +155,7 @@ nsJPEGDecoder::InitInternal()
/* If we get here, the JPEG code has signaled an error. /* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return. * We need to clean up the JPEG object, close the input file, and return.
*/ */
PostDecoderError(NS_ERROR_FAILURE);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -217,6 +218,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
nsresult error_code; nsresult error_code;
if ((error_code = setjmp(mErr.setjmp_buffer)) != 0) { if ((error_code = setjmp(mErr.setjmp_buffer)) != 0) {
if (error_code == NS_ERROR_FAILURE) { if (error_code == NS_ERROR_FAILURE) {
PostDataError();
/* Error due to corrupt stream - return NS_OK and consume silently /* Error due to corrupt stream - return NS_OK and consume silently
so that libpr0n doesn't throw away a partial image load */ so that libpr0n doesn't throw away a partial image load */
mState = JPEG_SINK_NON_JPEG_TRAILER; mState = JPEG_SINK_NON_JPEG_TRAILER;
@ -227,6 +229,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
/* Error due to reasons external to the stream (probably out of /* Error due to reasons external to the stream (probably out of
memory) - let libpr0n attempt to clean up, even though memory) - let libpr0n attempt to clean up, even though
mozilla is seconds away from falling flat on its face. */ mozilla is seconds away from falling flat on its face. */
PostDecoderError(error_code);
mState = JPEG_ERROR; mState = JPEG_ERROR;
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (setjmp returned an error)")); ("} (setjmp returned an error)"));
@ -297,6 +300,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
break; break;
default: default:
mState = JPEG_ERROR; mState = JPEG_ERROR;
PostDataError();
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (unknown colorpsace (1))")); ("} (unknown colorpsace (1))"));
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
@ -313,6 +317,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
break; break;
default: default:
mState = JPEG_ERROR; mState = JPEG_ERROR;
PostDataError();
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (unknown colorpsace (2))")); ("} (unknown colorpsace (2))"));
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
@ -362,6 +367,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
break; break;
default: default:
mState = JPEG_ERROR; mState = JPEG_ERROR;
PostDataError();
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (unknown colorpsace (3))")); ("} (unknown colorpsace (3))"));
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
@ -386,6 +392,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
gfxASurface::ImageFormatRGB24, gfxASurface::ImageFormatRGB24,
&mImageData, &imagelength))) { &mImageData, &imagelength))) {
mState = JPEG_ERROR; mState = JPEG_ERROR;
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (could not initialize image frame)")); ("} (could not initialize image frame)"));
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -551,9 +558,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
break; break;
case JPEG_ERROR: case JPEG_ERROR:
PR_LOG(gJPEGlog, PR_LOG_DEBUG, NS_ABORT_IF_FALSE(0, "Should always return immediately after error and not re-enter decoder");
("[this=%p] nsJPEGDecoder::ProcessData -- entering JPEG_ERROR case\n", this));
return NS_ERROR_FAILURE;
} }
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,

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

@ -86,7 +86,7 @@ nsPNGDecoder::nsPNGDecoder() :
mCMSLine(nsnull), interlacebuf(nsnull), mCMSLine(nsnull), interlacebuf(nsnull),
mInProfile(nsnull), mTransform(nsnull), mInProfile(nsnull), mTransform(nsnull),
mHeaderBuf(nsnull), mHeaderBytesRead(0), mHeaderBuf(nsnull), mHeaderBytesRead(0),
mChannels(0), mError(PR_FALSE), mFrameIsHidden(PR_FALSE), mChannels(0), mFrameIsHidden(PR_FALSE),
mNotifiedDone(PR_FALSE) mNotifiedDone(PR_FALSE)
{ {
} }
@ -242,8 +242,10 @@ nsPNGDecoder::InitInternal()
// For size decodes, we only need a small buffer // For size decodes, we only need a small buffer
if (IsSizeDecode()) { if (IsSizeDecode()) {
mHeaderBuf = (PRUint8 *)nsMemory::Alloc(BYTES_NEEDED_FOR_DIMENSIONS); mHeaderBuf = (PRUint8 *)nsMemory::Alloc(BYTES_NEEDED_FOR_DIMENSIONS);
if (!mHeaderBuf) if (!mHeaderBuf) {
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK; return NS_OK;
} }
@ -255,11 +257,14 @@ nsPNGDecoder::InitInternal()
mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, nsPNGDecoder::error_callback, NULL, nsPNGDecoder::error_callback,
nsPNGDecoder::warning_callback); nsPNGDecoder::warning_callback);
if (!mPNG) if (!mPNG) {
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
}
mInfo = png_create_info_struct(mPNG); mInfo = png_create_info_struct(mPNG);
if (!mInfo) { if (!mInfo) {
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
png_destroy_read_struct(&mPNG, NULL, NULL); png_destroy_read_struct(&mPNG, NULL, NULL);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -308,7 +313,7 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
PRUint32 height = 0; PRUint32 height = 0;
// No forgiveness if we previously hit an error // No forgiveness if we previously hit an error
if (mError) if (IsError())
goto error; goto error;
// If we only want width/height, we don't need to go through libpng // If we only want width/height, we don't need to go through libpng
@ -328,16 +333,20 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) { if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {
// Check that the signature bytes are right // Check that the signature bytes are right
if (memcmp(mHeaderBuf, pngSignatureBytes, sizeof(pngSignatureBytes))) if (memcmp(mHeaderBuf, pngSignatureBytes, sizeof(pngSignatureBytes))) {
PostDataError();
goto error; goto error;
}
// Grab the width and height, accounting for endianness (thanks libpng!) // Grab the width and height, accounting for endianness (thanks libpng!)
width = png_get_uint_32(mHeaderBuf + WIDTH_OFFSET); width = png_get_uint_32(mHeaderBuf + WIDTH_OFFSET);
height = png_get_uint_32(mHeaderBuf + HEIGHT_OFFSET); height = png_get_uint_32(mHeaderBuf + HEIGHT_OFFSET);
// Too big? // Too big?
if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) {
PostDataError();
goto error; goto error;
}
// Post our size to the superclass // Post our size to the superclass
PostSize(width, height); PostSize(width, height);
@ -349,6 +358,12 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
// libpng uses setjmp/longjmp for error handling - set the buffer // libpng uses setjmp/longjmp for error handling - set the buffer
if (setjmp(png_jmpbuf(mPNG))) { if (setjmp(png_jmpbuf(mPNG))) {
// We might not really know what caused the error, but it makes more
// sense to blame the data.
if (!IsError())
PostDataError();
png_destroy_read_struct(&mPNG, &mInfo, NULL); png_destroy_read_struct(&mPNG, &mInfo, NULL);
goto error; goto error;
} }
@ -362,7 +377,7 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
// Consolidate error handling // Consolidate error handling
error: error:
mError = PR_TRUE; NS_ABORT_IF_FALSE(IsError(), "Should only get here if we flagged an error!");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -791,9 +806,7 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
} }
break; break;
default: default:
NS_ERROR("Unknown PNG format!"); longjmp(png_jmpbuf(decoder->mPNG), 1);
NS_ABORT();
break;
} }
if (!rowHasNoAlpha) if (!rowHasNoAlpha)
@ -854,7 +867,7 @@ nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr)); static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
// We shouldn't get here if we've hit an error // We shouldn't get here if we've hit an error
NS_ABORT_IF_FALSE(!decoder->mError, "Finishing up PNG but hit error!"); NS_ABORT_IF_FALSE(!decoder->IsError(), "Finishing up PNG but hit error!");
#ifdef PNG_APNG_SUPPORTED #ifdef PNG_APNG_SUPPORTED
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) { if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {

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

@ -91,7 +91,6 @@ public:
PRUint32 mHeaderBytesRead; PRUint32 mHeaderBytesRead;
PRUint8 mChannels; PRUint8 mChannels;
PRPackedBool mError;
PRPackedBool mFrameHasNoAlpha; PRPackedBool mFrameHasNoAlpha;
PRPackedBool mFrameIsHidden; PRPackedBool mFrameIsHidden;
PRPackedBool mNotifiedDone; PRPackedBool mNotifiedDone;