Version in base suite: 1.6.48-1 Base version: libpng1.6_1.6.48-1 Target version: libpng1.6_1.6.48-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libp/libpng1.6/libpng1.6_1.6.48-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libp/libpng1.6/libpng1.6_1.6.48-1+deb13u1.dsc changelog | 13 ++ gbp.conf | 2 patches/CVE-2025-64505.patch | 41 +++++++++ patches/CVE-2025-64506.patch | 58 +++++++++++++ patches/CVE-2025-64720.patch | 104 +++++++++++++++++++++++ patches/CVE-2025-65018-part1.patch | 60 +++++++++++++ patches/CVE-2025-65018-part2.patch | 163 +++++++++++++++++++++++++++++++++++++ patches/CVE-2025-66293-part1.patch | 61 +++++++++++++ patches/CVE-2025-66293-part2.patch | 123 +++++++++++++++++++++++++++ patches/series | 7 + salsa-ci.yml | 6 + 11 files changed, 637 insertions(+), 1 deletion(-) diff -Nru libpng1.6-1.6.48/debian/changelog libpng1.6-1.6.48/debian/changelog --- libpng1.6-1.6.48/debian/changelog 2025-05-05 19:11:18.000000000 +0000 +++ libpng1.6-1.6.48/debian/changelog 2025-12-06 10:10:16.000000000 +0000 @@ -1,3 +1,16 @@ +libpng1.6 (1.6.48-1+deb13u1) trixie-security; urgency=high + + * Security upload targeting trixie. + * Backport fixes for: + - CVE-2025-64505 - Heap buffer over-read (Closes: #1121219) + - CVE-2025-64506 - Heap buffer over-read (Closes: #1121218) + - CVE-2025-64720 - Heap buffer overflow (Closes: #1121217) + - CVE-2025-65018 - Heap buffer overflow (Closes: #1121216) + - CVE-2025-66293 - Out-of-bounds read (Closes: #1121877) + * Set gbp.conf for trixie and enable salsa CI + + -- Tobias Frost Sat, 06 Dec 2025 11:10:16 +0100 + libpng1.6 (1.6.48-1) unstable; urgency=medium * New upstream version 1.6.48 diff -Nru libpng1.6-1.6.48/debian/gbp.conf libpng1.6-1.6.48/debian/gbp.conf --- libpng1.6-1.6.48/debian/gbp.conf 2024-12-10 21:43:32.000000000 +0000 +++ libpng1.6-1.6.48/debian/gbp.conf 2025-12-06 10:10:16.000000000 +0000 @@ -1,5 +1,5 @@ [DEFAULT] upstream-branch=upstream -debian-branch=master +debian-branch=debian/trixie pristine-tar = True sign-tags = True diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-64505.patch libpng1.6-1.6.48/debian/patches/CVE-2025-64505.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-64505.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-64505.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,41 @@ +Description: CVE-2025-64505 - Heap buffer over-read in `png_do_quantize` +Origin: https://github.com/pnggroup/libpng/commit/6a528eb5fd0dd7f6de1c39d30de0e41473431c37 +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-4952-h5wq-4m42 +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121219 + +From 6a528eb5fd0dd7f6de1c39d30de0e41473431c37 Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Sat, 8 Nov 2025 23:58:26 +0200 +Subject: [PATCH] Fix a buffer overflow in `png_do_quantize` + +Allocate the quantize_index array to PNG_MAX_PALETTE_LENGTH (256 bytes) +instead of num_palette bytes. This approach matches the allocation +pattern for `palette[]`, `trans_alpha[]` and `riffled_palette[]` which +were similarly oversized in libpng 1.2.1 to prevent buffer overflows +from malformed PNG files with out-of-range palette indices. + +Out-of-range palette indices `index >= num_palette` will now read +identity-mapped values from the `quantize_index` array (where index N +maps to palette entry N). This prevents undefined behavior while +avoiding runtime bounds checking overhead in the performance-critical +pixel processing loop. + +Reported-by: Samsung-PENTEST +Analyzed-by: degrigis +--- + pngrtran.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/pngrtran.c ++++ b/pngrtran.c +@@ -496,8 +496,8 @@ + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, +- (png_alloc_size_t)num_palette); +- for (i = 0; i < num_palette; i++) ++ PNG_MAX_PALETTE_LENGTH); ++ for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-64506.patch libpng1.6-1.6.48/debian/patches/CVE-2025-64506.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-64506.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-64506.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,58 @@ +Description: CVE-2025-64506 - Heap buffer over-read in png_write_image_8bit +Origin: https://github.com/pnggroup/libpng/commit/2bd84c019c300b78e811743fbcddb67c9d9bf821 +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-qpr4-xm66-hww6 +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121218 + +From 2bd84c019c300b78e811743fbcddb67c9d9bf821 Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Fri, 7 Nov 2025 22:40:05 +0200 +Subject: [PATCH] Fix a heap buffer overflow in `png_write_image_8bit` + +The condition guarding the pre-transform path incorrectly allowed 8-bit +input data to enter `png_write_image_8bit` which expects 16-bit input. +This caused out-of-bounds reads when processing 8-bit grayscale+alpha +images (GitHub #688), or 8-bit RGB or RGB+alpha images (GitHub #746), +with the `convert_to_8bit` flag set (an invalid combination that should +bypass the pre-transform path). + +The second part of the condition, i.e. + + colormap == 0 && convert_to_8bit != 0 + +failed to verify that input was 16-bit, i.e. + + linear != 0 + +contradicting the comment "This only applies when the input is 16-bit". + +The fix consists in restructuring the condition to ensure both the +`alpha` path and the `convert_to_8bit` path require linear (16-bit) +input. The corrected condition, i.e. + + linear != 0 && (alpha != 0 || display->convert_to_8bit != 0) + +matches the expectation of the `png_write_image_8bit` function and +prevents treating 8-bit buffers as 16-bit data. + +Reported-by: Samsung-PENTEST +Reported-by: weijinjinnihao +Analyzed-by: degrigis +Reviewed-by: John Bowler +--- + pngwrite.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/pngwrite.c b/pngwrite.c +index 35a5d17b60..83148960ef 100644 +--- a/pngwrite.c ++++ b/pngwrite.c +@@ -2173,8 +2173,7 @@ png_image_write_main(png_voidp argument) + * before it is written. This only applies when the input is 16-bit and + * either there is an alpha channel or it is converted to 8-bit. + */ +- if ((linear != 0 && alpha != 0 ) || +- (colormap == 0 && display->convert_to_8bit != 0)) ++ if (linear != 0 && (alpha != 0 || display->convert_to_8bit != 0)) + { + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-64720.patch libpng1.6-1.6.48/debian/patches/CVE-2025-64720.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-64720.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-64720.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,104 @@ +Description: CVE-2025-64720 - Buffer overflow in `png_image_read_composite` +Origin: https://github.com/pnggroup/libpng/commit/08da33b4c88cfcd36e5a706558a8d7e0e4773643 +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-hfc7-ph9c-wcww +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121217 + +From 08da33b4c88cfcd36e5a706558a8d7e0e4773643 Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Wed, 12 Nov 2025 13:46:23 +0200 +Subject: [PATCH] Fix a buffer overflow in `png_init_read_transformations` + +The palette compositing code in `png_init_read_transformations` was +incorrectly applying background compositing when PNG_FLAG_OPTIMIZE_ALPHA +was set. This violated the premultiplied alpha invariant +`component <= alpha` expected by `png_image_read_composite`, causing +values that exceeded the valid range for the PNG_sRGB_FROM_LINEAR lookup +tables. + +When PNG_ALPHA_OPTIMIZED is active, palette entries should contain pure +premultiplied RGB values without background compositing. The background +compositing must happen later in `png_image_read_composite` where the +actual background color from the PNG file is available. + +The fix consists in introducing conditional behavior based on +PNG_FLAG_OPTIMIZE_ALPHA: when set, the code performs only +premultiplication using the formula `component * alpha + 127) / 255` +with proper gamma correction. When not set, the original background +compositing calculation based on the `png_composite` macro is preserved. + +This prevents buffer overflows in `png_image_read_composite` where +out-of-range premultiplied values would cause out-of-bounds array access +in `png_sRGB_base[]` and `png_sRGB_delta[]`. + +Reported-by: Samsung-PENTEST +Analyzed-by: John Bowler +--- + pngrtran.c | 58 ++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 45 insertions(+), 13 deletions(-) + +--- a/pngrtran.c ++++ b/pngrtran.c +@@ -1768,19 +1768,51 @@ + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { +- png_byte v, w; ++ if ((png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0) ++ { ++ /* Premultiply only: ++ * component = round((component * alpha) / 255) ++ */ ++ png_uint_32 component; + +- v = png_ptr->gamma_to_1[palette[i].red]; +- png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); +- palette[i].red = png_ptr->gamma_from_1[w]; +- +- v = png_ptr->gamma_to_1[palette[i].green]; +- png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); +- palette[i].green = png_ptr->gamma_from_1[w]; +- +- v = png_ptr->gamma_to_1[palette[i].blue]; +- png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); +- palette[i].blue = png_ptr->gamma_from_1[w]; ++ component = png_ptr->gamma_to_1[palette[i].red]; ++ component = ++ (component * png_ptr->trans_alpha[i] + 128) / 255; ++ palette[i].red = png_ptr->gamma_from_1[component]; ++ ++ component = png_ptr->gamma_to_1[palette[i].green]; ++ component = ++ (component * png_ptr->trans_alpha[i] + 128) / 255; ++ palette[i].green = png_ptr->gamma_from_1[component]; ++ ++ component = png_ptr->gamma_to_1[palette[i].blue]; ++ component = ++ (component * png_ptr->trans_alpha[i] + 128) / 255; ++ palette[i].blue = png_ptr->gamma_from_1[component]; ++ } ++ else ++ { ++ /* Composite with background color: ++ * component = ++ * alpha * component + (1 - alpha) * background ++ */ ++ png_byte v, w; ++ ++ v = png_ptr->gamma_to_1[palette[i].red]; ++ png_composite(w, v, ++ png_ptr->trans_alpha[i], back_1.red); ++ palette[i].red = png_ptr->gamma_from_1[w]; ++ ++ v = png_ptr->gamma_to_1[palette[i].green]; ++ png_composite(w, v, ++ png_ptr->trans_alpha[i], back_1.green); ++ palette[i].green = png_ptr->gamma_from_1[w]; ++ ++ v = png_ptr->gamma_to_1[palette[i].blue]; ++ png_composite(w, v, ++ png_ptr->trans_alpha[i], back_1.blue); ++ palette[i].blue = png_ptr->gamma_from_1[w]; ++ } + } + } + else diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part1.patch libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part1.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part1.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,60 @@ +Description: CVE-2025-65018 - part 1 - Heap buffer overflow + in `png_combine_row` triggered via `png_image_finish_read` +Origin: https://github.com/pnggroup/libpng/commit/16b5e3823918840aae65c0a6da57c78a5a496a4d +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-7wv6-48j4-hj3g +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121216 + +From 16b5e3823918840aae65c0a6da57c78a5a496a4d Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Mon, 17 Nov 2025 20:38:47 +0200 +Subject: [PATCH] Fix a buffer overflow in `png_image_finish_read` +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reject bit-depth mismatches between IHDR and the requested output +format. When a 16-bit PNG is processed with an 8-bit output format +request, `png_combine_row` writes using the IHDR depth before +transformation, causing writes beyond the buffer allocated via +`PNG_IMAGE_SIZE(image)`. + +The validation establishes a safe API contract where +`PNG_IMAGE_SIZE(image)` is guaranteed to be sufficient across the +transformation pipeline. + +Example overflow (32×32 pixels, 16-bit RGB to 8-bit RGBA): +- Input format: 16 bits/channel × 3 channels = 6144 bytes +- Output buffer: 8 bits/channel × 4 channels = 4096 bytes +- Overflow: 6144 bytes - 4096 bytes = 2048 bytes + +Larger images produce proportionally larger overflows. For example, +for 256×256 pixels, the overflow is 131072 bytes. + +Reported-by: yosiimich +--- + pngread.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/pngread.c ++++ b/pngread.c +@@ -4034,6 +4034,20 @@ + int result; + png_image_read_control display; + ++ /* Reject bit depth mismatches to avoid buffer overflows. */ ++ png_uint_32 ihdr_bit_depth = ++ image->opaque->png_ptr->bit_depth; ++ int requested_linear = ++ (image->format & PNG_FORMAT_FLAG_LINEAR) != 0; ++ if (ihdr_bit_depth == 16 && !requested_linear) ++ return png_image_error(image, ++ "png_image_finish_read: " ++ "16-bit PNG must use 16-bit output format"); ++ if (ihdr_bit_depth < 16 && requested_linear) ++ return png_image_error(image, ++ "png_image_finish_read: " ++ "8-bit PNG must not use 16-bit output format"); ++ + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part2.patch libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part2.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-65018-part2.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,163 @@ +Description: CVE-2025-65018 - part 2 - Heap buffer overflow + in `png_combine_row` triggered via `png_image_finish_read` +Origin: https://github.com/pnggroup/libpng/commit/218612ddd6b17944e21eda56caf8b4bf7779d1ea +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-7wv6-48j4-hj3g +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121216 + +From 218612ddd6b17944e21eda56caf8b4bf7779d1ea Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Wed, 19 Nov 2025 21:45:13 +0200 +Subject: [PATCH] Rearchitect the fix to the buffer overflow in + `png_image_finish_read` + +Undo the fix from commit 16b5e3823918840aae65c0a6da57c78a5a496a4d. +That fix turned out to be unnecessarily limiting. It rejected all +16-to-8 bit transformations, although the vulnerability only affects +interlaced PNGs where `png_combine_row` writes using IHDR bit-depth +before the transformation completes. + +The proper solution is to add an intermediate `local_row` buffer, +specifically for the slow but necessary step of 16-to-8 bit conversion +of interlaced images. (The processing of non-interlaced images remains +intact, using the fast path.) We added the flag `do_local_scale` and +the function `png_image_read_direct_scaled`, following the pattern that +involves `do_local_compose`. + +In conclusion: +- The 16-to-8 bit transformations of interlaced images are now safe, + as they use an intermediate buffer. +- The 16-to-8 bit transformations of non-interlaced images remain safe, + as the fast path remains unchanged. +- All our regression tests are now passing. +--- + pngread.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 75 insertions(+), 14 deletions(-) + +--- a/pngread.c ++++ b/pngread.c +@@ -3123,6 +3123,54 @@ + } + } + ++/* Row reading for interlaced 16-to-8 bit depth conversion with local buffer. */ ++static int ++png_image_read_direct_scaled(png_voidp argument) ++{ ++ png_image_read_control *display = png_voidcast(png_image_read_control*, ++ argument); ++ png_imagep image = display->image; ++ png_structrp png_ptr = image->opaque->png_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; ++ int passes; ++ ++ /* Handle interlacing. */ ++ switch (png_ptr->interlaced) ++ { ++ case PNG_INTERLACE_NONE: ++ passes = 1; ++ break; ++ ++ case PNG_INTERLACE_ADAM7: ++ passes = PNG_INTERLACE_ADAM7_PASSES; ++ break; ++ ++ default: ++ png_error(png_ptr, "unknown interlace type"); ++ } ++ ++ /* Read each pass using local_row as intermediate buffer. */ ++ while (--passes >= 0) ++ { ++ png_uint_32 y = image->height; ++ png_bytep output_row = first_row; ++ ++ for (; y > 0; --y) ++ { ++ /* Read into local_row (gets transformed 8-bit data). */ ++ png_read_row(png_ptr, local_row, NULL); ++ ++ /* Copy from local_row to user buffer. */ ++ memcpy(output_row, local_row, (size_t)row_bytes); ++ output_row += row_bytes; ++ } ++ } ++ ++ return 1; ++} ++ + /* Just the row reading part of png_image_read. */ + static int + png_image_read_composite(png_voidp argument) +@@ -3541,6 +3589,7 @@ + int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; + int do_local_compose = 0; + int do_local_background = 0; /* to avoid double gamma correction bug */ ++ int do_local_scale = 0; /* for interlaced 16-to-8 bit conversion */ + int passes = 0; + + /* Add transforms to ensure the correct output format is produced then check +@@ -3674,8 +3723,16 @@ + png_set_expand_16(png_ptr); + + else /* 8-bit output */ ++ { + png_set_scale_16(png_ptr); + ++ /* For interlaced images, use local_row buffer to avoid overflow ++ * in png_combine_row() which writes using IHDR bit-depth. ++ */ ++ if (png_ptr->interlaced != 0) ++ do_local_scale = 1; ++ } ++ + change &= ~PNG_FORMAT_FLAG_LINEAR; + } + +@@ -3951,6 +4008,24 @@ + return result; + } + ++ else if (do_local_scale != 0) ++ { ++ /* For interlaced 16-to-8 conversion, use an intermediate row buffer ++ * to avoid buffer overflows in png_combine_row. The local_row is sized ++ * for the transformed (8-bit) output, preventing the overflow that would ++ * occur if png_combine_row wrote 16-bit data directly to the user buffer. ++ */ ++ int result; ++ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); ++ ++ display->local_row = row; ++ result = png_safe_execute(image, png_image_read_direct_scaled, display); ++ display->local_row = NULL; ++ png_free(png_ptr, row); ++ ++ return result; ++ } ++ + else + { + png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; +@@ -4034,20 +4109,6 @@ + int result; + png_image_read_control display; + +- /* Reject bit depth mismatches to avoid buffer overflows. */ +- png_uint_32 ihdr_bit_depth = +- image->opaque->png_ptr->bit_depth; +- int requested_linear = +- (image->format & PNG_FORMAT_FLAG_LINEAR) != 0; +- if (ihdr_bit_depth == 16 && !requested_linear) +- return png_image_error(image, +- "png_image_finish_read: " +- "16-bit PNG must use 16-bit output format"); +- if (ihdr_bit_depth < 16 && requested_linear) +- return png_image_error(image, +- "png_image_finish_read: " +- "8-bit PNG must not use 16-bit output format"); +- + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part1.patch libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part1.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part1.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,61 @@ +Description: CVE-2025-66293 - out-of-bounds read in png_image_read_composite part 1 +Origin: https://github.com/pnggroup/libpng/commit/788a624d7387a758ffd5c7ab010f1870dea753a1 +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-9mpm-9pxh-mg4f +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121877 + +From 788a624d7387a758ffd5c7ab010f1870dea753a1 Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Sat, 29 Nov 2025 00:39:16 +0200 +Subject: [PATCH] Fix an out-of-bounds read in `png_image_read_composite` + +Add a defensive bounds check before calling PNG_sRGB_FROM_LINEAR to +prevent reading up to 506 entries (1012 bytes) past `png_sRGB_base[]`. + +For palette images with gamma, `png_init_read_transformations` +clears PNG_COMPOSE after compositing on the palette, but it leaves +PNG_FLAG_OPTIMIZE_ALPHA set. The simplified API then calls +`png_image_read_composite` with sRGB data (not linear premultiplied), +causing the index to reach 1017. (The maximum valid index is 511.) + +NOTE: +This is a defensive fix that addresses the security issue (out-of-bounds +read) but *NOT* the correctness issue (wrong output). When the clamp +triggers, the affected pixels are clamped to white instead of the +correct composited color. Valid PNG images may render incorrectly with +the simplified API. + +TODO: +We already know the root cause is a flag synchronization error. +For palette images with gamma, `png_init_read_transformations` +clears PNG_COMPOSE but leaves PNG_FLAG_OPTIMIZE_ALPHA set, causing +`png_image_read_composite` to misinterpret sRGB data as linear +premultiplied. However, we have yet to implement an architectural fix +that requires coordinating the simplified API with the transformation +pipeline. + +Reported-by: flyfish101 +--- + pngread.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/pngread.c b/pngread.c +index 79917daaaf..ab62edd9d8 100644 +--- a/pngread.c ++++ b/pngread.c +@@ -3273,9 +3273,14 @@ png_image_read_composite(png_voidp argument) + component += (255-alpha)*png_sRGB_table[outrow[c]]; + + /* So 'component' is scaled by 255*65535 and is +- * therefore appropriate for the sRGB to linear +- * conversion table. ++ * therefore appropriate for the sRGB-to-linear ++ * conversion table. Clamp to the valid range ++ * as a defensive measure against an internal ++ * libpng bug where the data is sRGB rather than ++ * linear premultiplied. + */ ++ if (component > 255*65535) ++ component = 255*65535; + component = PNG_sRGB_FROM_LINEAR(component); + } + diff -Nru libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part2.patch libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part2.patch --- libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/CVE-2025-66293-part2.patch 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,123 @@ +Description: CVE-2025-66293 - out-of-bounds read in png_image_read_composite part 2 +Origin: https://github.com/pnggroup/libpng/commit/a05a48b756de63e3234ea6b3b938b8f5f862484a +Bug: https://github.com/pnggroup/libpng/security/advisories/GHSA-9mpm-9pxh-mg4f +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121877 + +From a05a48b756de63e3234ea6b3b938b8f5f862484a Mon Sep 17 00:00:00 2001 +From: Cosmin Truta +Date: Mon, 1 Dec 2025 22:31:54 +0200 +Subject: [PATCH] Finalize the fix for out-of-bounds read in + `png_image_read_composite` + +Following up on commit 788a624d7387a758ffd5c7ab010f1870dea753a1. + +The previous commit added a defensive bounds check to address the +security issue (out-of-bounds read), but noted that the correctness +issue remained: when the clamp triggered, the affected pixels were +clamped to white instead of the correct composited color. + +This commit addresses the correctness issue by fixing the flag +synchronization error identified in the previous commit's TODO: + +1. In `png_init_read_transformations`: + Clear PNG_FLAG_OPTIMIZE_ALPHA when clearing PNG_COMPOSE for palette + images. This correctly signals that the data is sRGB, not linear + premultiplied. + +2. In `png_image_read_composite`: + Check PNG_FLAG_OPTIMIZE_ALPHA and use the appropriate composition + formula. When set, use the existing linear composition. When cleared + (palette composition already done), use sRGB composition to match + what was done to the palette. + +Retain the previous clamp to the valid range as belt-and-suspenders +protection against any other unforeseen cases. +--- + pngread.c | 58 ++++++++++++++++++++++++++++++++++++------------------ + pngrtran.c | 1 + + 2 files changed, 40 insertions(+), 19 deletions(-) + +--- a/pngread.c ++++ b/pngread.c +@@ -3201,6 +3201,7 @@ + ptrdiff_t step_row = display->row_bytes; + unsigned int channels = + (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; ++ int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; + int pass; + + for (pass = 0; pass < passes; ++pass) +@@ -3257,25 +3258,44 @@ + + if (alpha < 255) /* else just use component */ + { +- /* This is PNG_OPTIMIZED_ALPHA, the component value +- * is a linear 8-bit value. Combine this with the +- * current outrow[c] value which is sRGB encoded. +- * Arithmetic here is 16-bits to preserve the output +- * values correctly. +- */ +- component *= 257*255; /* =65535 */ +- component += (255-alpha)*png_sRGB_table[outrow[c]]; +- +- /* So 'component' is scaled by 255*65535 and is +- * therefore appropriate for the sRGB-to-linear +- * conversion table. Clamp to the valid range +- * as a defensive measure against an internal +- * libpng bug where the data is sRGB rather than +- * linear premultiplied. +- */ +- if (component > 255*65535) +- component = 255*65535; +- component = PNG_sRGB_FROM_LINEAR(component); ++ if (optimize_alpha != 0) ++ { ++ /* This is PNG_OPTIMIZED_ALPHA, the component value ++ * is a linear 8-bit value. Combine this with the ++ * current outrow[c] value which is sRGB encoded. ++ * Arithmetic here is 16-bits to preserve the output ++ * values correctly. ++ */ ++ component *= 257*255; /* =65535 */ ++ component += (255-alpha)*png_sRGB_table[outrow[c]]; ++ ++ /* Clamp to the valid range to defend against ++ * unforeseen cases where the data might be sRGB ++ * instead of linear premultiplied. ++ * (Belt-and-suspenders for GitHub Issue #764.) ++ */ ++ if (component > 255*65535) ++ component = 255*65535; ++ ++ /* So 'component' is scaled by 255*65535 and is ++ * therefore appropriate for the sRGB-to-linear ++ * conversion table. ++ */ ++ component = PNG_sRGB_FROM_LINEAR(component); ++ } ++ else ++ { ++ /* Compositing was already done on the palette ++ * entries. The data is sRGB premultiplied on black. ++ * Composite with the background in sRGB space. ++ * This is not gamma-correct, but matches what was ++ * done to the palette. ++ */ ++ png_uint_32 background = outrow[c]; ++ component += ((255-alpha) * background + 127) / 255; ++ if (component > 255) ++ component = 255; ++ } + } + + outrow[c] = (png_byte)component; +--- a/pngrtran.c ++++ b/pngrtran.c +@@ -1830,6 +1830,7 @@ + * transformations elsewhere. + */ + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); ++ png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } /* color_type == PNG_COLOR_TYPE_PALETTE */ + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ diff -Nru libpng1.6-1.6.48/debian/patches/series libpng1.6-1.6.48/debian/patches/series --- libpng1.6-1.6.48/debian/patches/series 2024-12-10 21:43:32.000000000 +0000 +++ libpng1.6-1.6.48/debian/patches/series 2025-12-06 10:10:16.000000000 +0000 @@ -1,2 +1,9 @@ libpng-config.patch #libpng-1.6.39-apng.patch +CVE-2025-64505.patch +CVE-2025-64506.patch +CVE-2025-64720.patch +CVE-2025-65018-part1.patch +CVE-2025-65018-part2.patch +CVE-2025-66293-part1.patch +CVE-2025-66293-part2.patch diff -Nru libpng1.6-1.6.48/debian/salsa-ci.yml libpng1.6-1.6.48/debian/salsa-ci.yml --- libpng1.6-1.6.48/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ libpng1.6-1.6.48/debian/salsa-ci.yml 2025-12-06 10:10:16.000000000 +0000 @@ -0,0 +1,6 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml + +variables: + RELEASE: 'trixie'