Update bundled libpng to last upstream version 1.6.54

This commit is contained in:
ManoloFLTK 2026-01-20 18:01:12 +01:00
parent d30ca18664
commit 2f7d7adfcf
26 changed files with 1681 additions and 1266 deletions

View File

@ -23,12 +23,12 @@ The nanosvg library is not affected.
\section bundled-status Current status \section bundled-status Current status
\code \code
Current versions of bundled libraries (as of Sept 13, 2025): Current versions of bundled libraries (as of Jan 20, 2026):
Library Version/git commit Release date FLTK Version Library Version/git commit Release date FLTK Version
-------------------------------------------------------------------------- --------------------------------------------------------------------------
jpeg jpeg-9f 2024-01-14 1.4.0 jpeg jpeg-9f 2024-01-14 1.4.0
nanosvg 7aeda550a8 [1] 2023-12-02 1.4.0 nanosvg 7aeda550a8 [1] 2023-12-02 1.4.0
png libpng-1.6.50 2025-07-01 1.5.0 png libpng-1.6.54 2026-01-12 1.5.0
zlib zlib-1.3.1 2024-01-22 1.4.0 zlib zlib-1.3.1 2024-01-22 1.4.0
libdecor c4540b4a [2] 2025-08-15 1.5.0 libdecor c4540b4a [2] 2025-08-15 1.5.0
-------------------------------------------------------------------------- --------------------------------------------------------------------------

View File

@ -1,5 +1,5 @@
libpng 1.6.50 - July 1, 2025 libpng 1.6.54 - January 12, 2026
============================ ================================
This is a public release of libpng, intended for use in production code. This is a public release of libpng, intended for use in production code.
@ -7,15 +7,12 @@ This is a public release of libpng, intended for use in production code.
Files available for download Files available for download
---------------------------- ----------------------------
Source files with LF line endings (for Unix/Linux): Source files:
* libpng-1.6.50.tar.xz (LZMA-compressed, recommended) * libpng-1.6.54.tar.xz (LZMA-compressed, recommended)
* libpng-1.6.50.tar.gz (deflate-compressed) * libpng-1.6.54.tar.gz (deflate-compressed)
* lpng1654.7z (LZMA-compressed)
Source files with CRLF line endings (for Windows): * lpng1654.zip (deflate-compressed)
* lpng1650.7z (LZMA-compressed, recommended)
* lpng1650.zip (deflate-compressed)
Other information: Other information:
@ -25,19 +22,16 @@ Other information:
* TRADEMARK.md * TRADEMARK.md
Changes from version 1.6.49 to version 1.6.50 Changes from version 1.6.53 to version 1.6.54
--------------------------------------------- ---------------------------------------------
* Improved the detection of the RVV Extension on the RISC-V platform. * Fixed CVE-2026-22695 (medium severity):
(Contributed by Filip Wasil) Heap buffer over-read in `png_image_read_direct_scaled.
* Replaced inline ASM with C intrinsics in the RVV code. (Reported and fixed by Petr Simecek.)
(Contributed by Filip Wasil) * Fixed CVE-2026-22801 (medium severity):
* Fixed a decoder defect in which unknown chunks trailing IDAT, set Integer truncation causing heap buffer over-read in `png_image_write_*`.
to go through the unknown chunk handler, incorrectly triggered * Implemented various improvements in oss-fuzz.
out-of-place IEND errors. (Contributed by Philippe Antoine.)
(Contributed by John Bowler)
* Fixed the CMake file for cross-platform builds that require `libm`.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit Subscription is required; visit

View File

@ -6278,6 +6278,59 @@ Version 1.6.50 [July 1, 2025]
(Contributed by John Bowler) (Contributed by John Bowler)
Fixed the CMake file for cross-platform builds that require `libm`. Fixed the CMake file for cross-platform builds that require `libm`.
Version 1.6.51 [November 21, 2025]
Fixed CVE-2025-64505 (moderate severity):
Heap buffer overflow in `png_do_quantize` via malformed palette index.
(Reported by Samsung; analyzed by Fabio Gritti.)
Fixed CVE-2025-64506 (moderate severity):
Heap buffer over-read in `png_write_image_8bit` with 8-bit input and
`convert_to_8bit` enabled.
(Reported by Samsung and <weijinjinnihao@users.noreply.github.com>;
analyzed by Fabio Gritti.)
Fixed CVE-2025-64720 (high severity):
Buffer overflow in `png_image_read_composite` via incorrect palette
premultiplication.
(Reported by Samsung; analyzed by John Bowler.)
Fixed CVE-2025-65018 (high severity):
Heap buffer overflow in `png_combine_row` triggered via
`png_image_finish_read`.
(Reported by <yosiimich@users.noreply.github.com>.)
Fixed a memory leak in `png_set_quantize`.
(Reported by Samsung; analyzed by Fabio Gritti.)
Removed the experimental and incomplete ERROR_NUMBERS code.
(Contributed by Tobias Stoeckmann.)
Improved the RISC-V vector extension support; required RVV 1.0 or newer.
(Contributed by Filip Wasil.)
Added GitHub Actions workflows for automated testing.
Performed various refactorings and cleanups.
Version 1.6.52 [December 3, 2025]
Fixed CVE-2025-66293 (high severity):
Out-of-bounds read in `png_image_read_composite`.
(Reported by flyfish101 <flyfish101@users.noreply.github.com>.)
Fixed the Paeth filter handling in the RISC-V RVV implementation.
(Reported by Filip Wasil; fixed by Liang Junzhao.)
Improved the performance of the RISC-V RVV implementation.
(Contributed by Liang Junzhao.)
Added allocation failure fuzzing to oss-fuzz.
(Contributed by Philippe Antoine.)
Version 1.6.53 [December 5, 2025]
Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic.
(Contributed by Alexander Smorkalov.)
Fixed a build failure with CMake 4.1 or newer, on Windows, when using
Visual C++ without MASM installed.
Version 1.6.54 [January 12, 2026]
Fixed CVE-2026-22695 (medium severity):
Heap buffer over-read in `png_image_read_direct_scaled.
(Reported and fixed by Petr Simecek.)
Fixed CVE-2026-22801 (medium severity):
Integer truncation causing heap buffer over-read in `png_image_write_*`.
Implemented various improvements in oss-fuzz.
(Contributed by Philippe Antoine.)
Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement https://lists.sourceforge.net/lists/listinfo/png-mng-implement

View File

@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
PNG Reference Library License version 2 PNG Reference Library License version 2
--------------------------------------- ---------------------------------------
* Copyright (c) 1995-2025 The PNG Reference Library Authors. * Copyright (c) 1995-2026 The PNG Reference Library Authors.
* Copyright (c) 2018-2025 Cosmin Truta. * Copyright (c) 2018-2026 Cosmin Truta.
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* Copyright (c) 1996-1997 Andreas Dilger. * Copyright (c) 1996-1997 Andreas Dilger.
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.

View File

@ -1,4 +1,4 @@
README for libpng version 1.6.50 README for libpng version 1.6.54
================================ ================================
See the note about version numbers near the top of `png.h`. See the note about version numbers near the top of `png.h`.

View File

@ -48,7 +48,7 @@
void void
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + row_info->rowbytes;
@ -69,7 +69,7 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
void void
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + row_info->rowbytes;
@ -116,7 +116,7 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
void void
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + row_info->rowbytes;
@ -148,7 +148,7 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
void void
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
@ -216,7 +216,7 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
void void
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + row_info->rowbytes;
@ -285,7 +285,7 @@ paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
void void
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
@ -353,7 +353,7 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
void void
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row) png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + row_info->rowbytes;

View File

@ -9,9 +9,9 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on: Based on:
libpng version 1.6.36, December 2018, through 1.6.50 - July 2025 libpng version 1.6.36, December 2018, through 1.6.54 - January 2026
Updated and distributed by Cosmin Truta Updated and distributed by Cosmin Truta
Copyright (c) 2018-2025 Cosmin Truta Copyright (c) 2018-2026 Cosmin Truta
libpng versions 0.97, January 1998, through 1.6.35 - July 2018 libpng versions 0.97, January 1998, through 1.6.35 - July 2018
Updated and distributed by Glenn Randers-Pehrson Updated and distributed by Glenn Randers-Pehrson
@ -3355,19 +3355,6 @@ Here is an example of writing two private chunks, prVt and miNE:
/* Needed because miNE is not safe-to-copy */ /* Needed because miNE is not safe-to-copy */
png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS,
(png_bytep) "miNE", 1); (png_bytep) "miNE", 1);
# if PNG_LIBPNG_VER < 10600
/* Deal with unknown chunk location bug in 1.5.x and earlier */
png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR);
png_set_unknown_chunk_location(png, info, 1, PNG_AFTER_IDAT);
# endif
# if PNG_LIBPNG_VER < 10500
/* PNG_AFTER_IDAT writes two copies of the chunk prior to libpng-1.5.0,
* one before IDAT and another after IDAT, so don't use it; only use
* PNG_HAVE_IHDR location. This call resets the location previously
* set by assignment and png_set_unknown_chunk_location() for chunk 1.
*/
png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR);
# endif
#endif #endif
The high-level write interface The high-level write interface

View File

@ -1,6 +1,6 @@
.TH LIBPNG 3 "July 1, 2025" .TH LIBPNG 3 "January 12, 2026"
.SH NAME .SH NAME
libpng \- Portable Network Graphics (PNG) Reference Library 1.6.50 libpng \- Portable Network Graphics (PNG) Reference Library 1.6.54
.SH SYNOPSIS .SH SYNOPSIS
\fB#include <png.h>\fP \fB#include <png.h>\fP
@ -528,9 +528,9 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on: Based on:
libpng version 1.6.36, December 2018, through 1.6.50 - July 2025 libpng version 1.6.36, December 2018, through 1.6.54 - January 2026
Updated and distributed by Cosmin Truta Updated and distributed by Cosmin Truta
Copyright (c) 2018-2025 Cosmin Truta Copyright (c) 2018-2026 Cosmin Truta
libpng versions 0.97, January 1998, through 1.6.35 - July 2018 libpng versions 0.97, January 1998, through 1.6.35 - July 2018
Updated and distributed by Glenn Randers-Pehrson Updated and distributed by Glenn Randers-Pehrson
@ -3874,19 +3874,6 @@ Here is an example of writing two private chunks, prVt and miNE:
/* Needed because miNE is not safe-to-copy */ /* Needed because miNE is not safe-to-copy */
png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS,
(png_bytep) "miNE", 1); (png_bytep) "miNE", 1);
# if PNG_LIBPNG_VER < 10600
/* Deal with unknown chunk location bug in 1.5.x and earlier */
png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR);
png_set_unknown_chunk_location(png, info, 1, PNG_AFTER_IDAT);
# endif
# if PNG_LIBPNG_VER < 10500
/* PNG_AFTER_IDAT writes two copies of the chunk prior to libpng-1.5.0,
* one before IDAT and another after IDAT, so don't use it; only use
* PNG_HAVE_IHDR location. This call resets the location previously
* set by assignment and png_set_unknown_chunk_location() for chunk 1.
*/
png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR);
# endif
#endif #endif
.SS The high-level write interface .SS The high-level write interface

View File

@ -1,6 +1,6 @@
.TH LIBPNGPF 3 "July 1, 2025" .TH LIBPNGPF 3 "January 12, 2026"
.SH NAME .SH NAME
libpng \- Portable Network Graphics (PNG) Reference Library 1.6.50 libpng \- Portable Network Graphics (PNG) Reference Library 1.6.54
.SH SYNOPSIS .SH SYNOPSIS
\fB#include "pngpriv.h"\fP \fB#include "pngpriv.h"\fP

View File

@ -1,4 +1,4 @@
.TH PNG 5 "July 1, 2025" .TH PNG 5 "January 12, 2026"
.SH NAME .SH NAME
png \- Portable Network Graphics (PNG) format png \- Portable Network Graphics (PNG) format
@ -6,73 +6,76 @@ png \- Portable Network Graphics (PNG) format
PNG (Portable Network Graphics) is an extensible file format for the PNG (Portable Network Graphics) is an extensible file format for the
lossless, portable, well-compressed storage of raster images. PNG lossless, portable, well-compressed storage of raster images. PNG
provides a patent-free replacement for GIF, and can also replace many provides a patent-free replacement for GIF, and can also replace many
common uses of TIFF. Indexed-color, grayscale, and truecolor images are common uses of TIFF. Indexed-color, grayscale, and truecolor images
supported, plus an optional alpha channel. Sample depths range from are supported, plus an optional alpha channel. Sample depths range
1 to 16 bits. from 1 to 16 bits.
.br .P
PNG is designed to work well in online viewing applications, such PNG is designed to work well in online viewing applications, such
as the World Wide Web, so it is fully streamable with a progressive as the World Wide Web, so it is fully streamable with a progressive
display option. PNG is robust, providing both full file integrity display option. PNG is robust, providing both full file integrity
checking and fast, simple detection of common transmission errors. checking and fast, simple detection of common transmission errors.
Also, PNG can store gamma and chromaticity data for improved color Also, PNG can store color space data for improved color matching on
matching on heterogeneous platforms. heterogeneous platforms.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR "libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) .BR "libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5)
.LP .LP
PNG Specification (Third Edition), June 2025: Portable Network Graphics (PNG) Specification (Third Edition):
.IP .IP
.br .br
W3C Recommendation 24 June 2025
.br
https://www.w3.org/TR/2025/REC-png-3-20250624/ https://www.w3.org/TR/2025/REC-png-3-20250624/
.LP .LP
PNG Specification (Second Edition), November 2003: Portable Network Graphics (PNG) Specification (Second Edition):
.IP .IP
.br .br
ISO/IEC 15948:2004(E)
.br
https://www.iso.org/standard/29581.html
.IP
.br
W3C Recommendation 10 November 2003
.br
https://www.w3.org/TR/2003/REC-PNG-20031110/ https://www.w3.org/TR/2003/REC-PNG-20031110/
.LP .LP
PNG 1.2 Specification, August 1999: Portable Network Graphics (PNG) Specification Version 1.2:
.IP .IP
.br .br
Published by the PNG Development Group on 14 July 1999
.br
https://www.libpng.org/pub/png/spec/1.2/ https://www.libpng.org/pub/png/spec/1.2/
.LP .LP
PNG 1.1 Specification, December 1998: Portable Network Graphics (PNG) Specification Version 1.1:
.IP .IP
.br .br
Published by the PNG Development Group on 15 February 1999
.br
https://www.libpng.org/pub/png/spec/1.1/ https://www.libpng.org/pub/png/spec/1.1/
.LP .LP
PNG 1.0 Specification, October 1996: Portable Network Graphics (PNG) Specification Version 1.0:
.IP .IP
.br .br
RFC 2083 IETF RFC 2083, March 1997
.br .br
https://www.ietf.org/rfc/rfc2083.txt https://www.ietf.org/rfc/rfc2083.txt
.IP .IP
.br .br
or W3C Recommendation W3C Recommendation 1 October 1996
.br .br
https://www.w3.org/TR/REC-png-961001 https://www.w3.org/TR/REC-png-961001
.SH AUTHORS .SH AUTHORS
This man page: Glenn Randers-Pehrson, Cosmin Truta This man page: Glenn Randers-Pehrson, Cosmin Truta, Chris Lilley.
.LP .LP
Portable Network Graphics (PNG) Specification (Third Edition). PNG Specification (Third Edition): Chris Blume et al.
W3C Recommendation 24 June 2025:
Chris Blume et al.
.LP .LP
Portable Network Graphics (PNG) Specification (Second Edition) PNG Specification (Second Edition): David Duce et al.
Information technology - Computer graphics and image processing -
Portable Network Graphics (PNG): Functional specification.
ISO/IEC 15948:2003 (E), W3C Recommendation 10 November 2003:
David Duce et al.
.LP .LP
Portable Network Graphics (PNG) Specification Version 1.2 (11 August 1999): PNG Specification Version 1.2: Glenn Randers-Pehrson et al.
Glenn Randers-Pehrson et al.
.LP .LP
Portable Network Graphics (PNG) Specification Version 1.1 (31 December 1998): PNG Specification Version 1.1: Glenn Randers-Pehrson et al.
Glenn Randers-Pehrson et al.
.LP .LP
Portable Network Graphics (PNG) Specification Version 1.0. PNG Specification Version 1.0: Thomas Boutell et al.
IETF RFC 2083, W3C Recommendation 1 October 1996:
Thomas Boutell et al.
.\" end of man page .\" end of man page

View File

@ -1,6 +1,6 @@
/* png.c - location for general purpose libpng functions /* png.c - location for general purpose libpng functions
* *
* Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@ -13,7 +13,7 @@
#include "pngpriv.h" #include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */ /* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_50 Your_png_h_is_not_version_1_6_50; typedef png_libpng_version_1_6_54 Your_png_h_is_not_version_1_6_54;
/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the /* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
* corresponding macro definitions. This causes a compile time failure if * corresponding macro definitions. This causes a compile time failure if
@ -101,17 +101,24 @@ png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* Function to allocate memory for zlib */ /* Function to allocate memory for zlib */
PNG_FUNCTION(voidpf /* PRIVATE */, PNG_FUNCTION(voidpf /* PRIVATE */,
png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) png_zalloc,(voidpf png_ptr, uInt items, uInt size),
PNG_ALLOCATED)
{ {
png_alloc_size_t num_bytes = size; png_alloc_size_t num_bytes = size;
if (png_ptr == NULL) if (png_ptr == NULL)
return NULL; return NULL;
if (items >= (~(png_alloc_size_t)0)/size) /* This check against overflow is vestigial, dating back from
* the old times when png_zalloc used to be an exported function.
* We're still keeping it here for now, as an extra-cautious
* prevention against programming errors inside zlib, although it
* should rather be a debug-time assertion instead.
*/
if (size != 0 && items >= (~(png_alloc_size_t)0) / size)
{ {
png_warning (png_voidcast(png_structrp, png_ptr), png_warning(png_voidcast(png_structrp, png_ptr),
"Potential overflow in png_zalloc()"); "Potential overflow in png_zalloc()");
return NULL; return NULL;
} }
@ -238,10 +245,6 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
png_warning(png_ptr, m); png_warning(png_ptr, m);
#endif #endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
png_ptr->flags = 0;
#endif
return 0; return 0;
} }
@ -255,7 +258,8 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
PNG_FUNCTION(png_structp /* PRIVATE */, PNG_FUNCTION(png_structp /* PRIVATE */,
png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) png_malloc_ptr malloc_fn, png_free_ptr free_fn),
PNG_ALLOCATED)
{ {
png_struct create_struct; png_struct create_struct;
# ifdef PNG_SETJMP_SUPPORTED # ifdef PNG_SETJMP_SUPPORTED
@ -359,7 +363,8 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
/* Allocate the memory for an info_struct for the application. */ /* Allocate the memory for an info_struct for the application. */
PNG_FUNCTION(png_infop,PNGAPI PNG_FUNCTION(png_infop,PNGAPI
png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) png_create_info_struct,(png_const_structrp png_ptr),
PNG_ALLOCATED)
{ {
png_inforp info_ptr; png_inforp info_ptr;
@ -815,8 +820,8 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT return PNG_STRING_COPYRIGHT
#else #else
return PNG_STRING_NEWLINE \ return PNG_STRING_NEWLINE \
"libpng version 1.6.50" PNG_STRING_NEWLINE \ "libpng version 1.6.54" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 2018-2026 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \ PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@ -2255,8 +2260,8 @@ PNG_FP_End:
int int
png_check_fp_string(png_const_charp string, size_t size) png_check_fp_string(png_const_charp string, size_t size)
{ {
int state=0; int state = 0;
size_t char_index=0; size_t char_index = 0;
if (png_check_fp_number(string, size, &state, &char_index) != 0 && if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
(char_index == size || string[char_index] == 0)) (char_index == size || string[char_index] == 0))

1121
png/png.h

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/* pngconf.h - machine-configurable file for libpng /* pngconf.h - machine-configurable file for libpng
* *
* libpng version 1.6.50 * libpng version 1.6.54
* *
* Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.

View File

@ -38,9 +38,6 @@
#define PNGDEBUG_H #define PNGDEBUG_H
/* These settings control the formatting of messages in png.c and pngerror.c */ /* These settings control the formatting of messages in png.c and pngerror.c */
/* Moved to pngdebug.h at 1.5.0 */ /* Moved to pngdebug.h at 1.5.0 */
# ifndef PNG_LITERAL_SHARP
# define PNG_LITERAL_SHARP 0x23
# endif
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET # ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b # define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
# endif # endif

View File

@ -39,46 +39,6 @@ PNG_FUNCTION(void,PNGAPI
png_error,(png_const_structrp png_ptr, png_const_charp error_message), png_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN) PNG_NORETURN)
{ {
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
char msg[16];
if (png_ptr != NULL)
{
if ((png_ptr->flags &
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
{
if (*error_message == PNG_LITERAL_SHARP)
{
/* Strip "#nnnn " from beginning of error message. */
int offset;
for (offset = 1; offset<15; offset++)
if (error_message[offset] == ' ')
break;
if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
int i;
for (i = 0; i < offset - 1; i++)
msg[i] = error_message[i + 1];
msg[i - 1] = '\0';
error_message = msg;
}
else
error_message += offset;
}
else
{
if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
msg[0] = '0';
msg[1] = '\0';
error_message = msg;
}
}
}
}
#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL) if (png_ptr != NULL && png_ptr->error_fn != NULL)
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
error_message); error_message);
@ -89,7 +49,8 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message),
} }
#else #else
PNG_FUNCTION(void,PNGAPI PNG_FUNCTION(void,PNGAPI
png_err,(png_const_structrp png_ptr),PNG_NORETURN) png_err,(png_const_structrp png_ptr),
PNG_NORETURN)
{ {
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
* erroneously as '\0', instead of the empty string "". This was * erroneously as '\0', instead of the empty string "". This was
@ -216,21 +177,6 @@ void PNGAPI
png_warning(png_const_structrp png_ptr, png_const_charp warning_message) png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{ {
int offset = 0; int offset = 0;
if (png_ptr != NULL)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
if ((png_ptr->flags &
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
#endif
{
if (*warning_message == PNG_LITERAL_SHARP)
{
for (offset = 1; offset < 15; offset++)
if (warning_message[offset] == ' ')
break;
}
}
}
if (png_ptr != NULL && png_ptr->warning_fn != NULL) if (png_ptr != NULL && png_ptr->warning_fn != NULL)
(*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
warning_message + offset); warning_message + offset);
@ -431,8 +377,8 @@ static const char png_digit[16] = {
}; };
static void /* PRIVATE */ static void /* PRIVATE */
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp png_format_buffer(png_const_structrp png_ptr, png_charp buffer,
error_message) png_const_charp error_message)
{ {
png_uint_32 chunk_name = png_ptr->chunk_name; png_uint_32 chunk_name = png_ptr->chunk_name;
int iout = 0, ishift = 24; int iout = 0, ishift = 24;
@ -511,8 +457,8 @@ png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
#ifdef PNG_BENIGN_ERRORS_SUPPORTED #ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI void PNGAPI
png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp png_chunk_benign_error(png_const_structrp png_ptr,
error_message) png_const_charp error_message)
{ {
if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
png_chunk_warning(png_ptr, error_message); png_chunk_warning(png_ptr, error_message);
@ -569,7 +515,8 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
#ifdef PNG_ERROR_TEXT_SUPPORTED #ifdef PNG_ERROR_TEXT_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_FUNCTION(void, PNG_FUNCTION(void,
png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),
PNG_NORETURN)
{ {
# define fixed_message "fixed point overflow in " # define fixed_message "fixed point overflow in "
# define fixed_message_ln ((sizeof fixed_message)-1) # define fixed_message_ln ((sizeof fixed_message)-1)
@ -712,42 +659,9 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN) PNG_NORETURN)
{ {
#ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_CONSOLE_IO_SUPPORTED
#ifdef PNG_ERROR_NUMBERS_SUPPORTED fprintf(stderr, "libpng error: %s", error_message ? error_message :
/* Check on NULL only added in 1.5.4 */ "undefined");
if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) fprintf(stderr, PNG_STRING_NEWLINE);
{
/* Strip "#nnnn " from beginning of error message. */
int offset;
char error_number[16];
for (offset = 0; offset<15; offset++)
{
error_number[offset] = error_message[offset + 1];
if (error_message[offset] == ' ')
break;
}
if ((offset > 1) && (offset < 15))
{
error_number[offset - 1] = '\0';
fprintf(stderr, "libpng error no. %s: %s",
error_number, error_message + offset + 1);
fprintf(stderr, PNG_STRING_NEWLINE);
}
else
{
fprintf(stderr, "libpng error: %s, offset=%d",
error_message, offset);
fprintf(stderr, PNG_STRING_NEWLINE);
}
}
else
#endif
{
fprintf(stderr, "libpng error: %s", error_message ? error_message :
"undefined");
fprintf(stderr, PNG_STRING_NEWLINE);
}
#else #else
PNG_UNUSED(error_message) /* Make compiler happy */ PNG_UNUSED(error_message) /* Make compiler happy */
#endif #endif
@ -755,7 +669,8 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
} }
PNG_FUNCTION(void,PNGAPI PNG_FUNCTION(void,PNGAPI
png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) png_longjmp,(png_const_structrp png_ptr, int val),
PNG_NORETURN)
{ {
#ifdef PNG_SETJMP_SUPPORTED #ifdef PNG_SETJMP_SUPPORTED
if (png_ptr != NULL && png_ptr->longjmp_fn != NULL && if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
@ -785,40 +700,8 @@ static void /* PRIVATE */
png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{ {
#ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_CONSOLE_IO_SUPPORTED
# ifdef PNG_ERROR_NUMBERS_SUPPORTED fprintf(stderr, "libpng warning: %s", warning_message);
if (*warning_message == PNG_LITERAL_SHARP) fprintf(stderr, PNG_STRING_NEWLINE);
{
int offset;
char warning_number[16];
for (offset = 0; offset < 15; offset++)
{
warning_number[offset] = warning_message[offset + 1];
if (warning_message[offset] == ' ')
break;
}
if ((offset > 1) && (offset < 15))
{
warning_number[offset + 1] = '\0';
fprintf(stderr, "libpng warning no. %s: %s",
warning_number, warning_message + offset);
fprintf(stderr, PNG_STRING_NEWLINE);
}
else
{
fprintf(stderr, "libpng warning: %s",
warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
}
}
else
# endif
{
fprintf(stderr, "libpng warning: %s", warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
}
#else #else
PNG_UNUSED(warning_message) /* Make compiler happy */ PNG_UNUSED(warning_message) /* Make compiler happy */
#endif #endif
@ -866,12 +749,8 @@ png_get_error_ptr(png_const_structrp png_ptr)
void PNGAPI void PNGAPI
png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
{ {
if (png_ptr != NULL) PNG_UNUSED(png_ptr)
{ PNG_UNUSED(strip_mode)
png_ptr->flags &=
((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
}
} }
#endif #endif

View File

@ -122,8 +122,8 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
} }
png_uint_32 PNGAPI png_uint_32 PNGAPI
png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp png_get_x_pixels_per_meter(png_const_structrp png_ptr,
info_ptr) png_const_inforp info_ptr)
{ {
#ifdef PNG_pHYs_SUPPORTED #ifdef PNG_pHYs_SUPPORTED
png_debug(1, "in png_get_x_pixels_per_meter"); png_debug(1, "in png_get_x_pixels_per_meter");
@ -143,8 +143,8 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
} }
png_uint_32 PNGAPI png_uint_32 PNGAPI
png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp png_get_y_pixels_per_meter(png_const_structrp png_ptr,
info_ptr) png_const_inforp info_ptr)
{ {
#ifdef PNG_pHYs_SUPPORTED #ifdef PNG_pHYs_SUPPORTED
png_debug(1, "in png_get_y_pixels_per_meter"); png_debug(1, "in png_get_y_pixels_per_meter");
@ -186,8 +186,8 @@ png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
#ifdef PNG_FLOATING_POINT_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI float PNGAPI
png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp png_get_pixel_aspect_ratio(png_const_structrp png_ptr,
info_ptr) png_const_inforp info_ptr)
{ {
#ifdef PNG_READ_pHYs_SUPPORTED #ifdef PNG_READ_pHYs_SUPPORTED
png_debug(1, "in png_get_pixel_aspect_ratio"); png_debug(1, "in png_get_pixel_aspect_ratio");
@ -737,7 +737,6 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
} }
return 0; return 0;
} }
#endif #endif

View File

@ -1,8 +1,8 @@
/* pnglibconf.h - library build configuration */ /* pnglibconf.h - library build configuration */
/* libpng version 1.6.50 */ /* libpng version 1.6.54 */
/* Copyright (c) 2018-2025 Cosmin Truta */ /* Copyright (c) 2018-2026 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */ /* This code is released under the libpng license. */

View File

@ -46,7 +46,8 @@ png_destroy_png_struct(png_structrp png_ptr)
* have the ability to do that. * have the ability to do that.
*/ */
PNG_FUNCTION(png_voidp,PNGAPI PNG_FUNCTION(png_voidp,PNGAPI
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{ {
png_voidp ret; png_voidp ret;
@ -118,7 +119,8 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
PNG_FUNCTION(png_voidp /* PRIVATE */, PNG_FUNCTION(png_voidp /* PRIVATE */,
png_malloc_array,(png_const_structrp png_ptr, int nelements, png_malloc_array,(png_const_structrp png_ptr, int nelements,
size_t element_size),PNG_ALLOCATED) size_t element_size),
PNG_ALLOCATED)
{ {
if (nelements <= 0 || element_size == 0) if (nelements <= 0 || element_size == 0)
png_error(png_ptr, "internal error: array alloc"); png_error(png_ptr, "internal error: array alloc");
@ -128,7 +130,8 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements,
PNG_FUNCTION(png_voidp /* PRIVATE */, PNG_FUNCTION(png_voidp /* PRIVATE */,
png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) int old_elements, int add_elements, size_t element_size),
PNG_ALLOCATED)
{ {
/* These are internal errors: */ /* These are internal errors: */
if (add_elements <= 0 || element_size == 0 || old_elements < 0 || if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
@ -167,7 +170,8 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
* function png_malloc_default is also provided. * function png_malloc_default is also provided.
*/ */
PNG_FUNCTION(png_voidp,PNGAPI PNG_FUNCTION(png_voidp,PNGAPI
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{ {
png_voidp ret; png_voidp ret;
@ -241,7 +245,8 @@ png_free(png_const_structrp png_ptr, png_voidp ptr)
} }
PNG_FUNCTION(void,PNGAPI PNG_FUNCTION(void,PNGAPI
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) png_free_default,(png_const_structrp png_ptr, png_voidp ptr),
PNG_DEPRECATED)
{ {
if (png_ptr == NULL || ptr == NULL) if (png_ptr == NULL || ptr == NULL)
return; return;
@ -255,8 +260,8 @@ png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
* of allocating and freeing memory. * of allocating and freeing memory.
*/ */
void PNGAPI void PNGAPI
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr,
malloc_fn, png_free_ptr free_fn) png_malloc_ptr malloc_fn, png_free_ptr free_fn)
{ {
if (png_ptr != NULL) if (png_ptr != NULL)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* pngread.c - read a PNG file /* pngread.c - read a PNG file
* *
* Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@ -23,7 +23,8 @@
/* Create a PNG structure for reading, and allocate any memory needed. */ /* Create a PNG structure for reading, and allocate any memory needed. */
PNG_FUNCTION(png_structp,PNGAPI PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) png_error_ptr error_fn, png_error_ptr warn_fn),
PNG_ALLOCATED)
{ {
#ifndef PNG_USER_MEM_SUPPORTED #ifndef PNG_USER_MEM_SUPPORTED
png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
@ -39,7 +40,8 @@ png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
PNG_FUNCTION(png_structp,PNGAPI PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) png_malloc_ptr malloc_fn, png_free_ptr free_fn),
PNG_ALLOCATED)
{ {
png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
@ -519,7 +521,6 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
if (png_ptr->read_row_fn != NULL) if (png_ptr->read_row_fn != NULL)
(*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
} }
#endif /* SEQUENTIAL_READ */ #endif /* SEQUENTIAL_READ */
@ -867,7 +868,7 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI void PNGAPI
png_read_png(png_structrp png_ptr, png_inforp info_ptr, png_read_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, voidp params) int transforms, png_voidp params)
{ {
png_debug(1, "in png_read_png"); png_debug(1, "in png_read_png");
@ -1104,19 +1105,20 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr,
typedef struct typedef struct
{ {
/* Arguments: */ /* Arguments */
png_imagep image; png_imagep image;
png_voidp buffer; png_voidp buffer;
png_int_32 row_stride; png_int_32 row_stride;
png_voidp colormap; png_voidp colormap;
png_const_colorp background; png_const_colorp background;
/* Local variables: */
png_voidp local_row; /* Instance variables */
png_voidp first_row; png_voidp local_row;
ptrdiff_t row_bytes; /* step between rows */ png_voidp first_row;
int file_encoding; /* E_ values above */ ptrdiff_t row_step; /* step between rows */
png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ int file_encoding; /* E_ values above */
int colormap_processing; /* PNG_CMAP_ values above */ png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */
int colormap_processing; /* PNG_CMAP_ values above */
} png_image_read_control; } png_image_read_control;
/* Do all the *safe* initialization - 'safe' means that png_error won't be /* Do all the *safe* initialization - 'safe' means that png_error won't be
@ -2837,17 +2839,17 @@ png_image_read_and_map(png_voidp argument)
} }
{ {
png_uint_32 height = image->height; png_uint_32 height = image->height;
png_uint_32 width = image->width; png_uint_32 width = image->width;
int proc = display->colormap_processing; int proc = display->colormap_processing;
png_bytep first_row = png_voidcast(png_bytep, display->first_row); png_bytep first_row = png_voidcast(png_bytep, display->first_row);
ptrdiff_t step_row = display->row_bytes; ptrdiff_t row_step = display->row_step;
int pass; int pass;
for (pass = 0; pass < passes; ++pass) for (pass = 0; pass < passes; ++pass)
{ {
unsigned int startx, stepx, stepy; unsigned int startx, stepx, stepy;
png_uint_32 y; png_uint_32 y;
if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
{ {
@ -2871,7 +2873,7 @@ png_image_read_and_map(png_voidp argument)
for (; y<height; y += stepy) for (; y<height; y += stepy)
{ {
png_bytep inrow = png_voidcast(png_bytep, display->local_row); png_bytep inrow = png_voidcast(png_bytep, display->local_row);
png_bytep outrow = first_row + y * step_row; png_bytep outrow = first_row + y * row_step;
png_const_bytep end_row = outrow + width; png_const_bytep end_row = outrow + width;
/* Read read the libpng data into the temporary buffer. */ /* Read read the libpng data into the temporary buffer. */
@ -3080,20 +3082,20 @@ png_image_read_colormapped(png_voidp argument)
*/ */
{ {
png_voidp first_row = display->buffer; png_voidp first_row = display->buffer;
ptrdiff_t row_bytes = display->row_stride; ptrdiff_t row_step = display->row_stride;
/* The following expression is designed to work correctly whether it gives /* The following adjustment is to ensure that calculations are correct,
* a signed or an unsigned result. * regardless whether row_step is positive or negative.
*/ */
if (row_bytes < 0) if (row_step < 0)
{ {
char *ptr = png_voidcast(char*, first_row); char *ptr = png_voidcast(char*, first_row);
ptr += (image->height-1) * (-row_bytes); ptr += (image->height-1) * (-row_step);
first_row = png_voidcast(png_voidp, ptr); first_row = png_voidcast(png_voidp, ptr);
} }
display->first_row = first_row; display->first_row = first_row;
display->row_bytes = row_bytes; display->row_step = row_step;
} }
if (passes == 0) if (passes == 0)
@ -3111,17 +3113,17 @@ png_image_read_colormapped(png_voidp argument)
else else
{ {
png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; ptrdiff_t row_step = display->row_step;
while (--passes >= 0) while (--passes >= 0)
{ {
png_uint_32 y = image->height; png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row); png_bytep row = png_voidcast(png_bytep, display->first_row);
for (; y > 0; --y) for (; y > 0; --y)
{ {
png_read_row(png_ptr, row, NULL); png_read_row(png_ptr, row, NULL);
row += row_bytes; row += row_step;
} }
} }
@ -3129,6 +3131,61 @@ png_image_read_colormapped(png_voidp argument)
} }
} }
/* 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_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_step = display->row_step;
size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
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.
* Use row_bytes (i.e. the actual size in bytes of the row data) for
* copying into output_row. Use row_step for advancing output_row,
* to respect the caller's stride for padding or negative (bottom-up)
* layouts.
*/
memcpy(output_row, local_row, row_bytes);
output_row += row_step;
}
}
return 1;
}
/* Just the row reading part of png_image_read. */ /* Just the row reading part of png_image_read. */
static int static int
png_image_read_composite(png_voidp argument) png_image_read_composite(png_voidp argument)
@ -3154,17 +3211,18 @@ png_image_read_composite(png_voidp argument)
} }
{ {
png_uint_32 height = image->height; png_uint_32 height = image->height;
png_uint_32 width = image->width; png_uint_32 width = image->width;
ptrdiff_t step_row = display->row_bytes; ptrdiff_t row_step = display->row_step;
unsigned int channels = unsigned int channels =
(image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
int pass; int pass;
for (pass = 0; pass < passes; ++pass) for (pass = 0; pass < passes; ++pass)
{ {
unsigned int startx, stepx, stepy; unsigned int startx, stepx, stepy;
png_uint_32 y; png_uint_32 y;
if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
{ {
@ -3196,7 +3254,7 @@ png_image_read_composite(png_voidp argument)
png_read_row(png_ptr, inrow, NULL); png_read_row(png_ptr, inrow, NULL);
outrow = png_voidcast(png_bytep, display->first_row); outrow = png_voidcast(png_bytep, display->first_row);
outrow += y * step_row; outrow += y * row_step;
end_row = outrow + width * channels; end_row = outrow + width * channels;
/* Now do the composition on each pixel in this row. */ /* Now do the composition on each pixel in this row. */
@ -3215,20 +3273,44 @@ png_image_read_composite(png_voidp argument)
if (alpha < 255) /* else just use component */ if (alpha < 255) /* else just use component */
{ {
/* This is PNG_OPTIMIZED_ALPHA, the component value if (optimize_alpha != 0)
* is a linear 8-bit value. Combine this with the {
* current outrow[c] value which is sRGB encoded. /* This is PNG_OPTIMIZED_ALPHA, the component value
* Arithmetic here is 16-bits to preserve the output * is a linear 8-bit value. Combine this with the
* values correctly. * current outrow[c] value which is sRGB encoded.
*/ * Arithmetic here is 16-bits to preserve the output
component *= 257*255; /* =65535 */ * values correctly.
component += (255-alpha)*png_sRGB_table[outrow[c]]; */
component *= 257*255; /* =65535 */
component += (255-alpha)*png_sRGB_table[outrow[c]];
/* So 'component' is scaled by 255*65535 and is /* Clamp to the valid range to defend against
* therefore appropriate for the sRGB to linear * unforeseen cases where the data might be sRGB
* conversion table. * instead of linear premultiplied.
*/ * (Belt-and-suspenders for CVE-2025-66293.)
component = PNG_sRGB_FROM_LINEAR(component); */
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; outrow[c] = (png_byte)component;
@ -3317,12 +3399,12 @@ png_image_read_background(png_voidp argument)
*/ */
{ {
png_bytep first_row = png_voidcast(png_bytep, display->first_row); png_bytep first_row = png_voidcast(png_bytep, display->first_row);
ptrdiff_t step_row = display->row_bytes; ptrdiff_t row_step = display->row_step;
for (pass = 0; pass < passes; ++pass) for (pass = 0; pass < passes; ++pass)
{ {
unsigned int startx, stepx, stepy; unsigned int startx, stepx, stepy;
png_uint_32 y; png_uint_32 y;
if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
{ {
@ -3349,7 +3431,7 @@ png_image_read_background(png_voidp argument)
{ {
png_bytep inrow = png_voidcast(png_bytep, png_bytep inrow = png_voidcast(png_bytep,
display->local_row); display->local_row);
png_bytep outrow = first_row + y * step_row; png_bytep outrow = first_row + y * row_step;
png_const_bytep end_row = outrow + width; png_const_bytep end_row = outrow + width;
/* Read the row, which is packed: */ /* Read the row, which is packed: */
@ -3394,7 +3476,7 @@ png_image_read_background(png_voidp argument)
{ {
png_bytep inrow = png_voidcast(png_bytep, png_bytep inrow = png_voidcast(png_bytep,
display->local_row); display->local_row);
png_bytep outrow = first_row + y * step_row; png_bytep outrow = first_row + y * row_step;
png_const_bytep end_row = outrow + width; png_const_bytep end_row = outrow + width;
/* Read the row, which is packed: */ /* Read the row, which is packed: */
@ -3440,9 +3522,9 @@ png_image_read_background(png_voidp argument)
png_uint_16p first_row = png_voidcast(png_uint_16p, png_uint_16p first_row = png_voidcast(png_uint_16p,
display->first_row); display->first_row);
/* The division by two is safe because the caller passed in a /* The division by two is safe because the caller passed in a
* stride which was multiplied by 2 (below) to get row_bytes. * stride which was multiplied by 2 (below) to get row_step.
*/ */
ptrdiff_t step_row = display->row_bytes / 2; ptrdiff_t row_step = display->row_step / 2;
unsigned int preserve_alpha = (image->format & unsigned int preserve_alpha = (image->format &
PNG_FORMAT_FLAG_ALPHA) != 0; PNG_FORMAT_FLAG_ALPHA) != 0;
unsigned int outchannels = 1U+preserve_alpha; unsigned int outchannels = 1U+preserve_alpha;
@ -3456,8 +3538,8 @@ png_image_read_background(png_voidp argument)
for (pass = 0; pass < passes; ++pass) for (pass = 0; pass < passes; ++pass)
{ {
unsigned int startx, stepx, stepy; unsigned int startx, stepx, stepy;
png_uint_32 y; png_uint_32 y;
/* The 'x' start and step are adjusted to output components here. /* The 'x' start and step are adjusted to output components here.
*/ */
@ -3484,7 +3566,7 @@ png_image_read_background(png_voidp argument)
for (; y<height; y += stepy) for (; y<height; y += stepy)
{ {
png_const_uint_16p inrow; png_const_uint_16p inrow;
png_uint_16p outrow = first_row + y*step_row; png_uint_16p outrow = first_row + y * row_step;
png_uint_16p end_row = outrow + width * outchannels; png_uint_16p end_row = outrow + width * outchannels;
/* Read the row, which is packed: */ /* Read the row, which is packed: */
@ -3547,6 +3629,7 @@ png_image_read_direct(png_voidp argument)
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
int do_local_compose = 0; int do_local_compose = 0;
int do_local_background = 0; /* to avoid double gamma correction bug */ 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; int passes = 0;
/* Add transforms to ensure the correct output format is produced then check /* Add transforms to ensure the correct output format is produced then check
@ -3680,8 +3763,16 @@ png_image_read_direct(png_voidp argument)
png_set_expand_16(png_ptr); png_set_expand_16(png_ptr);
else /* 8-bit output */ else /* 8-bit output */
{
png_set_scale_16(png_ptr); 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; change &= ~PNG_FORMAT_FLAG_LINEAR;
} }
@ -3912,23 +4003,23 @@ png_image_read_direct(png_voidp argument)
*/ */
{ {
png_voidp first_row = display->buffer; png_voidp first_row = display->buffer;
ptrdiff_t row_bytes = display->row_stride; ptrdiff_t row_step = display->row_stride;
if (linear != 0) if (linear != 0)
row_bytes *= 2; row_step *= 2;
/* The following expression is designed to work correctly whether it gives /* The following adjustment is to ensure that calculations are correct,
* a signed or an unsigned result. * regardless whether row_step is positive or negative.
*/ */
if (row_bytes < 0) if (row_step < 0)
{ {
char *ptr = png_voidcast(char*, first_row); char *ptr = png_voidcast(char*, first_row);
ptr += (image->height-1) * (-row_bytes); ptr += (image->height - 1) * (-row_step);
first_row = png_voidcast(png_voidp, ptr); first_row = png_voidcast(png_voidp, ptr);
} }
display->first_row = first_row; display->first_row = first_row;
display->row_bytes = row_bytes; display->row_step = row_step;
} }
if (do_local_compose != 0) if (do_local_compose != 0)
@ -3957,19 +4048,37 @@ png_image_read_direct(png_voidp argument)
return result; 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 else
{ {
png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; ptrdiff_t row_step = display->row_step;
while (--passes >= 0) while (--passes >= 0)
{ {
png_uint_32 y = image->height; png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row); png_bytep row = png_voidcast(png_bytep, display->first_row);
for (; y > 0; --y) for (; y > 0; --y)
{ {
png_read_row(png_ptr, row, NULL); png_read_row(png_ptr, row, NULL);
row += row_bytes; row += row_step;
} }
} }

View File

@ -501,9 +501,19 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
{ {
int i; int i;
/* Initialize the array to index colors.
*
* Ensure quantize_index can fit 256 elements (PNG_MAX_PALETTE_LENGTH)
* rather than num_palette elements. This is to prevent buffer overflows
* caused by malformed PNG files with out-of-range palette indices.
*
* Be careful to avoid leaking memory. Applications are allowed to call
* this function more than once per png_struct.
*/
png_free(png_ptr, png_ptr->quantize_index);
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette); PNG_MAX_PALETTE_LENGTH);
for (i = 0; i < num_palette; i++) for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
png_ptr->quantize_index[i] = (png_byte)i; png_ptr->quantize_index[i] = (png_byte)i;
} }
@ -515,15 +525,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
* Perhaps not the best solution, but good enough. * Perhaps not the best solution, but good enough.
*/ */
int i; png_bytep quantize_sort;
int i, j;
/* Initialize an array to sort colors */ /* Initialize the local array to sort colors. */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, quantize_sort = (png_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette); (png_alloc_size_t)num_palette);
/* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
png_ptr->quantize_sort[i] = (png_byte)i; quantize_sort[i] = (png_byte)i;
/* Find the least used palette entries by starting a /* Find the least used palette entries by starting a
* bubble sort, and running it until we have sorted * bubble sort, and running it until we have sorted
@ -535,19 +544,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
for (i = num_palette - 1; i >= maximum_colors; i--) for (i = num_palette - 1; i >= maximum_colors; i--)
{ {
int done; /* To stop early if the list is pre-sorted */ int done; /* To stop early if the list is pre-sorted */
int j;
done = 1; done = 1;
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
if (histogram[png_ptr->quantize_sort[j]] if (histogram[quantize_sort[j]]
< histogram[png_ptr->quantize_sort[j + 1]]) < histogram[quantize_sort[j + 1]])
{ {
png_byte t; png_byte t;
t = png_ptr->quantize_sort[j]; t = quantize_sort[j];
png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; quantize_sort[j] = quantize_sort[j + 1];
png_ptr->quantize_sort[j + 1] = t; quantize_sort[j + 1] = t;
done = 0; done = 0;
} }
} }
@ -559,18 +567,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Swap the palette around, and set up a table, if necessary */ /* Swap the palette around, and set up a table, if necessary */
if (full_quantize != 0) if (full_quantize != 0)
{ {
int j = num_palette; j = num_palette;
/* Put all the useful colors within the max, but don't /* Put all the useful colors within the max, but don't
* move the others. * move the others.
*/ */
for (i = 0; i < maximum_colors; i++) for (i = 0; i < maximum_colors; i++)
{ {
if ((int)png_ptr->quantize_sort[i] >= maximum_colors) if ((int)quantize_sort[i] >= maximum_colors)
{ {
do do
j--; j--;
while ((int)png_ptr->quantize_sort[j] >= maximum_colors); while ((int)quantize_sort[j] >= maximum_colors);
palette[i] = palette[j]; palette[i] = palette[j];
} }
@ -578,7 +586,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
} }
else else
{ {
int j = num_palette; j = num_palette;
/* Move all the used colors inside the max limit, and /* Move all the used colors inside the max limit, and
* develop a translation table. * develop a translation table.
@ -586,13 +594,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
for (i = 0; i < maximum_colors; i++) for (i = 0; i < maximum_colors; i++)
{ {
/* Only move the colors we need to */ /* Only move the colors we need to */
if ((int)png_ptr->quantize_sort[i] >= maximum_colors) if ((int)quantize_sort[i] >= maximum_colors)
{ {
png_color tmp_color; png_color tmp_color;
do do
j--; j--;
while ((int)png_ptr->quantize_sort[j] >= maximum_colors); while ((int)quantize_sort[j] >= maximum_colors);
tmp_color = palette[j]; tmp_color = palette[j];
palette[j] = palette[i]; palette[j] = palette[i];
@ -630,8 +638,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
} }
} }
} }
png_free(png_ptr, png_ptr->quantize_sort); png_free(png_ptr, quantize_sort);
png_ptr->quantize_sort = NULL;
} }
else else
{ {
@ -1113,8 +1120,8 @@ png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void PNGAPI void PNGAPI
png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr png_set_read_user_transform_fn(png_structrp png_ptr,
read_user_transform_fn) png_user_transform_ptr read_user_transform_fn)
{ {
png_debug(1, "in png_set_read_user_transform_fn"); png_debug(1, "in png_set_read_user_transform_fn");
@ -1774,19 +1781,51 @@ png_init_read_transformations(png_structrp png_ptr)
} }
else /* if (png_ptr->trans_alpha[i] != 0xff) */ 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]; component = png_ptr->gamma_to_1[palette[i].red];
png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); component =
palette[i].red = png_ptr->gamma_from_1[w]; (component * png_ptr->trans_alpha[i] + 128) / 255;
palette[i].red = png_ptr->gamma_from_1[component];
v = png_ptr->gamma_to_1[palette[i].green]; component = png_ptr->gamma_to_1[palette[i].green];
png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); component =
palette[i].green = png_ptr->gamma_from_1[w]; (component * png_ptr->trans_alpha[i] + 128) / 255;
palette[i].green = png_ptr->gamma_from_1[component];
v = png_ptr->gamma_to_1[palette[i].blue]; component = png_ptr->gamma_to_1[palette[i].blue];
png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); component =
palette[i].blue = png_ptr->gamma_from_1[w]; (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 else
@ -1804,6 +1843,7 @@ png_init_read_transformations(png_structrp png_ptr)
* transformations elsewhere. * transformations elsewhere.
*/ */
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
} /* color_type == PNG_COLOR_TYPE_PALETTE */ } /* color_type == PNG_COLOR_TYPE_PALETTE */
/* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
@ -5009,13 +5049,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
#ifdef PNG_READ_QUANTIZE_SUPPORTED #ifdef PNG_READ_QUANTIZE_SUPPORTED
if ((png_ptr->transformations & PNG_QUANTIZE) != 0) if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
{
png_do_quantize(row_info, png_ptr->row_buf + 1, png_do_quantize(row_info, png_ptr->row_buf + 1,
png_ptr->palette_lookup, png_ptr->quantize_index); png_ptr->palette_lookup, png_ptr->quantize_index);
if (row_info->rowbytes == 0)
png_error(png_ptr, "png_do_quantize returned rowbytes=0");
}
#endif /* READ_QUANTIZE */ #endif /* READ_QUANTIZE */
#ifdef PNG_READ_EXPAND_16_SUPPORTED #ifdef PNG_READ_EXPAND_16_SUPPORTED

View File

@ -2386,7 +2386,7 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
static png_handle_result_code /* PRIVATE */ static png_handle_result_code /* PRIVATE */
png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ {
png_text text_info; png_text text_info;
png_bytep buffer; png_bytep buffer;
png_charp key; png_charp key;
png_charp text; png_charp text;
@ -2459,8 +2459,8 @@ static png_handle_result_code /* PRIVATE */
png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ {
png_const_charp errmsg = NULL; png_const_charp errmsg = NULL;
png_bytep buffer; png_bytep buffer;
png_uint_32 keyword_length; png_uint_32 keyword_length;
png_debug(1, "in png_handle_zTXt"); png_debug(1, "in png_handle_zTXt");

View File

@ -405,7 +405,6 @@ struct png_struct_def
#ifdef PNG_READ_QUANTIZE_SUPPORTED #ifdef PNG_READ_QUANTIZE_SUPPORTED
/* The following three members were added at version 1.0.14 and 1.2.4 */ /* The following three members were added at version 1.0.14 and 1.2.4 */
png_bytep quantize_sort; /* working sort array */
png_bytep index_to_palette; /* where the original index currently is png_bytep index_to_palette; /* where the original index currently is
in the palette */ in the palette */
png_bytep palette_to_index; /* which original index points to this png_bytep palette_to_index; /* which original index points to this

View File

@ -802,8 +802,8 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
void PNGAPI void PNGAPI
png_set_user_transform_info(png_structrp png_ptr, png_voidp png_set_user_transform_info(png_structrp png_ptr, png_voidp user_transform_ptr,
user_transform_ptr, int user_transform_depth, int user_transform_channels) int user_transform_depth, int user_transform_channels)
{ {
png_debug(1, "in png_set_user_transform_info"); png_debug(1, "in png_set_user_transform_info");

View File

@ -1,6 +1,6 @@
/* pngwrite.c - general routines to write a PNG file /* pngwrite.c - general routines to write a PNG file
* *
* Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@ -542,7 +542,8 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
/* Initialize png_ptr structure, and allocate any memory needed */ /* Initialize png_ptr structure, and allocate any memory needed */
PNG_FUNCTION(png_structp,PNGAPI PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) png_error_ptr error_fn, png_error_ptr warn_fn),
PNG_ALLOCATED)
{ {
#ifndef PNG_USER_MEM_SUPPORTED #ifndef PNG_USER_MEM_SUPPORTED
png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
@ -556,7 +557,8 @@ png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
PNG_FUNCTION(png_structp,PNGAPI PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) png_malloc_ptr malloc_fn, png_free_ptr free_fn),
PNG_ALLOCATED)
{ {
png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
@ -1376,8 +1378,8 @@ png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
void PNGAPI void PNGAPI
png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr png_set_write_user_transform_fn(png_structrp png_ptr,
write_user_transform_fn) png_user_transform_ptr write_user_transform_fn)
{ {
png_debug(1, "in png_set_write_user_transform_fn"); png_debug(1, "in png_set_write_user_transform_fn");
@ -1393,7 +1395,7 @@ png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI void PNGAPI
png_write_png(png_structrp png_ptr, png_inforp info_ptr, png_write_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, voidp params) int transforms, png_voidp params)
{ {
png_debug(1, "in png_write_png"); png_debug(1, "in png_write_png");
@ -1558,18 +1560,20 @@ png_image_write_init(png_imagep image)
/* Arguments to png_image_write_main: */ /* Arguments to png_image_write_main: */
typedef struct typedef struct
{ {
/* Arguments: */ /* Arguments */
png_imagep image; png_imagep image;
png_const_voidp buffer; png_const_voidp buffer;
png_int_32 row_stride; png_int_32 row_stride;
png_const_voidp colormap; png_const_voidp colormap;
int convert_to_8bit; int convert_to_8bit;
/* Local variables: */
/* Instance variables */
png_const_voidp first_row; png_const_voidp first_row;
ptrdiff_t row_bytes; png_voidp local_row;
png_voidp local_row; ptrdiff_t row_step;
/* Byte count for memory writing */ /* Byte count for memory writing */
png_bytep memory; png_bytep memory;
png_alloc_size_t memory_bytes; /* not used for STDIO */ png_alloc_size_t memory_bytes; /* not used for STDIO */
png_alloc_size_t output_bytes; /* running total */ png_alloc_size_t output_bytes; /* running total */
} png_image_write_control; } png_image_write_control;
@ -1676,7 +1680,7 @@ png_write_image_16bit(png_voidp argument)
} }
png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); 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_step / 2;
} }
return 1; return 1;
@ -1802,7 +1806,7 @@ png_write_image_8bit(png_voidp argument)
png_write_row(png_ptr, png_voidcast(png_const_bytep, png_write_row(png_ptr, png_voidcast(png_const_bytep,
display->local_row)); display->local_row));
input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); input_row += display->row_step / 2;
} /* while y */ } /* while y */
} }
@ -1827,7 +1831,7 @@ png_write_image_8bit(png_voidp argument)
} }
png_write_row(png_ptr, output_row); png_write_row(png_ptr, output_row);
input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); input_row += display->row_step / 2;
} }
} }
@ -2143,16 +2147,16 @@ png_image_write_main(png_voidp argument)
{ {
png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
ptrdiff_t row_bytes = display->row_stride; ptrdiff_t row_step = display->row_stride;
if (linear != 0) if (linear != 0)
row_bytes *= (sizeof (png_uint_16)); row_step *= 2;
if (row_bytes < 0) if (row_step < 0)
row += (image->height-1) * (-row_bytes); row += (image->height-1) * (-row_step);
display->first_row = row; display->first_row = row;
display->row_bytes = row_bytes; display->row_step = row_step;
} }
/* Apply 'fast' options if the flag is set. */ /* Apply 'fast' options if the flag is set. */
@ -2173,8 +2177,7 @@ png_image_write_main(png_voidp argument)
* before it is written. This only applies when the input is 16-bit and * 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. * either there is an alpha channel or it is converted to 8-bit.
*/ */
if ((linear != 0 && alpha != 0 ) || if (linear != 0 && (alpha != 0 || display->convert_to_8bit != 0))
(colormap == 0 && display->convert_to_8bit != 0))
{ {
png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
png_get_rowbytes(png_ptr, info_ptr))); png_get_rowbytes(png_ptr, info_ptr)));
@ -2200,13 +2203,13 @@ png_image_write_main(png_voidp argument)
else else
{ {
png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
ptrdiff_t row_bytes = display->row_bytes; ptrdiff_t row_step = display->row_step;
png_uint_32 y = image->height; png_uint_32 y = image->height;
for (; y > 0; --y) for (; y > 0; --y)
{ {
png_write_row(png_ptr, row); png_write_row(png_ptr, row);
row += row_bytes; row += row_step;
} }
} }

View File

@ -485,10 +485,10 @@ png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
*/ */
typedef struct typedef struct
{ {
png_const_bytep input; /* The uncompressed input data */ png_const_bytep input; /* The uncompressed input data */
png_alloc_size_t input_len; /* Its length */ png_alloc_size_t input_len; /* Its length */
png_uint_32 output_len; /* Final compressed length */ png_uint_32 output_len; /* Final compressed length */
png_byte output[1024]; /* First block of output */ png_byte output[1024]; /* First block of output */
} compression_state; } compression_state;
static void static void