Bug 685471 - In PNG decoder, the allocating of mHeaderBuf can be prevented. r=joe@drew.ca

This commit is contained in:
Alfred Kayser 2013-05-04 11:39:47 +02:00
parent be2d315b5c
commit 8374926681
2 changed files with 37 additions and 31 deletions

View File

@ -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)) {

View File

@ -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