From f5a7fba76a24a96f906abcbd928f37e4eabfa76c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 12 Apr 2024 02:03:49 +0300
Subject: 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.
---
 indra/llimage/llimagepng.cpp   | 56 +++++++++++++++++++++++++++---------------
 indra/llimage/llpngwrapper.cpp |  7 ++++++
 2 files changed, 43 insertions(+), 20 deletions(-)

(limited to 'indra/llimage')

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();
-- 
cgit v1.2.3