From 03d8b191958e1a35d8039da9fe611dae0318a857 Mon Sep 17 00:00:00 2001 From: "Brian R. Bondy" Date: Tue, 30 Aug 2011 01:12:59 -0400 Subject: [PATCH] Bug 682568 - ICO crash fix for size decodes. r=joe --- modules/libpr0n/decoders/nsBMPDecoder.cpp | 1 + modules/libpr0n/decoders/nsICODecoder.cpp | 30 +++++++++++++++++++++-- modules/libpr0n/decoders/nsICODecoder.h | 2 ++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/modules/libpr0n/decoders/nsBMPDecoder.cpp b/modules/libpr0n/decoders/nsBMPDecoder.cpp index c2b49127093b..7ea081982fd2 100644 --- a/modules/libpr0n/decoders/nsBMPDecoder.cpp +++ b/modules/libpr0n/decoders/nsBMPDecoder.cpp @@ -67,6 +67,7 @@ nsBMPDecoder::nsBMPDecoder() { mColors = nsnull; mRow = nsnull; + mImageData = nsnull; mCurPos = mPos = mNumColors = mRowBytes = 0; mOldLine = mCurLine = 1; // Otherwise decoder will never start mState = eRLEStateInitial; diff --git a/modules/libpr0n/decoders/nsICODecoder.cpp b/modules/libpr0n/decoders/nsICODecoder.cpp index 07563b74950a..f78a98b6c2ea 100644 --- a/modules/libpr0n/decoders/nsICODecoder.cpp +++ b/modules/libpr0n/decoders/nsICODecoder.cpp @@ -184,6 +184,15 @@ nsICODecoder::ExtractBPPFromBitmap(PRInt8 *bih) return bitsPerPixel; } +PRInt32 +nsICODecoder::ExtractBIHSizeFromBitmap(PRInt8 *bih) +{ + PRInt32 headerSize; + memcpy(&headerSize, bih, sizeof(headerSize)); + headerSize = LITTLE_TO_NATIVE32(headerSize); + return headerSize; +} + void nsICODecoder::SetHotSpotIfCursor() { if (!mIsCursor) { @@ -360,9 +369,16 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount) // If we have a BMP inside the ICO and we have read the BIH header if (!mIsPNG && mPos == mImageOffset + BITMAPINFOSIZE) { + + // Make sure we have a sane value for the bitmap information header + PRInt32 bihSize = ExtractBIHSizeFromBitmap(reinterpret_cast(mBIHraw)); + if (bihSize != BITMAPINFOSIZE) { + PostDataError(); + return; + } // We are extracting the BPP from the BIH header as it should be trusted // over the one we have from the icon header - mBPP = ExtractBPPFromBitmap((PRInt8*)mBIHraw); + mBPP = ExtractBPPFromBitmap(reinterpret_cast(mBIHraw)); // Init the bitmap decoder which will do most of the work for us // It will do everything except the AND mask which isn't present in bitmaps @@ -400,6 +416,11 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount) return; } + // We have the size. If we're doing a size decode, we got what + // we came for. + if (IsSizeDecode()) + return; + // Sometimes the ICO BPP header field is not filled out // so we should trust the contained resource over our own // information. @@ -487,7 +508,12 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount) mCurLine--; mRowBytes = 0; - PRUint32* imageData = static_cast(mContainedDecoder.get())->GetImageData(); + PRUint32* imageData = + static_cast(mContainedDecoder.get())->GetImageData(); + if (!imageData) { + PostDataError(); + return; + } PRUint32* decoded = imageData + mCurLine * mDirEntry.mWidth; PRUint32* decoded_end = decoded + mDirEntry.mWidth; PRUint8* p = mRow, *p_end = mRow + rowSize; diff --git a/modules/libpr0n/decoders/nsICODecoder.h b/modules/libpr0n/decoders/nsICODecoder.h index 9e21ca69c6b0..ce1f2721b53f 100644 --- a/modules/libpr0n/decoders/nsICODecoder.h +++ b/modules/libpr0n/decoders/nsICODecoder.h @@ -73,6 +73,8 @@ private: PRBool FillBitmapFileHeaderBuffer(PRInt8 *bfh); // Fixes the height of a BMP information header field void FillBitmapInformationBufferHeight(PRInt8 *bih); + // Extract bitmap info header size count from BMP information header + PRInt32 ExtractBIHSizeFromBitmap(PRInt8 *bih); // Extract bit count from BMP information header PRInt32 ExtractBPPFromBitmap(PRInt8 *bih); // Calculates the row size in bytes for the AND mask table