summaryrefslogtreecommitdiff
path: root/pngrutil.c
diff options
context:
space:
mode:
authorGlenn Randers-Pehrson <glennrp at users.sourceforge.net>2017-08-06 19:14:18 -0500
committerGlenn Randers-Pehrson <glennrp at users.sourceforge.net>2017-08-06 19:14:18 -0500
commit752c6c0042aa1de559139e79be59aa258efa70c1 (patch)
tree84232af7292ce49444a097bfba99022674d7eb7b /pngrutil.c
parentdc2b679f1346e37b370f5440c0dbd8579635831c (diff)
downloadlibpng-752c6c0042aa1de559139e79be59aa258efa70c1.tar.gz
[libpng15] Moved chunk-name and chunk-length checks into PNG_EXTERN private
png_check_chunk_name() and png_check_chunk_length() functions (Suggested by Max Stepin). Merged pngtest.c with libpng-1.6.32.
Diffstat (limited to 'pngrutil.c')
-rw-r--r--pngrutil.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/pngrutil.c b/pngrutil.c
index 9c3bf0557..8570c968d 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -171,6 +171,9 @@ png_read_chunk_header(png_structp png_ptr)
/* Put the chunk name into png_ptr->chunk_name. */
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
+ /* Check to see if chunk name is valid. */
+ png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
png_debug2(0, "Reading %lx chunk, length = %lu",
(unsigned long)png_ptr->chunk_name, (unsigned long)length);
@@ -178,8 +181,8 @@ png_read_chunk_header(png_structp png_ptr)
png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, buf + 4, 4);
- /* Check to see if chunk name is valid. */
- png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+ /* Check for too-large chunk length */
+ png_check_chunk_length(png_ptr, length);
#ifdef PNG_IO_STATE_SUPPORTED
png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
@@ -2803,17 +2806,55 @@ void /* PRIVATE */
png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
{
int i;
+ png_uint_32 cn=chunk_name;
png_debug(1, "in png_check_chunk_name");
for (i=1; i<=4; ++i)
{
- int c = chunk_name & 0xff;
+ int c = cn & 0xff;
if (c < 65 || c > 122 || (c > 90 && c < 97))
png_chunk_error(png_ptr, "invalid chunk type");
- chunk_name >>= 8;
+ cn >>= 8;
+ }
+}
+
+void /* PRIVATE */
+png_check_chunk_length(png_structp png_ptr, png_uint_32 length)
+{
+ png_uint_32 limit = PNG_UINT_31_MAX;
+
+ if (png_ptr->chunk_name != png_IDAT)
+ {
+# 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;
+# endif
+ }
+ else
+ {
+ size_t row_factor =
+ (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1)
+ + 1 + (png_ptr->interlaced? 6: 0));
+ if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
+ limit=PNG_UINT_31_MAX;
+ else
+ limit = png_ptr->height * row_factor;
+ limit += 6 + 5*(limit/32566+1); /* zlib+deflate overhead */
+ limit=limit < PNG_UINT_31_MAX? limit : PNG_UINT_31_MAX;
+ }
+
+ if (length > limit)
+ {
+ png_debug2(0," length = %lu, limit = %lu",
+ (unsigned long)length,(unsigned long)limit);
+ png_chunk_error(png_ptr, "chunk data is too large");
}
}