vcl/source/filter/png/PngImageReader.cxx |   72 ++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 19 deletions(-)

New commits:
commit 03b0afa5fdf8f4bd0fb23dbfd1c19d50202c07bd
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Apr 30 17:42:56 2025 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Apr 30 14:42:37 2025 +0200

    vcl: more fine grained handling of error in PNG reader
    
    Handle if the error happens at init, reading and after reading
    differently. At init we don't need to handle the bitmap as nothing
    has yet been writtent to it. Also after reading we can handle it
    like no error happened, because we have read the data completely
    but the error happened after that (like missing IEND chunk for
    example).
    
    Change the error and warning messgaes when reading from the stream.
    
    Change-Id: I927b8679f168da43e8e6e00663ff551064b870c8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184811
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/source/filter/png/PngImageReader.cxx 
b/vcl/source/filter/png/PngImageReader.cxx
index 595a3a0b0c67..e35216919bdc 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -41,12 +41,14 @@ void lclReadStream(png_structp pPng, png_bytep pOutBytes, 
png_size_t nBytesToRea
     if (nBytesRead != nBytesToRead)
     {
         if (!nBytesRead)
-            png_error(pPng, "Error reading");
+        {
+            png_error(pPng, "Stream read: no data read from the stream.");
+        }
         else
         {
             // Make sure to not reuse old data (could cause infinite loop).
             memset(pOutBytes + nBytesRead, 0, nBytesToRead - nBytesRead);
-            png_warning(pPng, "Short read");
+            png_warning(pPng, "Stream read: read less bytes than asked for.");
         }
     }
 }
@@ -370,23 +372,8 @@ bool reader(SvStream& rStream, ImportOutput& rImportOutput,
 
     if (setjmp(png_jmpbuf(pPng)))
     {
-        if (!bUseExistingBitmap)
-        {
-            // Set the bitmap if it contains something, even on failure. This 
allows
-            // reading images that are only partially broken.
-            pWriteAccessInstance.reset();
-            pWriteAccessAlphaInstance.reset();
-            if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
-                aBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
-            else if (!aBitmap.IsEmpty())
-                aBitmapEx = BitmapEx(aBitmap);
-            if (!aBitmapEx.IsEmpty() && !prefSize.IsEmpty())
-            {
-                aBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
-                aBitmapEx.SetPrefSize(prefSize);
-            }
-            rImportOutput.moBitmap = aBitmapEx;
-        }
+        pWriteAccessInstance.reset();
+        pWriteAccessAlphaInstance.reset();
         return false;
     }
 
@@ -521,6 +508,31 @@ bool reader(SvStream& rStream, ImportOutput& rImportOutput,
     BitmapScopedWriteAccess& pWriteAccessAlpha
         = pAlphaAccess ? *pAlphaAccess : pWriteAccessAlphaInstance;
 
+    if (setjmp(png_jmpbuf(pPng)))
+    {
+        pWriteAccessInstance.reset();
+        pWriteAccessAlphaInstance.reset();
+
+        if (!bUseExistingBitmap)
+        {
+            // Set the bitmap if it contains something, even on failure. This 
allows
+            // reading images that are only partially broken.
+            pWriteAccessInstance.reset();
+            pWriteAccessAlphaInstance.reset();
+            if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
+                aBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+            else if (!aBitmap.IsEmpty())
+                aBitmapEx = BitmapEx(aBitmap);
+            if (!aBitmapEx.IsEmpty() && !prefSize.IsEmpty())
+            {
+                aBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+                aBitmapEx.SetPrefSize(prefSize);
+            }
+            rImportOutput.moBitmap = aBitmapEx;
+        }
+        return false;
+    }
+
     if (colorType == PNG_COLOR_TYPE_RGB)
     {
         ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
@@ -665,6 +677,28 @@ bool reader(SvStream& rStream, ImportOutput& rImportOutput,
         }
     }
 
+    // If an error is thrown when calling png_read_end
+    if (setjmp(png_jmpbuf(pPng)))
+    {
+        if (!bUseExistingBitmap)
+        {
+            pWriteAccessInstance.reset();
+            pWriteAccessAlphaInstance.reset();
+            if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
+                aBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+            else if (!aBitmap.IsEmpty())
+                aBitmapEx = BitmapEx(aBitmap);
+            if (!aBitmapEx.IsEmpty() && !prefSize.IsEmpty())
+            {
+                aBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+                aBitmapEx.SetPrefSize(prefSize);
+            }
+            rImportOutput.moBitmap = aBitmapEx;
+        }
+        // Return true in this case, as we read the bitmap
+        return true;
+    }
+
     png_read_end(pPng, pInfo);
 
     if (!bUseExistingBitmap)

Reply via email to