File libpng16-CVE-2026-22801.patch of Package libpng16.42472

From cf155de014fc6c5cb199dd681dd5c8fb70429072 Mon Sep 17 00:00:00 2001
From: Cosmin Truta <ctruta@gmail.com>
Date: Sat, 10 Jan 2026 15:20:18 +0200
Subject: [PATCH] fix: Remove incorrect truncation casts from
 `png_write_image_*`

The type of the row stride (`display->row_bytes`) is ptrdiff_t. Casting
to png_uint_16 before division will truncate large strides, causing
incorrect pointer arithmetic for images exceeding 65535 bytes per row.
For bottom-up images (negative stride), the truncation also corrupts
the sign, advancing the row pointer forward instead of backward.

Remove the erroneous casts and let the compiler handle the pointer
arithmetic correctly. Also replace `sizeof (png_uint_16)` with 2.

Add regression test via `pngstest --stride-extra N` where N > 32767
triggers the affected code paths.

A NOTE ABOUT HISTORY:
The original code in libpng 1.5.6 (2011) had no such casts. They were
introduced in libpng 1.6.26 (2016), likely to silence compiler warnings
on 16-bit systems where the cast would be a no-op. On 32/64-bit systems
the cast truncates the strides above 65535 and corrupts the negative
strides.
---
Index: libpng-1.6.40/pngwrite.c
===================================================================
--- libpng-1.6.40.orig/pngwrite.c
+++ libpng-1.6.40/pngwrite.c
@@ -1636,7 +1636,7 @@ png_write_image_16bit(png_voidp argument
       }
 
       png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
-      input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
+      input_row += display->row_bytes / 2;
    }
 
    return 1;
@@ -1762,7 +1762,7 @@ png_write_image_8bit(png_voidp argument)
 
          png_write_row(png_ptr, png_voidcast(png_const_bytep,
              display->local_row));
-         input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
+         input_row += display->row_bytes / 2;
       } /* while y */
    }
 
@@ -1787,7 +1787,7 @@ png_write_image_8bit(png_voidp argument)
          }
 
          png_write_row(png_ptr, output_row);
-         input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
+         input_row += display->row_bytes / 2;
       }
    }
 
@@ -2106,7 +2106,7 @@ png_image_write_main(png_voidp argument)
       ptrdiff_t row_bytes = display->row_stride;
 
       if (linear != 0)
-         row_bytes *= (sizeof (png_uint_16));
+         row_bytes *= 2;
 
       if (row_bytes < 0)
          row += (image->height-1) * (-row_bytes);
openSUSE Build Service is sponsored by