diff options
author | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2017-08-06 20:32:11 -0500 |
---|---|---|
committer | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2017-08-06 20:32:11 -0500 |
commit | 1a74f4f5f9f7f85e2ddb2d160d1aca15b10f7aa3 (patch) | |
tree | a4523635dac5b62348c159d844a0d0acf236736f | |
parent | 03f35f7156be2de65af83d86e07c1d08f041942d (diff) | |
download | libpng-1a74f4f5f9f7f85e2ddb2d160d1aca15b10f7aa3.tar.gz |
[lbpng14] 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).
-rw-r--r-- | ANNOUNCE | 5 | ||||
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | pngpread.c | 1 | ||||
-rw-r--r-- | pngpriv.h | 2 | ||||
-rw-r--r-- | pngrutil.c | 89 |
5 files changed, 82 insertions, 22 deletions
@@ -1,5 +1,5 @@ -Libpng 1.4.21beta01 - December 30, 2016 +Libpng 1.4.21beta01 - August 7, 2017 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. @@ -27,6 +27,9 @@ Other information: Changes since the last public release (1.4.20): version 1.4.21 [%RDATE%] + 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). Send comments/corrections/commendations to glennrp at users.sourceforge.net or to png-mng-implement at lists.sf.net (subscription required; visit @@ -3041,9 +3041,12 @@ version 1.4.20rc01 [December 27, 2016] version 1.4.20 [December 29, 2016] Fixed a potential null pointer dereference in png_set_text_2() (bug report - and patch by Patrick Keshishian). + and patch by Patrick Keshishian, CVE-2016-10087). -version 1.4.21 [December 30, 2016] +version 1.4.21 [August 7, 2017] + 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). Send comments/corrections/commendations to glennrp at users.sourceforge.net or to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/pngpread.c b/pngpread.c index d8e9104c1..4c844e916 100644 --- a/pngpread.c +++ b/pngpread.c @@ -203,6 +203,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) png_reset_crc(png_ptr); png_crc_read(png_ptr, png_ptr->chunk_name, 4); png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_check_chunk_length(png_ptr, png_ptr->push_length); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * libpng version 1.4.21beta01 - December 30, 2016 + * libpng version 1.4.20 - December 29, 2016 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/pngrutil.c b/pngrutil.c index 26ba00ee3..98ad5115e 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -119,6 +119,74 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: + * + * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + */ + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + int i; + png_uint_32 cn=chunk_name[0]<<24|chunk_name[1]<<16|chunk_name[2]<<8| + chunk_name[3]; + + png_debug(1, "in png_check_chunk_name"); + + for (i=1; i<=4; ++i) + { + int c = cn & 0xff; + + if (c < 65 || c > 122 || (c > 90 && c < 97)) + png_chunk_error(png_ptr, "invalid chunk type"); + + 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 != "IDAT") */ + if (png_ptr->chunk_name[0] != 73 || png_ptr->chunk_name[1] !=68 || + png_ptr->chunk_name[2] != 65 || png_ptr->chunk_name[3] !=84) + { +# 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"); + } +} /* Read the chunk header (length + type name). * Put the type name into png_ptr->chunk_name, and return the length. */ @@ -151,6 +219,9 @@ png_read_chunk_header(png_structp png_ptr) /* 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 /* It is unspecified how many I/O calls will be performed * during the serialization of the chunk data. @@ -2535,24 +2606,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif } -/* This function is called to verify that a chunk name is valid. - This function can't have the "critical chunk check" incorporated - into it, since in the future we will need to be able to call user - functions to handle unknown critical chunks after we check that - the chunk name itself is valid. */ - -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) - -void /* PRIVATE */ -png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) -{ - png_debug(1, "in png_check_chunk_name"); - if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || - isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) - { - png_chunk_error(png_ptr, "invalid chunk type"); - } -} /* Combines the row recently read in with the existing pixels in the row. This routine takes care of alpha and transparency if requested. |