File libpng16-CVE-2026-22695.patch of Package libpng16.42239

From e4f7ad4ea2a471776c81dda4846b7691925d9786 Mon Sep 17 00:00:00 2001
From: Cosmin Truta <ctruta@gmail.com>
Date: Fri, 9 Jan 2026 20:51:53 +0200
Subject: [PATCH] Fix a heap buffer over-read in `png_image_read_direct_scaled`

Fix a regression from commit 218612ddd6b17944e21eda56caf8b4bf7779d1ea.

The function `png_image_read_direct_scaled`, introduced by the fix for
CVE-2025-65018, copies transformed row data from an intermediate buffer
(`local_row`) to the user's output buffer. The copy incorrectly used
`row_bytes` (the caller's stride) as the size parameter to memcpy, even
though `local_row` is only `png_get_rowbytes()` bytes long.

This causes a heap buffer over-read when:

1. The caller provides a padded stride (e.g., for memory alignment):
   memcpy reads past the end of `local_row` by `stride - row_width`
   bytes.

2. The caller provides a negative stride (for bottom-up layouts):
   casting ptrdiff_t to size_t produces ~2^64, causing memcpy to
   attempt reading exabytes, resulting in an immediate crash.

The fix consists in using the size of the row buffer for the copy and
using the stride for pointer advancement only.

Reported-by: Petr Simecek <simecek@users.noreply.github.com>
Analyzed-by: Stanislav Fort
Analyzed-by: Pavel Kohout
Co-authored-by: Petr Simecek <simecek@users.noreply.github.com>
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
---
 AUTHORS   | 1 +
 pngread.c | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

Index: libpng-1.6.40/AUTHORS
===================================================================
--- libpng-1.6.40.orig/AUTHORS
+++ libpng-1.6.40/AUTHORS
@@ -22,6 +22,7 @@ Authors, for copyright and licensing pur
  * Mike Klein
  * Pascal Massimino
  * Paul Schmidt
+ * Petr Simecek
  * Philippe Antoine
  * Qiang Zhou
  * Sam Bushell
Index: libpng-1.6.40/pngread.c
===================================================================
--- libpng-1.6.40.orig/pngread.c
+++ libpng-1.6.40/pngread.c
@@ -3268,9 +3268,11 @@ png_image_read_direct_scaled(png_voidp a
        argument);
    png_imagep image = display->image;
    png_structrp png_ptr = image->opaque->png_ptr;
+   png_inforp info_ptr = image->opaque->info_ptr;
    png_bytep local_row = png_voidcast(png_bytep, display->local_row);
    png_bytep first_row = png_voidcast(png_bytep, display->first_row);
    ptrdiff_t row_bytes = display->row_bytes;
+   size_t copy_bytes = png_get_rowbytes(png_ptr, info_ptr);
    int passes;
 
    /* Handle interlacing. */
@@ -3300,7 +3302,7 @@ png_image_read_direct_scaled(png_voidp a
          png_read_row(png_ptr, local_row, NULL);
 
          /* Copy from local_row to user buffer. */
-         memcpy(output_row, local_row, (size_t)row_bytes);
+         memcpy(output_row, local_row, copy_bytes);
          output_row += row_bytes;
       }
    }
openSUSE Build Service is sponsored by