From 68e090e7006c52b9822a13242517f976b6e7fe0f Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 29 Jan 2025 18:42:22 -0800 Subject: [PATCH] fix: `png_write_iCCP` check on profile length This is a regression of commit a8242dd9473a8da4d851623cf0b514a8ee4bee34 "PNGv3 colourspace precedence rules conformance". Previously, `png_write_iCCP` used the length from the first four bytes of the profile set by `png_set_iCCP`, rather than the actual data length recorded by `png_set_iCCP`. If the profile data were less than 4 bytes long, it would have caused a read-beyond-end-of-malloc error. This bug was in the libpng code even before the changes introduced in the above-mentioned commit, but it was inaccessible. It became accessible when we removed the pre-PNGv3 colour space checks in `png_set_iCCP`. Reported-by: Bob Friesenhahn Reviewed-by: Cosmin Truta Signed-off-by: John Bowler Signed-off-by: Cosmin Truta --- pngpriv.h | 8 ++++---- pngwrite.c | 2 +- pngwutil.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pngpriv.h b/pngpriv.h index 0be3efc9f..d514dff5c 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -1276,10 +1276,10 @@ PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr, #ifdef PNG_WRITE_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, - png_const_charp name, png_const_bytep profile), PNG_EMPTY); - /* The profile must have been previously validated for correctness, the - * length comes from the first four bytes. Only the base, deflate, - * compression is supported. + png_const_charp name, png_const_bytep profile, png_uint_32 proflen), + PNG_EMPTY); + /* Writes a previously 'set' profile. The profile argument is **not** + * compressed. */ #endif diff --git a/pngwrite.c b/pngwrite.c index 4d28a2fd0..b7aeff4ce 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -196,7 +196,7 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) if ((info_ptr->valid & PNG_INFO_iCCP) != 0) { png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); + info_ptr->iccp_profile, info_ptr->iccp_proflen); } # endif diff --git a/pngwutil.c b/pngwutil.c index c98475a08..be706afe6 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1132,10 +1132,9 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent) /* Write an iCCP chunk */ void /* PRIVATE */ png_write_iCCP(png_structrp png_ptr, png_const_charp name, - png_const_bytep profile) + png_const_bytep profile, png_uint_32 profile_len) { png_uint_32 name_len; - png_uint_32 profile_len; png_byte new_name[81]; /* 1 byte for the compression byte */ compression_state comp; png_uint_32 temp; @@ -1148,11 +1147,12 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name, if (profile == NULL) png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ - profile_len = png_get_uint_32(profile); - if (profile_len < 132) png_error(png_ptr, "ICC profile too short"); + if (png_get_uint_32(profile) != profile_len) + png_error(png_ptr, "Incorrect data in iCCP"); + temp = (png_uint_32) (*(profile+8)); if (temp > 3 && (profile_len & 0x03)) png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");