diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2024-04-12 02:03:49 +0300 |
---|---|---|
committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2024-04-12 16:03:07 +0300 |
commit | f5a7fba76a24a96f906abcbd928f37e4eabfa76c (patch) | |
tree | 351bcb646148529e988b021c2533ab78a82d4ea0 | |
parent | 00e09ddcad8ec2c33ecbcdd0da09bd7819bc3509 (diff) |
viewer-private#226 Unhandled PngError throws application into a loop
png_read_info triggered a PngError, LLAppViewer::frame() handled it
instead of LLPngWrapper::readPng, and since status didn't
change viewer tried to decode image again and again and again.
-rw-r--r-- | indra/llimage/llimagepng.cpp | 56 | ||||
-rw-r--r-- | indra/llimage/llpngwrapper.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llfloaterimagepreview.cpp | 96 | ||||
-rw-r--r-- | indra/newview/llviewertexturelist.cpp | 122 | ||||
-rw-r--r-- | indra/newview/llviewertexturelist.h | 2 |
5 files changed, 161 insertions, 122 deletions
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index c4b98d8260..19c160e402 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -27,6 +27,7 @@ #include "linden_common.h" #include "stdtypes.h" #include "llerror.h" +#include "llexception.h" #include "llimage.h" #include "llpngwrapper.h" @@ -51,29 +52,44 @@ bool LLImagePNG::updateData() { resetLastError(); - // Check to make sure that this instance has been initialized with data - if (!getData() || (0 == getDataSize())) + try { - setLastError("Uninitialized instance of LLImagePNG"); + // Check to make sure that this instance has been initialized with data + if (!getData() || (0 == getDataSize())) + { + setLastError("Uninitialized instance of LLImagePNG"); + return false; + } + + // Decode the PNG data and extract sizing information + LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return false; + } + + LLPngWrapper::ImageInfo infop; + if (!pngWrapper.readPng(getData(), getDataSize(), NULL, &infop)) + { + setLastError(pngWrapper.getErrorMessage()); + return false; + } + + setSize(infop.mWidth, infop.mHeight, infop.mComponents); + } + catch (const LLContinueError& msg) + { + setLastError(msg.what()); + LOG_UNHANDLED_EXCEPTION(""); + return false; + } + catch (...) + { + setLastError("LLImagePNG"); + LOG_UNHANDLED_EXCEPTION(""); return false; } - - // Decode the PNG data and extract sizing information - LLPngWrapper pngWrapper; - if (!pngWrapper.isValidPng(getData())) - { - setLastError("LLImagePNG data does not have a valid PNG header!"); - return false; - } - - LLPngWrapper::ImageInfo infop; - if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop)) - { - setLastError(pngWrapper.getErrorMessage()); - return false; - } - - setSize(infop.mWidth, infop.mHeight, infop.mComponents); return true; } diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index cad7c00042..55d867728f 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -216,6 +216,13 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf releaseResources(); return (FALSE); } + catch (...) + { + mErrorMessage = "LLPngWrapper"; + releaseResources(); + LOG_UNHANDLED_EXCEPTION(""); + return (FALSE); + } // Clean up and return releaseResources(); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index ba0f97e2e1..6da1481c7e 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -332,54 +332,62 @@ void LLFloaterImagePreview::draw() //----------------------------------------------------------------------------- bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { - std::string exten = gDirUtilp->getExtension(src_filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); + try + { + std::string exten = gDirUtilp->getExtension(src_filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); - LLImageDimensionsInfo image_info; - if (!image_info.load(src_filename,codec)) - { - mImageLoadError = image_info.getLastError(); - return false; - } + LLImageDimensionsInfo image_info; + if (!image_info.load(src_filename, codec)) + { + mImageLoadError = image_info.getLastError(); + return false; + } - S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); - S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); + S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); + S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); - if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) - { - LLStringUtil::format_map_t args; - args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_height); + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); - mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); - return false; - } - - // Load the image - LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); - if (image.isNull()) - { - return false; - } - if (!image->load(src_filename)) - { - return false; - } - // Decompress or expand it in a raw image structure - LLPointer<LLImageRaw> raw_image = new LLImageRaw; - if (!image->decode(raw_image, 0.0f)) - { - return false; - } - // Check the image constraints - if ((image->getComponents() != 3) && (image->getComponents() != 4)) - { - image->setLastError("Image files with less than 3 or more than 4 components are not supported."); - return false; - } - - raw_image->biasedScaleToPowerOfTwo(1024); - mRawImagep = raw_image; + mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); + return false; + } + + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return false; + } + if (!image->load(src_filename)) + { + return false; + } + // Decompress or expand it in a raw image structure + LLPointer<LLImageRaw> raw_image = new LLImageRaw; + if (!image->decode(raw_image, 0.0f)) + { + return false; + } + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + + raw_image->biasedScaleToPowerOfTwo(1024); + mRawImagep = raw_image; + } + catch (...) + { + LOG_UNHANDLED_EXCEPTION(""); + return false; + } return true; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 971d3c4363..ccfaad2b15 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1297,7 +1297,7 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image, return true; } -BOOL LLViewerTextureList::createUploadFile(const std::string& filename, +bool LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec, const S32 max_image_dimentions, @@ -1305,64 +1305,72 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, bool force_square) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // Load the image - LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); - if (image.isNull()) - { - LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL; - return FALSE; - } - if (!image->load(filename)) - { - image->setLastError("Couldn't load the image to be uploaded."); - return FALSE; - } - // Decompress or expand it in a raw image structure - LLPointer<LLImageRaw> raw_image = new LLImageRaw; - if (!image->decode(raw_image, 0.0f)) - { - image->setLastError("Couldn't decode the image to be uploaded."); - return FALSE; - } - // Check the image constraints - if ((image->getComponents() != 3) && (image->getComponents() != 4)) - { - image->setLastError("Image files with less than 3 or more than 4 components are not supported."); - return FALSE; - } - if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions) + try { - std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx", - min_image_dimentions, - min_image_dimentions, - image->getWidth(), - image->getHeight()); - image->setLastError(reason); - return FALSE; + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL; + return false; + } + if (!image->load(filename)) + { + image->setLastError("Couldn't load the image to be uploaded."); + return false; + } + // Decompress or expand it in a raw image structure + LLPointer<LLImageRaw> raw_image = new LLImageRaw; + if (!image->decode(raw_image, 0.0f)) + { + image->setLastError("Couldn't decode the image to be uploaded."); + return false; + } + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions) + { + std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx", + min_image_dimentions, + min_image_dimentions, + image->getWidth(), + image->getHeight()); + image->setLastError(reason); + return false; + } + // Convert to j2c (JPEG2000) and save the file locally + LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square); + if (compressedImage.isNull()) + { + image->setLastError("Couldn't convert the image to jpeg2000."); + LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL; + return false; + } + if (!compressedImage->save(out_filename)) + { + image->setLastError("Couldn't create the jpeg2000 image for upload."); + LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL; + return false; + } + // Test to see if the encode and save worked + LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; + if (!integrity_test->loadAndValidate(out_filename)) + { + image->setLastError("The created jpeg2000 image is corrupt."); + LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL; + return false; + } } - // Convert to j2c (JPEG2000) and save the file locally - LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square); - if (compressedImage.isNull()) - { - image->setLastError("Couldn't convert the image to jpeg2000."); - LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL; - return FALSE; - } - if (!compressedImage->save(out_filename)) - { - image->setLastError("Couldn't create the jpeg2000 image for upload."); - LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL; - return FALSE; - } - // Test to see if the encode and save worked - LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; - if (!integrity_test->loadAndValidate( out_filename )) - { - image->setLastError("The created jpeg2000 image is corrupt."); - LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL; - return FALSE; - } - return TRUE; + catch (...) + { + LOG_UNHANDLED_EXCEPTION(""); + return false; + } + return true; } // note: modifies the argument raw_image!!!! diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 10a2cfa32a..04d3309f86 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -96,7 +96,7 @@ public: const std::string& out_filename, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT, const S32 min_image_dimentions = 0); - static BOOL createUploadFile(const std::string& filename, + static bool createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT, |