diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 217880565a6..e5c77e63f55 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -103,7 +103,7 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo) #endif // First 8 bytes of a PNG file -const uint8_t +const uint8_t nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; nsPNGDecoder::nsPNGDecoder(RasterImage &aImage) @@ -111,9 +111,9 @@ nsPNGDecoder::nsPNGDecoder(RasterImage &aImage) mPNG(nullptr), mInfo(nullptr), mCMSLine(nullptr), interlacebuf(nullptr), mInProfile(nullptr), mTransform(nullptr), - mHeaderBuf(nullptr), mHeaderBytesRead(0), + mHeaderBytesRead(0), mCMSMode(0), mChannels(0), mFrameIsHidden(false), - mCMSMode(0), mDisablePremultipliedAlpha(false), + mDisablePremultipliedAlpha(false), mNumFrames(0) { } @@ -133,8 +133,6 @@ nsPNGDecoder::~nsPNGDecoder() if (mTransform) qcms_transform_release(mTransform); } - if (mHeaderBuf) - nsMemory::Free(mHeaderBuf); } // CreateFrame() is used for both simple and animated images @@ -193,6 +191,11 @@ void nsPNGDecoder::EndImageFrame() void nsPNGDecoder::InitInternal() { + // For size decodes, we don't need to initialize the png decoder + if (IsSizeDecode()) { + return; + } + mCMSMode = gfxPlatform::GetCMSMode(); if ((mDecodeFlags & DECODER_NO_COLORSPACE_CONVERSION) != 0) mCMSMode = eCMSMode_Off; @@ -217,12 +220,6 @@ nsPNGDecoder::InitInternal() 122, 84, 88, 116, '\0'}; /* zTXt */ #endif - // For size decodes, we only need a small buffer - if (IsSizeDecode()) { - mHeaderBuf = (uint8_t *)moz_xmalloc(BYTES_NEEDED_FOR_DIMENSIONS); - return; - } - /* For full decodes, do png init stuff */ /* Initialize the container's source image header. */ @@ -249,7 +246,7 @@ nsPNGDecoder::InitInternal() png_set_keep_unknown_chunks(mPNG, 1, color_chunks, 2); png_set_keep_unknown_chunks(mPNG, 1, unused_chunks, - (int)sizeof(unused_chunks)/5); + (int)sizeof(unused_chunks)/5); #endif #ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED @@ -289,25 +286,34 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount) if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) return; - // Read data into our header buffer - uint32_t bytesToRead = std::min(aCount, BYTES_NEEDED_FOR_DIMENSIONS - - mHeaderBytesRead); - memcpy(mHeaderBuf + mHeaderBytesRead, aBuffer, bytesToRead); - mHeaderBytesRead += bytesToRead; + // Scan the header for the width and height bytes + PRUint32 pos = 0; + const uint8_t *bptr = (uint8_t *)aBuffer; + + while (pos < aCount && mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS) { + // Verify the signature bytes + if (mHeaderBytesRead < sizeof(pngSignatureBytes)) { + if (bptr[pos] != nsPNGDecoder::pngSignatureBytes[mHeaderBytesRead]) { + PostDataError(); + return; + } + } + + // Get width and height bytes into the buffer + if ((mHeaderBytesRead >= WIDTH_OFFSET) && + (mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS)) { + mSizeBytes[mHeaderBytesRead - WIDTH_OFFSET] = bptr[pos]; + } + pos ++; + mHeaderBytesRead ++; + } // If we're done now, verify the data and set up the container if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) { - // Check that the signature bytes are right - if (memcmp(mHeaderBuf, nsPNGDecoder::pngSignatureBytes, - sizeof(pngSignatureBytes))) { - PostDataError(); - return; - } - // Grab the width and height, accounting for endianness (thanks libpng!) - uint32_t width = png_get_uint_32(mHeaderBuf + WIDTH_OFFSET); - uint32_t height = png_get_uint_32(mHeaderBuf + HEIGHT_OFFSET); + PRUint32 width = png_get_uint_32(mSizeBytes); + PRUint32 height = png_get_uint_32(mSizeBytes + 4); // Too big? if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) { diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h index f881e54f245..65ddc4733fb 100644 --- a/image/decoders/nsPNGDecoder.h +++ b/image/decoders/nsPNGDecoder.h @@ -79,15 +79,15 @@ public: gfxASurface::gfxImageFormat format; // For size decodes - uint8_t *mHeaderBuf; - uint32_t mHeaderBytesRead; + PRUint8 mSizeBytes[8]; // Space for width and height, both 4 bytes + PRUint32 mHeaderBytesRead; + + // whether CMS or premultiplied alpha are forced off + uint32_t mCMSMode; uint8_t mChannels; bool mFrameHasNoAlpha; bool mFrameIsHidden; - - // whether CMS or premultiplied alpha are forced off - uint32_t mCMSMode; bool mDisablePremultipliedAlpha; struct AnimFrameInfo