[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.
diff --git a/ANNOUNCE b/ANNOUNCE
index 3fb484e..bef84dc 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 @@
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 97c7e2c..024c050 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4090,12 +4090,14 @@
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 24f4a17..e44e939 100644
--- a/png.c
+++ b/png.c
@@ -747,13 +747,13 @@
#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 @@
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_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 7a61a2d..71cb28f 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -1443,9 +1443,14 @@
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 ef348fa..3996041 100644
--- a/pngread.c
+++ b/pngread.c
@@ -63,7 +63,7 @@
/* 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 b8a3d00..efcac78 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -338,7 +338,7 @@
* 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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 606ee5e..769da73 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -82,25 +82,32 @@
#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 @@
*/
# 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 a6a659b..ca745f7 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -325,7 +325,7 @@
* 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 3b77065..7b1cc23 100644
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -478,7 +478,46 @@
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 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 e368b50..14452e2 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