vcl/source/filter/png/PngImageReader.cxx |   60 ++++++++++++++++++++++++-------
 1 file changed, 47 insertions(+), 13 deletions(-)

New commits:
commit da4de084d20116f0ae49b43cd454188fde2ddac9
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Mar 5 19:38:07 2021 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Fri Mar 12 15:35:16 2021 +0100

    make PngImageReader return partially broken images
    
    This makes it consistent with PNGReader, which is capable of reading
    in e.g. the invalid-chunk.png test file.
    
    Change-Id: Ia3b5553e588ac5778fad6de5bc284d5822febbda
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112038
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/source/filter/png/PngImageReader.cxx 
b/vcl/source/filter/png/PngImageReader.cxx
index be94f99b04d2..ad778bce6aba 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -33,7 +33,11 @@ void lclReadStream(png_structp pPng, png_bytep pOutBytes, 
png_size_t nBytesToRea
     sal_Size nBytesRead = pStream->ReadBytes(pOutBytes, nBytesToRead);
 
     if (nBytesRead != nBytesToRead)
-        png_error(pPng, "Error reading");
+    {
+        // Make sure to not reuse old data (could cause infinite loop).
+        memset(pOutBytes + nBytesRead, 0, nBytesToRead - nBytesRead);
+        png_warning(pPng, "Error reading");
+    }
 }
 
 bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
@@ -61,9 +65,32 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
         return false;
     }
 
+    // All variables holding resources need to be declared here in order to be
+    // properly cleaned up in case of an error, otherwise libpng's longjmp()
+    // jumps over the destructor calls.
+    Bitmap aBitmap;
+    AlphaMask aBitmapAlpha;
+    Size prefSize;
+    BitmapScopedWriteAccess pWriteAccess;
+    AlphaScopedWriteAccess pWriteAccessAlpha;
+    std::vector<std::vector<png_byte>> aRows;
+
     if (setjmp(png_jmpbuf(pPng)))
     {
         png_destroy_read_struct(&pPng, &pInfo, nullptr);
+        // Set the bitmap if it contains something, even on failure. This 
allows
+        // reading images that are only partially broken.
+        pWriteAccess.reset();
+        pWriteAccessAlpha.reset();
+        if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
+            rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+        else if (!aBitmap.IsEmpty())
+            rBitmapEx = BitmapEx(aBitmap);
+        if (!rBitmapEx.IsEmpty() && !prefSize.IsEmpty())
+        {
+            rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+            rBitmapEx.SetPrefSize(prefSize);
+        }
         return false;
     }
 
@@ -133,7 +160,6 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
         return false;
     }
 
-    Size prefSize;
     png_uint_32 res_x = 0;
     png_uint_32 res_y = 0;
     int unit_type = 0;
@@ -150,14 +176,15 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
         {
             size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
 
-            Bitmap aBitmap(Size(width, height), 24);
+            aBitmap = Bitmap(Size(width, height), 24);
+            aBitmap.Erase(COL_WHITE);
             {
-                BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                pWriteAccess = BitmapScopedWriteAccess(aBitmap);
                 ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
                 if (eFormat == ScanlineFormat::N24BitTcBgr)
                     png_set_bgr(pPng);
 
-                std::vector<std::vector<png_byte>> aRows(height);
+                aRows = std::vector<std::vector<png_byte>>(height);
                 for (auto& rRow : aRows)
                     rRow.resize(aRowSizeBytes, 0);
 
@@ -177,6 +204,7 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
                         }
                     }
                 }
+                pWriteAccess.reset();
             }
             rBitmapEx = BitmapEx(aBitmap);
         }
@@ -186,9 +214,10 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
 
             if (bUseBitmap32)
             {
-                Bitmap aBitmap(Size(width, height), 32);
+                aBitmap = Bitmap(Size(width, height), 32);
+                aBitmap.Erase(COL_WHITE);
                 {
-                    BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                    pWriteAccess = BitmapScopedWriteAccess(aBitmap);
                     ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
                     if (eFormat == ScanlineFormat::N32BitTcAbgr
                         || eFormat == ScanlineFormat::N32BitTcBgra)
@@ -196,7 +225,7 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
                         png_set_bgr(pPng);
                     }
 
-                    std::vector<std::vector<png_byte>> aRows(height);
+                    aRows = std::vector<std::vector<png_byte>>(height);
                     for (auto& rRow : aRows)
                         rRow.resize(aRowSizeBytes, 0);
 
@@ -227,22 +256,25 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
                             }
                         }
                     }
+                    pWriteAccess.reset();
                 }
                 rBitmapEx = BitmapEx(aBitmap);
             }
             else
             {
-                Bitmap aBitmap(Size(width, height), 24);
-                AlphaMask aBitmapAlpha(Size(width, height), nullptr);
+                aBitmap = Bitmap(Size(width, height), 24);
+                aBitmapAlpha = AlphaMask(Size(width, height), nullptr);
+                aBitmap.Erase(COL_WHITE);
+                aBitmapAlpha.Erase(0xff); // transparent
                 {
-                    BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                    pWriteAccess = BitmapScopedWriteAccess(aBitmap);
                     ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
                     if (eFormat == ScanlineFormat::N24BitTcBgr)
                         png_set_bgr(pPng);
 
-                    AlphaScopedWriteAccess pWriteAccessAlpha(aBitmapAlpha);
+                    pWriteAccessAlpha = AlphaScopedWriteAccess(aBitmapAlpha);
 
-                    std::vector<std::vector<png_byte>> aRows(height);
+                    aRows = std::vector<std::vector<png_byte>>(height);
                     for (auto& rRow : aRows)
                         rRow.resize(aRowSizeBytes, 0);
 
@@ -265,6 +297,8 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool 
bUseBitmap32)
                             }
                         }
                     }
+                    pWriteAccess.reset();
+                    pWriteAccessAlpha.reset();
                 }
                 rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
             }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to