diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index 294f68b1220cf0ad761a8f4daad227147007c9e0..7735dc13797a2807c7425eed8c778f501554def1 100755 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -67,7 +67,7 @@ BOOL LLImagePNG::updateData() } LLPngWrapper::ImageInfo infop; - if (! pngWrapper.readPng(getData(), NULL, &infop)) + if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop)) { setLastError(pngWrapper.getErrorMessage()); return FALSE; @@ -102,7 +102,7 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time) return FALSE; } - if (! pngWrapper.readPng(getData(), raw_image)) + if (! pngWrapper.readPng(getData(), getDataSize(), raw_image)) { setLastError(pngWrapper.getErrorMessage()); return FALSE; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 2cc7d3c460c7ed93146271a1e013ab26d7ef7b49..aad139f57087c2dc818a67f57ee08d1bf6840522 100755 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -87,6 +87,12 @@ void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg) void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_size_t length) { PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr); + if(dataInfo->mOffset + length > dataInfo->mDataSize) + { + png_error(png_ptr, "Data read error. Requested data size exceeds available data size."); + return; + } + U8 *src = &dataInfo->mData[dataInfo->mOffset]; memcpy(dest, src, length); dataInfo->mOffset += static_cast<U32>(length); @@ -114,7 +120,7 @@ void LLPngWrapper::writeFlush(png_structp png_ptr) // The scanline also begins at the bottom of // the image (per SecondLife conventions) instead of at the top, so we // must assign row-pointers in "reverse" order. -BOOL LLPngWrapper::readPng(U8* src, LLImageRaw* rawImage, ImageInfo *infop) +BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop) { try { @@ -133,6 +139,7 @@ BOOL LLPngWrapper::readPng(U8* src, LLImageRaw* rawImage, ImageInfo *infop) PngDataInfo dataPtr; dataPtr.mData = src; dataPtr.mOffset = 0; + dataPtr.mDataSize = dataSize; png_set_read_fn(mReadPngPtr, &dataPtr, &readDataCallback); png_set_sig_bytes(mReadPngPtr, 0); diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index 739f4359961c6155bcfb3bd68fb11c70326b8883..27d7df3bef9a9af161542a7b2d4077908cbfcd50 100755 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -44,7 +44,7 @@ class LLPngWrapper }; BOOL isValidPng(U8* src); - BOOL readPng(U8* src, LLImageRaw* rawImage, ImageInfo *infop = NULL); + BOOL readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL); BOOL writePng(const LLImageRaw* rawImage, U8* dst); U32 getFinalSize(); const std::string& getErrorMessage(); @@ -61,6 +61,7 @@ class LLPngWrapper { U8 *mData; U32 mOffset; + S32 mDataSize; }; static void writeFlush(png_structp png_ptr);