vcl/source/filter/png/PngImageReader.cxx |   42 ++++++++-----------------------
 1 file changed, 12 insertions(+), 30 deletions(-)

New commits:
commit 329465f19d7800c87f641565cd7e5a69f0a63d47
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Sep 11 09:34:44 2025 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Sep 11 16:03:13 2025 +0200

    ofz#438873386 pngfuzzer Out-of-memory
    
    we can skip the intermediate buffer now and use
    the bitmap data itself as the buffer.
    
    Change-Id: Ifea467ca16ffb5a6f5b1b88dfb08f9a0426168f9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190797
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/vcl/source/filter/png/PngImageReader.cxx 
b/vcl/source/filter/png/PngImageReader.cxx
index f89e3cc6db12..b0312c72610a 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -515,44 +515,26 @@ bool reader(SvStream& rStream, ImportOutput& 
rImportOutput,
         {
             size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
 
-            if (nNumberOfPasses == 1)
+            // Reuse the bitmap data as a buffer for reading the png data. The
+            // order is possibly incorrect from what it should finally be and
+            // in any case the result is not premultiplied.
+            for (int pass = 0; pass < nNumberOfPasses; pass++)
             {
-                // optimise the common case, where we can use a buffer of only 
a single row
-                std::vector<png_byte> aRow(aRowSizeBytes, 0);
                 for (png_uint_32 y = 0; y < height; y++)
                 {
                     Scanline pScanline = pWriteAccess->GetScanline(y);
-                    png_bytep pRow = aRow.data();
-                    png_read_row(pPng, pRow, nullptr);
-                    for (size_t i = 0; i < aRowSizeBytes; i += 4)
-                    {
-                        Color aCol(ColorAlpha, pRow[i + 3], pRow[i + 0], 
pRow[i + 1], pRow[i + 2]);
-                        pWriteAccess->SetPixelOnData(pScanline, i / 4, aCol);
-                    }
+                    png_read_row(pPng, pScanline, nullptr);
                 }
             }
-            else
+            // Fix order and do premultiplication
+            for (png_uint_32 y = 0; y < height; y++)
             {
-                std::vector<std::vector<png_byte>> aRows(height);
-                for (auto& rRow : aRows)
-                    rRow.resize(aRowSizeBytes, 0);
-                for (int pass = 0; pass < nNumberOfPasses; pass++)
-                {
-                    for (png_uint_32 y = 0; y < height; y++)
-                    {
-                        png_bytep pRow = aRows[y].data();
-                        png_read_row(pPng, pRow, nullptr);
-                    }
-                }
-                for (png_uint_32 y = 0; y < height; y++)
+                Scanline pScanline = pWriteAccess->GetScanline(y);
+                for (size_t i = 0; i < aRowSizeBytes; i += 4)
                 {
-                    Scanline pScanline = pWriteAccess->GetScanline(y);
-                    png_bytep pRow = aRows[y].data();
-                    for (size_t i = 0; i < aRowSizeBytes; i += 4)
-                    {
-                        Color aCol(ColorAlpha, pRow[i + 3], pRow[i + 0], 
pRow[i + 1], pRow[i + 2]);
-                        pWriteAccess->SetPixelOnData(pScanline, i / 4, aCol);
-                    }
+                    Color aCol(ColorAlpha, pScanline[i + 3], pScanline[i + 0], 
pScanline[i + 1],
+                               pScanline[i + 2]);
+                    pWriteAccess->SetPixelOnData(pScanline, i / 4, aCol);
                 }
             }
         }

Reply via email to