From 921648a997e733eb63e18e835a9b98a5507da197 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 28 Mar 2012 23:36:12 -0500 Subject: [PATCH] [libpng16] Recognize known sRGB ICC profiles while reading; prefer writing the iCCP profile over writing the sRGB chunk, controlled by the PNG_sRGB_PROFILE_CHECKS option. --- ANNOUNCE | 10 +- CHANGES | 8 +- png.c | 198 ++++++++++++++++++++++++++++++++-- pngpriv.h | 9 +- pngread.c | 2 +- pngrutil.c | 189 ++++++++++++-------------------- pngwrite.c | 43 +++++--- pngwutil.c | 2 +- scripts/pnglibconf.dfa | 42 +++++++- scripts/pnglibconf.h.prebuilt | 4 +- 10 files changed, 347 insertions(+), 160 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 3fb484e2b..bef84dc7c 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.6.0beta20 - March 28, 2012 +Libpng 1.6.0beta20 - March 29, 2012 This is not intended to be a public release. It will be replaced within a few weeks by a public version or by another test version. @@ -339,12 +339,14 @@ Version 1.6.0beta19 [March 18,2012] Avoid the double gamma correction warning in the simplified API. This allows the --strict option to pass in the pngstest checks -Version 1.6.0beta20 [March 28, 2012] +Version 1.6.0beta20 [March 29, 2012] Changed chunk handler warnings into benign errors, incrementally load iCCP - Recognize known sRGB ICC profiles while reading and issue a warning about - it, if PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED is defined. Added checksum-icc.c to contrib/tools Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice. + Recognize known sRGB ICC profiles while reading; prefer writing the + iCCP profile over writing the sRGB chunk, controlled by the + PNG_sRGB_PROFILE_CHECKS option. + Revised png_set_text_2() to avoid potential memory corruption. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/CHANGES b/CHANGES index 97c7e2c3a..024c050ec 100644 --- a/CHANGES +++ b/CHANGES @@ -4090,12 +4090,14 @@ Version 1.6.0beta19 [March 18, 2012] Avoid the double gamma correction warning in the simplified API. This allows the --strict option to pass in the pngstest checks -Version 1.6.0beta20 [March 28, 2012] +Version 1.6.0beta20 [March 29, 2012] Changed chunk handler warnings into benign errors, incrementally load iCCP - Recognize known sRGB ICC profiles while reading and issue a warning about - it, if PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED is defined. Added checksum-icc.c to contrib/tools Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice. + Recognize known sRGB ICC profiles while reading; prefer writing the + iCCP profile over writing the sRGB chunk, controlled by the + PNG_sRGB_PROFILE_CHECKS option. + Revised png_set_text_2() to avoid potential memory corruption. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.c b/png.c index 24f4a17b9..e44e9391a 100644 --- a/png.c +++ b/png.c @@ -747,13 +747,13 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.0beta20 - March 21, 2012" PNG_STRING_NEWLINE \ + "libpng version 1.6.0beta20 - March 29, 2012" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.0beta20 - March 21, 2012\ + return "libpng version 1.6.0beta20 - March 29, 2012\ Copyright (c) 1998-2012 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -1974,17 +1974,192 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, return 1; } -void /* PRIVATE */ +#ifdef PNG_sRGB_SUPPORTED +/* Information about the known ICC sRGB profiles */ +static const struct +{ + png_uint_32 adler, crc, length; + png_uint_32 md5[4]; + png_uint_16 have_md5; + png_uint_16 intent; + +# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) +# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, date, length, fname)\ + { adler, crc, length, md5, intent }, + +} png_sRGB_checks[] = +{ + /* This data comes from contrib/tools/checksum-icc run on downloads of + * all four ICC sRGB profiles from www.color.org. + */ + /* adler32, crc32, MD5[4], intent, date, length, file-name */ + PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, + PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, + "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") + + /* ICC sRGB v2 perceptual no black-compensation: */ + PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, + PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, + "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") + + PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, + PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, + "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") + + /* ICC sRGB v4 perceptual */ + PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, + PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, + "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") + + /* The following profiles have no known MD5 checksum, if there is a match + * on the (empty) MD5 the other fields are used to attempt a match and + * a warning is produced. The first two of these profiles have a 'cprt' tag + * which suggests that they were also made by Hewlett Packard. + */ + PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, + "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") + + PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, + "1998/02/09 06:49:00", 3144, "sRGB Profile.icc") + + PNG_ICC_CHECKSUM(0x0398f3fcUL, 0xf29e526dUL, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, + "unknown", 3144, "HP-Microsoft sRGB v2 perceptual") +}; + +static int +png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, + png_const_bytep profile, uLong adler) +{ + /* The quick check is to verify just the MD5 signature and trust to the + * rest of the data. Because the profile has already been verified for + * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' + * field too, so if the profile has been editted with an intent not defined + * by sRGB (but maybe defined by a later ICC specification) the read of + * the profile will fail at that point. + */ + png_uint_32 length = 0; + png_uint_32 intent = 0x10000; /* invalid */ +#if PNG_sRGB_PROFILE_CHECKS > 1 + uLong crc = 0; /* the value for 0 length data */ +#endif + unsigned int i; + + for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) + { + if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && + png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && + png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && + png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) + { + /* This may be one of the old HP profiles without an MD5, in that + * case we can only use the length and Adler32 (note that these + * are not used by default if there is an MD5!) + */ +# if PNG_sRGB_PROFILE_CHECKS == 0 + if (png_sRGB_checks[i].have_md5) + return 1; +# endif + + /* Profile is unsigned or more checks have been configured in. */ + if (length == 0) + { + length = png_get_uint_32(profile); + intent = png_get_uint_32(profile+64); + } + + /* Length *and* intent must match */ + if (length == png_sRGB_checks[i].length && + intent == png_sRGB_checks[i].intent) + { + /* Now calculate the alder32 if not done already. */ + if (adler == 0) + { + adler = adler32(0, NULL, 0); + adler = adler32(adler, profile, length); + } + + if (adler == png_sRGB_checks[i].adler) + { + /* These basic checks suggest that the data has not been + * modified, but if the check level is more than 1 perform + * our own crc32 checksum on the data. + */ +# if PNG_sRGB_PROFILE_CHECKS > 1 + if (crc == 0) + { + crc = crc32(0, NULL, 0); + crc = crc32(crc, profile, length); + } + + /* So this check must pass for the 'return' below to happen. + */ + if (crc == png_sRGB_checks[i].crc) +# endif + { + /* Warn that this being done; this isn't even an error since + * the profile is perfectly valid, but it would be nice if + * people used the up-to-date ones. + */ + if (!png_sRGB_checks[i].have_md5) + { +# ifdef PNG_READ_SUPPORTED + if (png_ptr->mode & PNG_IS_READ_STRUCT) + png_chunk_warning(png_ptr, + "out-of-date sRGB profile with no signature"); + else +# endif + png_app_warning(png_ptr, + "out-of-date sRGB profile with no signature"); + } + + return 1; + } + } + } + +# if PNG_sRGB_PROFILE_CHECKS > 0 + /* The signature matched, but the profile had been changed in some + * way. This is an apparent violation of the ICC terms of use and, + * anyway, the rejection may be unexpected. + */ + if (png_sRGB_checks[i].have_md5) + png_benign_error(png_ptr, + "copyright violation: edited ICC profile ignored"); +# endif + } + } + + return 0; /* no match */ +} +#endif + +int /* PRIVATE */ png_icc_set_gAMA_and_cHRM(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_const_bytep profile, - int preferred) + uLong adler, int preferred) { - /* TODO: implement this! */ - PNG_UNUSED(png_ptr) - PNG_UNUSED(colorspace) - PNG_UNUSED(name) - PNG_UNUSED(profile) - PNG_UNUSED(preferred) +# ifdef PNG_sRGB_SUPPORTED + /* 1) Is this profile one of the known ICC sRGB profiles? If it is just + * set the sRGB information. + */ + if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler)) + return png_colorspace_set_sRGB(png_ptr, colorspace, + (int)/*already checked*/png_get_uint_32(profile+64), preferred); + + else +# endif + + /* 2) Attempt to extract the gAMA and cHRM information from non-sRGB + * profiles. + */ + { + /* TODO: implement this! */ + PNG_UNUSED(name) /* NYI */ + return 1; + } } int /* PRIVATE */ @@ -2000,7 +2175,8 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, profile)) { - png_icc_set_gAMA_and_cHRM(png_ptr, colorspace, name, profile, preferred); + png_icc_set_gAMA_and_cHRM(png_ptr, colorspace, name, profile, 0, + preferred); return 1; } diff --git a/pngpriv.h b/pngpriv.h index 7a61a2d10..71cb28fdb 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -1443,9 +1443,14 @@ PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_icc_set_gAMA_and_cHRM,( +PNG_INTERNAL_FUNCTION(int,png_icc_set_gAMA_and_cHRM,( png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_const_bytep profile, int preferred), PNG_EMPTY); + png_const_charp name, png_const_bytep profile, uLong adler, int preferred), + PNG_EMPTY); + /* 'adler' is the Adler32 checksum of the uncompressed profile data, it may + * be 0 to indicate that it is not available. It is used, if provided, as a + * fast check on the profile when checking to see if it is sRGB. + */ #endif /* iCCP */ #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED diff --git a/pngread.c b/pngread.c index ef348fa07..399604121 100644 --- a/pngread.c +++ b/pngread.c @@ -63,7 +63,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, /* In stable builds only warn if an application error can be completely * handled. */ -# if PNG_LIBPNG_BUILD_BASE_TYPE == PNG_LIBPNG_BUILD_STABLE +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; # endif # endif diff --git a/pngrutil.c b/pngrutil.c index b8a3d0091..efcac780d 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -338,7 +338,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner, int window_bits) * are minimal. */ (void)png_safecat(msg, sizeof msg, 4, " using zstream"); -# if PNG_LIBPNG_BUILD_BASE_TYPE == PNG_LIBPNG_BUILD_STABLE +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC png_chunk_warning(png_ptr, msg); png_ptr->zowner = 0; # else @@ -1314,72 +1314,12 @@ png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) #endif /* PNG_READ_sRGB_SUPPORTED */ #ifdef PNG_READ_iCCP_SUPPORTED -#ifdef PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED -int /* PRIVATE */ -png_compare_ICC_profile_with_sRGB(png_structrp png_ptr, png_bytep profile, - png_uint_32 length) -{ - /* See if it's a known sRGB profile. If it is, return intent; - * if not, return -1. - */ - - int - icheck; - - /* Known sRGB profiles: - * 0: not a known sRGB profile - * 1: HP-Microsoft sRGB v2 perceptual - * 2: ICC sRGB v4 perceptual - * 3: ICC sRGB v2 perceptual - * no black-compensation - */ - - typedef struct png_sRGB_check_struct - { - uLong crc; - uLong adler; - png_uint_32 check_len; - int intent; - } png_sRGB_check; - - png_sRGB_check check[3] = - { - { 0xf29e526dUL, 0x0398f3fcUL, 3144UL, 0 }, - { 0xbbef7812UL, 0x209c35d2UL, 60960UL, 0 }, - { 0x427ebb21UL, 0x4909e5e1UL, 3052UL, 0 } - }; - - if (png_ptr == NULL) - return -1; - - for (icheck = 2; icheck >= 0; icheck--) - { - if (length == check[icheck].check_len) - { - uLong profile_adler = adler32(1, profile, length); - - if (profile_adler == (uLong) check[icheck].adler) - { - uLong profile_crc = crc32(0, profile, length); - - if (profile_crc == (uLong) check[icheck].crc) - return check[icheck].intent; - - else - return -1; - } - } - } - - return -1; -} -#endif - void /* PRIVATE */ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* Note: this does not properly handle profiles that are > 64K under DOS */ { - png_const_charp errmsg; + png_const_charp errmsg = NULL; /* error message output, or no error */ + int finished = 0; /* crc checked */ png_debug(1, "in png_handle_iCCP"); @@ -1452,14 +1392,13 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_inflate_claim(png_ptr, png_iCCP, png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN ? 15 : 0) == Z_OK) { - int ret; Byte profile_header[132]; Byte local_buffer[PNG_INFLATE_BUF_SIZE]; png_alloc_size_t size = sizeof profile_header; png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); png_ptr->zstream.avail_in = read_length; - ret = png_inflate_read(png_ptr, local_buffer, + (void)png_inflate_read(png_ptr, local_buffer, sizeof local_buffer, &length, profile_header, &size, 0/*finish: don't, because the output is too small*/); @@ -1470,8 +1409,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) const png_uint_32 profile_length = png_get_uint_32(profile_header); - errmsg = NULL; /* flag to say error message output */ - if (png_icc_check_length(png_ptr, &png_ptr->colorspace, keyword, profile_length)) { @@ -1498,10 +1435,13 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) size = 12 * tag_count; - ret = png_inflate_read(png_ptr, local_buffer, + (void)png_inflate_read(png_ptr, local_buffer, sizeof local_buffer, &length, profile + (sizeof profile_header), &size, 0); + /* Still expect a a buffer error because we expect + * there to be some tag data! + */ if (size == 0) { if (png_icc_check_tag_table(png_ptr, @@ -1514,53 +1454,43 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) size = profile_length - (sizeof profile_header) - 12 * tag_count; - ret = png_inflate_read(png_ptr, local_buffer, + (void)png_inflate_read(png_ptr, local_buffer, sizeof local_buffer, &length, profile + (sizeof profile_header) + 12 * tag_count, &size, 1/*finish*/); - if (size == 0) + if (length > 0 && !(png_ptr->flags & + PNG_FLAG_BENIGN_ERRORS_WARN)) + errmsg = "extra compressed data"; + + /* But otherwise allow extra data: */ + else if (size == 0) { -#ifdef PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED - int - intent; -#endif + int ok; - if (ret != Z_STREAM_END) - png_chunk_warning(png_ptr, - png_ptr->zstream.msg); - - else if (length > 0) + if (length > 0) + { + /* This can be handled completely, so + * keep going. + */ png_chunk_warning(png_ptr, "extra compressed data"); + } - /* But, because we got the whole profile, - * assume it is ok. + png_crc_finish(png_ptr, length); + finished = 1; + + /* Set the gAMA and cHRM information, this + * checks for a known sRGB profile. The + * result is 0 on error. */ - png_ptr->zowner = 0; - - /* Yet the CRC should still be correct */ - if (png_crc_finish(png_ptr, length)) - return; - -#ifdef PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED - /* See if it's a known sRGB profile. */ - intent = - png_compare_ICC_profile_with_sRGB( - png_ptr, profile, profile_length); - - if (intent >= 0) - png_chunk_warning(png_ptr, - "describes sRGB\n"); -#endif - - /* Set the gAMA and cHRM information */ - png_icc_set_gAMA_and_cHRM(png_ptr, + ok = png_icc_set_gAMA_and_cHRM(png_ptr, &png_ptr->colorspace, keyword, profile, + png_ptr->zstream.adler, 0/*prefer explicit gAMA/cHRM*/); /* Steal the profile for info_ptr. */ - if (info_ptr != NULL) + if (ok && info_ptr != NULL) { png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); @@ -1568,33 +1498,50 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) info_ptr->iccp_name = png_voidcast(char*, png_malloc_base(png_ptr, keyword_length+1)); - if (info_ptr->iccp_name == NULL) + if (info_ptr->iccp_name != NULL) + { + memcpy(info_ptr->iccp_name, keyword, + keyword_length+1); + info_ptr->iccp_proflen = + profile_length; + info_ptr->iccp_profile = profile; + png_ptr->read_buffer = NULL; /*steal*/ + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; + } + + else { png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, - info_ptr); - png_chunk_benign_error(png_ptr, - "out of memory"); - return; + errmsg = "out of memory"; } - - memcpy(info_ptr->iccp_name, keyword, - keyword_length+1); - info_ptr->iccp_proflen = profile_length; - info_ptr->iccp_profile = profile; - png_ptr->read_buffer = NULL; /*steal*/ - info_ptr->free_me |= PNG_FREE_ICCP; - info_ptr->valid |= PNG_INFO_iCCP; - - png_colorspace_sync(png_ptr, info_ptr); } - return; + /* else the profile remains in the read + * buffer which gets reused for subsequent + * chunks. + */ + + if (info_ptr != NULL) + png_colorspace_sync(png_ptr, info_ptr); + + if (errmsg == NULL && ok) + { + png_ptr->zowner = 0; + return; + } + + /* else png_icc_set_gAMA_and_cHRM has + * already output an error. + */ } - else + else if (size > 0) errmsg = "truncated"; + + else + errmsg = png_ptr->zstream.msg; } /* else png_icc_check_tag_table output an error */ @@ -1637,7 +1584,9 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) errmsg = "too many profiles"; /* Failure: the reason is in 'errmsg' */ - png_crc_finish(png_ptr, length); + if (!finished) + png_crc_finish(png_ptr, length); + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; png_colorspace_sync(png_ptr, info_ptr); if (errmsg != NULL) /* else already output */ diff --git a/pngwrite.c b/pngwrite.c index 606ee5e3f..769da73ba 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -82,25 +82,32 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) #endif #ifdef PNG_COLORSPACE_SUPPORTED - /* Write only one of sRGB or an ICC profile, favour sRGB if the profile - * matches sRGB. + /* Write only one of sRGB or an ICC profile. If a profile was supplied + * and it matches one of the known sRGB ones issue a warning. */ +# ifdef PNG_WRITE_iCCP_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->valid & PNG_INFO_iCCP)) + { +# ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_app_warning(png_ptr, + "profile matches sRGB but writing iCCP instead"); +# endif + + png_write_iCCP(png_ptr, info_ptr->iccp_name, + info_ptr->iccp_profile); + } +# ifdef PNG_WRITE_sRGB_SUPPORTED + else +# endif +# endif + # ifdef PNG_WRITE_sRGB_SUPPORTED if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && (info_ptr->valid & PNG_INFO_sRGB)) png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); - -# ifdef PNG_WRITE_iCCP_SUPPORTED - else -# endif # endif /* WRITE_sRGB */ - -# ifdef PNG_WRITE_iCCP_SUPPORTED - if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && - (info_ptr->valid & PNG_INFO_iCCP)) - png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); -# endif #endif /* COLORSPACE */ #ifdef PNG_WRITE_sBIT_SUPPORTED @@ -527,6 +534,16 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, */ # ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + /* In stable builds only warn if an application error can be completely + * handled. + */ +# endif + + /* App warnings are warnings in release (or release candidate) builds but + * are errors during development. + */ +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; # endif if (png_ptr != NULL) diff --git a/pngwutil.c b/pngwutil.c index a6a659bc0..ca745f79d 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -325,7 +325,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, * are minimal. */ (void)png_safecat(msg, sizeof msg, 10, " using zstream"); -# if PNG_LIBPNG_BUILD_BASE_TYPE == PNG_LIBPNG_BUILD_STABLE +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC png_warning(png_ptr, msg); /* Attempt sane error recovery */ diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa index 3b7706595..7b1cc2360 100644 --- a/scripts/pnglibconf.dfa +++ b/scripts/pnglibconf.dfa @@ -478,7 +478,46 @@ option WRITE_TEXT requires WRITE_ANCILLARY_CHUNKS enables TEXT option GAMMA disabled option COLORSPACE enables GAMMA disabled +# When an ICC profile is read, or png_set, it will be checked for a match +# against known sRGB profiles if the sRGB handling is enabled. This +# setting controls how much work is done during the check: # +# 0: Just validate the profile MD5 signature if present, otherwise use +# the checks in option 1. +# +# 1: Additionally check the length, intent and adler32 checksum of the +# actual data. If enabled this will reject known profiles that have +# had the rendering intent in the header changed as well as other edits +# done without updating the checksum. See the discussion below. +# +# 2: Additionally checksum all the data using the ethernet CRC32 algorithm. +# This makes it more difficult to fake profiles and makes it less likely +# to get a false positive on profiles with no signature, but is probably +# just a waste of time since all currently approved ICC sRGB profiles have +# a secure MD5 signature. +# +# The rendering intent. An ICC profile stores an intended rendering intent, +# but does not include the value in the signature. The intent is documented +# as the intent that should be used when combining two profiles. The sRGB +# profile is intended, however, to be used with any of the four defined intents. +# For this reason the sRGB chunk includes an 'intent' to be used when displaying +# the image (intent is really a property of the image not the profile.) +# +# Unfortunately the iCCP chunk does not. It may therefore be that some +# applications modify the intent in profiles (including sRGB profiles) to work +# round this problem. Selecting an option other than option '0' will cause such +# modified profiles to be rejected. +# +# Security. The use of Adler32 and CRC32 checksums does not help significantly +# with any security issues. It is relatively easy to produce arbitrary profiles +# with the required checksums on current computer systems. Nevertheless +# security does not seem to be an issue because the only consequence of a false +# positive is a false assertion that the profile is an sRGB profile. This might +# be used to hide data from libpng using applications, but it doesn't seem +# possible to damage them. + +setting sRGB_PROFILE_CHECKS default 2 + # Artificially align memory - the code typically aligns to 8 byte # boundaries if this is switched on, it's a small waste of space # but can help (in theory) on some architectures. Only affects @@ -650,9 +689,6 @@ option CHECK_FOR_INVALID_INDEX enables WRITE_CHECK_FOR_INVALID_INDEX option READ_CHECK_FOR_INVALID_INDEX requires READ CHECK_FOR_INVALID_INDEX option WRITE_CHECK_FOR_INVALID_INDEX requires WRITE CHECK_FOR_INVALID_INDEX -# added at libpng-1.6.0 -option WARN_IF_iCCP_IS_sRGB requires READ iCCP - # Simplified API options (added at libpng-1.6.0) # Read: option SIMPLIFIED_READ requires SEQUENTIAL_READ READ_TRANSFORMS SETJMP diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt index e368b50c6..14452e21f 100644 --- a/scripts/pnglibconf.h.prebuilt +++ b/scripts/pnglibconf.h.prebuilt @@ -3,7 +3,7 @@ /* pnglibconf.h - library build configuration */ -/* Libpng 1.6.0beta20 - March 28, 2012 */ +/* Libpng 1.6.0beta20 - March 29, 2012 */ /* Copyright (c) 1998-2012 Glenn Randers-Pehrson */ @@ -33,6 +33,7 @@ #define PNG_QUANTIZE_GREEN_BITS 5 #define PNG_QUANTIZE_RED_BITS 5 #define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 #define PNG_WEIGHT_SHIFT 8 #define PNG_ZBUF_SIZE 8192 /* end of settings */ @@ -138,7 +139,6 @@ #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED #define PNG_SIMPLIFIED_WRITE_SUPPORTED -#define PNG_WARN_IF_iCCP_IS_sRGB_SUPPORTED #define PNG_sPLT_SUPPORTED #define PNG_sRGB_SUPPORTED #define PNG_STDIO_SUPPORTED