From 823c2d80dcea0d29cc3922c8599d250515a44f33 Mon Sep 17 00:00:00 2001 From: Cosmin Truta Date: Tue, 31 Dec 2024 22:05:03 +0200 Subject: [PATCH] [libpng16] fix: Update the cICP support for better compliance with PNG-3 Apply the following corrections and improvements: * Add a validity check in `png_set_cICP`. * Fix the ordering check in `png_handle_cICP`. * Add a multiplicity check in `png_handle_cICP`. * Optimize the implementation of `png_write_cICP`. * Remove an unnecessary preprocessor guard from pngtest.c. * Update the dependency declaration in pnglibconf.dfa. * Fix the indentation where necessary. This is a cherry-pick of commit c2a02691df1ecf51b7c97142752a7034350cb1f6 from branch 'libpng18'. --- pngpread.c | 4 ++-- pngread.c | 2 +- pngrutil.c | 48 +++++++++++++++++++++++------------------- pngset.c | 30 +++++++++++++++----------- pngtest.c | 28 ++++++++++++------------ pngwrite.c | 15 +++++++------ pngwutil.c | 17 +++++++++------ scripts/pnglibconf.dfa | 2 +- 8 files changed, 79 insertions(+), 67 deletions(-) diff --git a/pngpread.c b/pngpread.c index efa03f978f..1bf880eabb 100644 --- a/pngpread.c +++ b/pngpread.c @@ -312,8 +312,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_READ_cICP_SUPPORTED else if (png_ptr->chunk_name == png_cICP) { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_cICP(png_ptr, info_ptr, png_ptr->push_length); + PNG_PUSH_SAVE_BUFFER_IF_FULL + png_handle_cICP(png_ptr, info_ptr, png_ptr->push_length); } #endif diff --git a/pngread.c b/pngread.c index 317951f3d2..175d60144f 100644 --- a/pngread.c +++ b/pngread.c @@ -175,7 +175,7 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) #endif #ifdef PNG_READ_cICP_SUPPORTED else if (chunk_name == png_cICP) - png_handle_cICP(png_ptr, info_ptr, length); + png_handle_cICP(png_ptr, info_ptr, length); #endif #ifdef PNG_READ_eXIf_SUPPORTED diff --git a/pngrutil.c b/pngrutil.c index 282d976c89..7c609b4b48 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -2050,36 +2050,40 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) void /* PRIVATE */ png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { - png_byte buf[4]; + png_byte buf[4]; - png_debug(1, "in png_handle_cICP"); + png_debug(1, "in png_handle_cICP"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); + if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cICP) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } + else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cICP) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } - if (length != 4) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } + else if (length != 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } - png_crc_read(png_ptr, buf, 4); + png_crc_read(png_ptr, buf, 4); - if (png_crc_finish(png_ptr, 0) != 0) - return; + if (png_crc_finish(png_ptr, 0) != 0) + return; - png_set_cICP(png_ptr, info_ptr, buf[0], buf[1], buf[2], buf[3]); + png_set_cICP(png_ptr, info_ptr, buf[0], buf[1], buf[2], buf[3]); } #endif diff --git a/pngset.c b/pngset.c index c4f2867336..383a256c11 100644 --- a/pngset.c +++ b/pngset.c @@ -135,21 +135,27 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #ifdef PNG_cICP_SUPPORTED void PNGAPI -png_set_cICP(png_const_structrp png_ptr, - png_inforp info_ptr, png_byte colour_primaries, - png_byte transfer_function, png_byte matrix_coefficients, - png_byte video_full_range_flag) +png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag) { - png_debug1(1, "in %s storage function", "cICP"); + png_debug1(1, "in %s storage function", "cICP"); - if (png_ptr == NULL || info_ptr == NULL) - return; + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->cicp_colour_primaries = colour_primaries; + info_ptr->cicp_transfer_function = transfer_function; + info_ptr->cicp_matrix_coefficients = matrix_coefficients; + info_ptr->cicp_video_full_range_flag = video_full_range_flag; + + if (info_ptr->cicp_matrix_coefficients != 0) + { + png_warning(png_ptr, "Invalid cICP matrix coefficients"); + return; + } - info_ptr->cicp_colour_primaries = colour_primaries; - info_ptr->cicp_transfer_function = transfer_function; - info_ptr->cicp_matrix_coefficients = matrix_coefficients; - info_ptr->cicp_video_full_range_flag = video_full_range_flag; - info_ptr->valid |= PNG_INFO_cICP; + info_ptr->valid |= PNG_INFO_cICP; } #endif /* cICP */ diff --git a/pngtest.c b/pngtest.c index 60da60825c..dbbcf1e2c1 100644 --- a/pngtest.c +++ b/pngtest.c @@ -1206,21 +1206,19 @@ test_one_file(const char *inname, const char *outname) } #endif #ifdef PNG_cICP_SUPPORTED - { - png_byte colour_primaries; - png_byte transfer_function; - png_byte matrix_coefficients; - png_byte video_full_range_flag; - - if (png_get_cICP(read_ptr, read_info_ptr, &colour_primaries, - &transfer_function, &matrix_coefficients, - &video_full_range_flag) != 0) -#ifdef PNG_WRITE_cICP_SUPPORTED - png_set_cICP(write_ptr, write_info_ptr, colour_primaries, - transfer_function, matrix_coefficients, - video_full_range_flag); -#endif - } + { + png_byte colour_primaries; + png_byte transfer_function; + png_byte matrix_coefficients; + png_byte video_full_range_flag; + + if (png_get_cICP(read_ptr, read_info_ptr, + &colour_primaries, &transfer_function, + &matrix_coefficients, &video_full_range_flag) != 0) + png_set_cICP(write_ptr, write_info_ptr, + colour_primaries, transfer_function, + matrix_coefficients, video_full_range_flag); + } #endif #ifdef PNG_READ_eXIf_SUPPORTED { diff --git a/pngwrite.c b/pngwrite.c index 8b72304f4e..6e939cc0b3 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -237,13 +237,14 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) #endif #ifdef PNG_WRITE_cICP_SUPPORTED - if ((info_ptr->valid & PNG_INFO_cICP) != 0) - { - png_write_cICP(png_ptr, info_ptr->cicp_colour_primaries, - info_ptr->cicp_transfer_function, - info_ptr->cicp_matrix_coefficients, - info_ptr->cicp_video_full_range_flag); - } + if ((info_ptr->valid & PNG_INFO_cICP) != 0) + { + png_write_cICP(png_ptr, + info_ptr->cicp_colour_primaries, + info_ptr->cicp_transfer_function, + info_ptr->cicp_matrix_coefficients, + info_ptr->cicp_video_full_range_flag); + } #endif #ifdef PNG_WRITE_eXIf_SUPPORTED diff --git a/pngwutil.c b/pngwutil.c index 11f343daa5..8b2bf4e6d6 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1495,16 +1495,19 @@ png_write_cICP(png_structrp png_ptr, png_byte colour_primaries, png_byte transfer_function, png_byte matrix_coefficients, png_byte video_full_range_flag) { - png_debug(1, "in png_write_cICP"); + png_byte buf[4]; + + png_debug(1, "in png_write_cICP"); - png_write_chunk_header(png_ptr, png_cICP, 4); + png_write_chunk_header(png_ptr, png_cICP, 4); - png_write_chunk_data(png_ptr, &colour_primaries, 1); - png_write_chunk_data(png_ptr, &transfer_function, 1); - png_write_chunk_data(png_ptr, &matrix_coefficients, 1); - png_write_chunk_data(png_ptr, &video_full_range_flag, 1); + buf[0] = colour_primaries; + buf[1] = transfer_function; + buf[2] = matrix_coefficients; + buf[3] = video_full_range_flag; + png_write_chunk_data(png_ptr, buf, 4); - png_write_chunk_end(png_ptr); + png_write_chunk_end(png_ptr); } #endif diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa index 0a2345447b..83000d618c 100644 --- a/scripts/pnglibconf.dfa +++ b/scripts/pnglibconf.dfa @@ -846,7 +846,7 @@ setting IDAT_READ_SIZE default PNG_ZBUF_SIZE # Ancillary chunks chunk bKGD chunk cHRM enables COLORSPACE -chunk cICP +chunk cICP enables COLORSPACE, GAMMA chunk eXIf chunk gAMA enables GAMMA chunk hIST