From 5205be0c65bf8dee8b51c112083a4cc8a7cebc49 Mon Sep 17 00:00:00 2001
From: pavelkproductengine <pavelkproductengine@lindenlab.com>
Date: Wed, 31 May 2017 19:28:46 +0300
Subject: [PATCH] STORM-2148 Crash on trying to save texture file(s) to
 computer from inventory

---
 doc/contributions.txt          | 1 +
 indra/llimage/llimagepng.cpp   | 4 ++--
 indra/llimage/llpngwrapper.cpp | 8 +++++++-
 indra/llimage/llpngwrapper.h   | 2 +-
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 1d591e2ec2..6e4cd76d77 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1304,6 +1304,7 @@ Sovereign Engineer
     MAINT-6218
     MAINT-6913
     STORM-2143
+    STORM-2148
 SpacedOut Frye
 	VWR-34
 	VWR-45
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index a299602d79..a4823ed859 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -124,12 +124,12 @@ bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
 
 	// Temporary buffer to hold the encoded image. Note: the final image
 	// size should be much smaller due to compression.
-	U32 bufferSize = getWidth() * getHeight() * getComponents() + 1024;
+	U32 bufferSize = getWidth() * getHeight() * getComponents() + 8192;
     U8* tmpWriteBuffer = new U8[ bufferSize ];
 
 	// Delegate actual encoding work to wrapper
 	LLPngWrapper pngWrapper;
-	if (! pngWrapper.writePng(raw_image, tmpWriteBuffer))
+	if (!pngWrapper.writePng(raw_image, tmpWriteBuffer, bufferSize))
 	{
 		setLastError(pngWrapper.getErrorMessage());
 		delete[] tmpWriteBuffer;
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index da289ea889..b2fa0ed315 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -112,6 +112,11 @@ void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_siz
 void LLPngWrapper::writeDataCallback(png_structp png_ptr, png_bytep src, png_size_t length)
 {
 	PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr);
+	if (dataInfo->mOffset + length > dataInfo->mDataSize)
+	{
+		png_error(png_ptr, "Data write error. Requested data size exceeds available data size.");
+		return;
+	}
 	U8 *dest = &dataInfo->mData[dataInfo->mOffset];
 	memcpy(dest, src, length);
 	dataInfo->mOffset += static_cast<U32>(length);
@@ -272,7 +277,7 @@ void LLPngWrapper::updateMetaData()
 
 // Method to write raw image into PNG at dest. The raw scanline begins
 // at the bottom of the image per SecondLife conventions.
-BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
+BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSize)
 {
 	try
 	{
@@ -313,6 +318,7 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
 		PngDataInfo dataPtr;
 		dataPtr.mData = dest;
 		dataPtr.mOffset = 0;
+		dataPtr.mDataSize = destSize;
 		png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush);
 
 		// Setup image params
diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h
index 27d7df3bef..8d42317b0f 100644
--- a/indra/llimage/llpngwrapper.h
+++ b/indra/llimage/llpngwrapper.h
@@ -45,7 +45,7 @@ public:
 
 	BOOL isValidPng(U8* src);
 	BOOL readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL);
-	BOOL writePng(const LLImageRaw* rawImage, U8* dst);
+	BOOL writePng(const LLImageRaw* rawImage, U8* dst, size_t destSize);
 	U32  getFinalSize();
 	const std::string& getErrorMessage();
 
-- 
GitLab