summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libpng/pngrutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libpng/pngrutil.c')
-rw-r--r--src/3rdparty/libpng/pngrutil.c386
1 files changed, 204 insertions, 182 deletions
diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c
index 6c5c37526b..ee584a8c40 100644
--- a/src/3rdparty/libpng/pngrutil.c
+++ b/src/3rdparty/libpng/pngrutil.c
@@ -1,7 +1,7 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Last changed in libpng 1.6.19 [November 12, 2015]
* Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -89,7 +89,13 @@ png_get_int_32)(png_const_bytep buf)
return uval;
uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */
- return -(png_int_32)uval;
+ if ((uval & 0x80000000) == 0) /* no overflow */
+ return -(png_int_32)uval;
+ /* The following has to be safe; this function only gets called on PNG data
+ * and if we get here that data is invalid. 0 is the most safe value and
+ * if not then an attacker would surely just generate a PNG with 0 instead.
+ */
+ return 0;
}
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
@@ -98,7 +104,7 @@ png_get_uint_16)(png_const_bytep buf)
{
/* ANSI-C requires an int value to accomodate at least 16 bits so this
* works and allows the compiler not to worry about possible narrowing
- * on 32 bit systems. (Pre-ANSI systems did not make integers smaller
+ * on 32-bit systems. (Pre-ANSI systems did not make integers smaller
* than 16 bits either.)
*/
unsigned int val =
@@ -341,7 +347,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
* are minimal.
*/
(void)png_safecat(msg, (sizeof msg), 4, " using zstream");
-#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+#if PNG_RELEASE_BUILD
png_chunk_warning(png_ptr, msg);
png_ptr->zowner = 0;
#else
@@ -575,7 +581,7 @@ png_decompress_chunk(png_structrp png_ptr,
*/
png_alloc_size_t limit = PNG_SIZE_MAX;
-# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_malloc_max > 0 &&
png_ptr->user_chunk_malloc_max < limit)
limit = png_ptr->user_chunk_malloc_max;
@@ -670,7 +676,6 @@ png_decompress_chunk(png_structrp png_ptr,
* success)
*/
png_free(png_ptr, text);
- text = NULL;
/* This really is very benign, but it's still an error because
* the extra space may otherwise be used as a Trojan Horse.
@@ -867,7 +872,7 @@ void /* PRIVATE */
png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_color palette[PNG_MAX_PALETTE_LENGTH];
- int num, i;
+ int max_palette_length, num, i;
#ifdef PNG_POINTER_INDEXING_SUPPORTED
png_colorp pal_ptr;
#endif
@@ -928,6 +933,19 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
/* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
num = (int)length / 3;
+ /* If the palette has 256 or fewer entries but is too large for the bit
+ * depth, we don't issue an error, to preserve the behavior of previous
+ * libpng versions. We silently truncate the unused extra palette entries
+ * here.
+ */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ max_palette_length = (1 << png_ptr->bit_depth);
+ else
+ max_palette_length = PNG_MAX_PALETTE_LENGTH;
+
+ if (num > max_palette_length)
+ num = max_palette_length;
+
#ifdef PNG_POINTER_INDEXING_SUPPORTED
for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
{
@@ -960,7 +978,7 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#endif
{
- png_crc_finish(png_ptr, 0);
+ png_crc_finish(png_ptr, (int) length - num * 3);
}
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
@@ -1147,11 +1165,13 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
return;
for (i=0; i<truelen; ++i)
+ {
if (buf[i] == 0 || buf[i] > sample_depth)
{
png_chunk_benign_error(png_ptr, "invalid");
return;
}
+ }
if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
@@ -1462,10 +1482,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
finished = 1;
# ifdef PNG_sRGB_SUPPORTED
- /* Check for a match against sRGB */
- png_icc_set_sRGB(png_ptr,
- &png_ptr->colorspace, profile,
- png_ptr->zstream.adler);
+ /* Check for a match against sRGB */
+ png_icc_set_sRGB(png_ptr,
+ &png_ptr->colorspace, profile,
+ png_ptr->zstream.adler);
# endif
/* Steal the profile for info_ptr. */
@@ -1675,8 +1695,8 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
if (dl > max_dl)
{
- png_warning(png_ptr, "sPLT chunk too long");
- return;
+ png_warning(png_ptr, "sPLT chunk too long");
+ return;
}
new_palette.nentries = (png_int_32)(data_length / entry_size);
@@ -1686,8 +1706,8 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
if (new_palette.entries == NULL)
{
- png_warning(png_ptr, "sPLT chunk requires too much memory");
- return;
+ png_warning(png_ptr, "sPLT chunk requires too much memory");
+ return;
}
#ifdef PNG_POINTER_INDEXING_SUPPORTED
@@ -1817,7 +1837,8 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
return;
}
- if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH ||
+ if (length > (unsigned int) png_ptr->num_palette ||
+ length > (unsigned int) PNG_MAX_PALETTE_LENGTH ||
length == 0)
{
png_crc_finish(png_ptr, length);
@@ -1980,7 +2001,8 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
num = length / 2 ;
- if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH)
+ if (num != (unsigned int) png_ptr->num_palette ||
+ num > (unsigned int) PNG_MAX_PALETTE_LENGTH)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
@@ -2715,14 +2737,14 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
png_ptr->unknown_chunk.data = NULL;
}
-# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
- if (png_ptr->user_chunk_malloc_max > 0 &&
- png_ptr->user_chunk_malloc_max < limit)
- limit = png_ptr->user_chunk_malloc_max;
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
# elif PNG_USER_CHUNK_MALLOC_MAX > 0
- if (PNG_USER_CHUNK_MALLOC_MAX < limit)
- limit = PNG_USER_CHUNK_MALLOC_MAX;
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
# endif
if (length <= limit)
@@ -2785,7 +2807,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
*/
# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
- keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
+ keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
# endif
# endif
@@ -2794,153 +2816,153 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
*/
# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- /* The user callback takes precedence over the chunk keep value, but the
- * keep value is still required to validate a save of a critical chunk.
- */
- if (png_ptr->read_user_chunk_fn != NULL)
+ /* The user callback takes precedence over the chunk keep value, but the
+ * keep value is still required to validate a save of a critical chunk.
+ */
+ if (png_ptr->read_user_chunk_fn != NULL)
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) != 0)
{
- if (png_cache_unknown_chunk(png_ptr, length) != 0)
+ /* Callback to user unknown chunk handler */
+ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
+ &png_ptr->unknown_chunk);
+
+ /* ret is:
+ * negative: An error occurred; png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be discarded
+ * unless png_set_keep_unknown_chunks has been used to set
+ * a 'keep' behavior for this particular chunk, in which
+ * case that will be used. A critical chunk will cause an
+ * error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ */
+ if (ret < 0)
+ png_chunk_error(png_ptr, "error in user chunk");
+
+ else if (ret == 0)
{
- /* Callback to user unknown chunk handler */
- int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
- &png_ptr->unknown_chunk);
-
- /* ret is:
- * negative: An error occurred; png_chunk_error will be called.
- * zero: The chunk was not handled, the chunk will be discarded
- * unless png_set_keep_unknown_chunks has been used to set
- * a 'keep' behavior for this particular chunk, in which
- * case that will be used. A critical chunk will cause an
- * error at this point unless it is to be saved.
- * positive: The chunk was handled, libpng will ignore/discard it.
+ /* If the keep value is 'default' or 'never' override it, but
+ * still error out on critical chunks unless the keep value is
+ * 'always' While this is weird it is the behavior in 1.4.12.
+ * A possible improvement would be to obey the value set for the
+ * chunk, but this would be an API change that would probably
+ * damage some applications.
+ *
+ * The png_app_warning below catches the case that matters, where
+ * the application has not set specific save or ignore for this
+ * chunk or global save or ignore.
*/
- if (ret < 0)
- png_chunk_error(png_ptr, "error in user chunk");
-
- else if (ret == 0)
+ if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
{
- /* If the keep value is 'default' or 'never' override it, but
- * still error out on critical chunks unless the keep value is
- * 'always' While this is weird it is the behavior in 1.4.12.
- * A possible improvement would be to obey the value set for the
- * chunk, but this would be an API change that would probably
- * damage some applications.
- *
- * The png_app_warning below catches the case that matters, where
- * the application has not set specific save or ignore for this
- * chunk or global save or ignore.
- */
- if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
{
-# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
- if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
- {
- png_chunk_warning(png_ptr, "Saving unknown chunk:");
- png_app_warning(png_ptr,
- "forcing save of an unhandled chunk;"
- " please call png_set_keep_unknown_chunks");
- /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
- }
-# endif
- keep = PNG_HANDLE_CHUNK_IF_SAFE;
+ png_chunk_warning(png_ptr, "Saving unknown chunk:");
+ png_app_warning(png_ptr,
+ "forcing save of an unhandled chunk;"
+ " please call png_set_keep_unknown_chunks");
+ /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
}
- }
-
- else /* chunk was handled */
- {
- handled = 1;
- /* Critical chunks can be safely discarded at this point. */
- keep = PNG_HANDLE_CHUNK_NEVER;
+# endif
+ keep = PNG_HANDLE_CHUNK_IF_SAFE;
}
}
- else
- keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
+ else /* chunk was handled */
+ {
+ handled = 1;
+ /* Critical chunks can be safely discarded at this point. */
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
}
else
- /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
+ keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
+ }
+
+ else
+ /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
# endif /* READ_USER_CHUNKS */
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
- {
- /* keep is currently just the per-chunk setting, if there was no
- * setting change it to the global default now (not that this may
- * still be AS_DEFAULT) then obtain the cache of the chunk if required,
- * if not simply skip the chunk.
- */
- if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
- keep = png_ptr->unknown_default;
-
- if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
- PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
- {
- if (png_cache_unknown_chunk(png_ptr, length) == 0)
- keep = PNG_HANDLE_CHUNK_NEVER;
- }
+ {
+ /* keep is currently just the per-chunk setting, if there was no
+ * setting change it to the global default now (not that this may
+ * still be AS_DEFAULT) then obtain the cache of the chunk if required,
+ * if not simply skip the chunk.
+ */
+ if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
+ keep = png_ptr->unknown_default;
- else
- png_crc_finish(png_ptr, length);
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) == 0)
+ keep = PNG_HANDLE_CHUNK_NEVER;
}
+
+ else
+ png_crc_finish(png_ptr, length);
+ }
# else
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
# error no method to support READ_UNKNOWN_CHUNKS
# endif
- {
- /* If here there is no read callback pointer set and no support is
- * compiled in to just save the unknown chunks, so simply skip this
- * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
- * the app has erroneously asked for unknown chunk saving when there
- * is no support.
- */
- if (keep > PNG_HANDLE_CHUNK_NEVER)
- png_app_error(png_ptr, "no unknown chunk support available");
+ {
+ /* If here there is no read callback pointer set and no support is
+ * compiled in to just save the unknown chunks, so simply skip this
+ * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
+ * the app has erroneously asked for unknown chunk saving when there
+ * is no support.
+ */
+ if (keep > PNG_HANDLE_CHUNK_NEVER)
+ png_app_error(png_ptr, "no unknown chunk support available");
- png_crc_finish(png_ptr, length);
- }
+ png_crc_finish(png_ptr, length);
+ }
# endif
# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
- /* Now store the chunk in the chunk list if appropriate, and if the limits
- * permit it.
- */
- if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
- PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
- {
-# ifdef PNG_USER_LIMITS_SUPPORTED
- switch (png_ptr->user_chunk_cache_max)
- {
- case 2:
- png_ptr->user_chunk_cache_max = 1;
- png_chunk_benign_error(png_ptr, "no space in chunk cache");
- /* FALL THROUGH */
- case 1:
- /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
- * chunk being skipped, now there will be a hard error below.
- */
- break;
-
- default: /* not at limit */
- --(png_ptr->user_chunk_cache_max);
- /* FALL THROUGH */
- case 0: /* no limit */
-# endif /* USER_LIMITS */
- /* Here when the limit isn't reached or when limits are compiled
- * out; store the chunk.
- */
- png_set_unknown_chunks(png_ptr, info_ptr,
- &png_ptr->unknown_chunk, 1);
- handled = 1;
+ /* Now store the chunk in the chunk list if appropriate, and if the limits
+ * permit it.
+ */
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
# ifdef PNG_USER_LIMITS_SUPPORTED
- break;
- }
-# endif
+ switch (png_ptr->user_chunk_cache_max)
+ {
+ case 2:
+ png_ptr->user_chunk_cache_max = 1;
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
+ /* FALL THROUGH */
+ case 1:
+ /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
+ * chunk being skipped, now there will be a hard error below.
+ */
+ break;
+
+ default: /* not at limit */
+ --(png_ptr->user_chunk_cache_max);
+ /* FALL THROUGH */
+ case 0: /* no limit */
+# endif /* USER_LIMITS */
+ /* Here when the limit isn't reached or when limits are compiled
+ * out; store the chunk.
+ */
+ png_set_unknown_chunks(png_ptr, info_ptr,
+ &png_ptr->unknown_chunk, 1);
+ handled = 1;
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ break;
}
+# endif
+ }
# else /* no store support: the chunk must be handled by the user callback */
- PNG_UNUSED(info_ptr)
+ PNG_UNUSED(info_ptr)
# endif
/* Regardless of the error handling below the cached data (if any) can be
@@ -3042,13 +3064,13 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
end_byte = *end_ptr;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
- /* little-endian byte */
- end_mask = 0xff << end_mask;
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ /* little-endian byte */
+ end_mask = 0xff << end_mask;
- else /* big-endian byte */
+ else /* big-endian byte */
# endif
- end_mask = 0xff >> end_mask;
+ end_mask = 0xff >> end_mask;
/* end_mask is now the bits to *keep* from the destination row */
}
@@ -3206,12 +3228,12 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
png_uint_32 mask;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
- mask = MASK(pass, pixel_depth, display, 0);
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ mask = MASK(pass, pixel_depth, display, 0);
- else
+ else
# endif
- mask = MASK(pass, pixel_depth, display, 1);
+ mask = MASK(pass, pixel_depth, display, 1);
for (;;)
{
@@ -3812,15 +3834,15 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
p = b - c;
pc = a - c;
-# ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-# else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-# endif
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
/* Find the best predictor, the least of pa, pb, pc favoring the earlier
* ones in the case of a tie.
@@ -3867,15 +3889,15 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
p = b - c;
pc = a - c;
-# ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-# else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-# endif
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
if (pb < pa) pa = pb, a = b;
if (pc < pa) a = c;
@@ -4280,18 +4302,18 @@ png_read_start_row(png_structrp png_ptr)
#ifdef PNG_READ_EXPAND_16_SUPPORTED
if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
{
-# ifdef PNG_READ_EXPAND_SUPPORTED
- /* In fact it is an error if it isn't supported, but checking is
- * the safe way.
- */
- if ((png_ptr->transformations & PNG_EXPAND) != 0)
- {
- if (png_ptr->bit_depth < 16)
- max_pixel_depth *= 2;
- }
- else
-# endif
- png_ptr->transformations &= ~PNG_EXPAND_16;
+# ifdef PNG_READ_EXPAND_SUPPORTED
+ /* In fact it is an error if it isn't supported, but checking is
+ * the safe way.
+ */
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
+ {
+ if (png_ptr->bit_depth < 16)
+ max_pixel_depth *= 2;
+ }
+ else
+# endif
+ png_ptr->transformations &= ~PNG_EXPAND_16;
}
#endif