diff --git a/ANNOUNCE b/ANNOUNCE index 60f3cf115..cb0d9f316 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -53,6 +53,8 @@ Version 1.7.0alpha01 [December 15, 2012] in png.h have been made more clear. Minor fixes to contrib/libtests/timepng.c and some of the png_*_tRNS logic, including more error detection in png_set_tRNS. + Clean up USER_LIMITS feature, removing members from png_struct when not + required. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/CHANGES b/CHANGES index c35450007..4c8042fa3 100644 --- a/CHANGES +++ b/CHANGES @@ -4338,6 +4338,8 @@ Version 1.7.0alpha01 [December 15, 2012] in png.h have been made more clear. Minor fixes to contrib/libtests/timepng.c and some of the png_*_tRNS logic, including more error detection in png_set_tRNS. + Clean up USER_LIMITS feature, removing members from png_struct when not + required. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.c b/png.c index 7dbd60c28..a75936a15 100644 --- a/png.c +++ b/png.c @@ -236,6 +236,23 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, */ memset(&create_struct, 0, (sizeof create_struct)); + /* These limits are only used on read at present, and if READ is not turned + * on neither will USER_LIMITS be. The width/height and chunk malloc limits + * are constants, so if they cannot be set they don't get defined in + * png_struct, the user_chunk_cache limits is a down-counter, when it reaches + * 1 no more chunks will be handled. 0 means unlimited, consequently the + * limit is 1 more than the number of chunks that will be handled. + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + create_struct.user_width_max = PNG_USER_WIDTH_MAX; + create_struct.user_height_max = PNG_USER_HEIGHT_MAX; + create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +# ifdef PNG_USER_LIMITS_SUPPORTED + /* Must exist even if the initial value is constant */ + create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + /* Added at libpng-1.2.6 */ # ifdef PNG_USER_LIMITS_SUPPORTED create_struct.user_width_max = PNG_USER_WIDTH_MAX; diff --git a/pngrutil.c b/pngrutil.c index 72d01bda1..172add2df 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -562,7 +562,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_SUPPOPRTED if (png_ptr->user_chunk_malloc_max > 0 && png_ptr->user_chunk_malloc_max < limit) limit = png_ptr->user_chunk_malloc_max; @@ -1582,7 +1582,8 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (--png_ptr->user_chunk_cache_max == 1) { - png_warning(png_ptr, "No space in chunk cache for sPLT"); + /* Warn the first time */ + png_chunk_benign_error(png_ptr, "chunk cache full"); png_crc_finish(png_ptr, length); return; } @@ -2372,7 +2373,7 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } @@ -2451,7 +2452,7 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } @@ -2560,7 +2561,7 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } @@ -2700,7 +2701,7 @@ 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 +# ifdef PNG_SET_USER_LIMITS_SUPPOPRTED if (png_ptr->user_chunk_malloc_max > 0 && png_ptr->user_chunk_malloc_max < limit) limit = png_ptr->user_chunk_malloc_max; @@ -2895,7 +2896,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, { case 2: png_ptr->user_chunk_cache_max = 1; - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); /* FALL THROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical diff --git a/pngset.c b/pngset.c index ee8d44e94..f52a20731 100644 --- a/pngset.c +++ b/pngset.c @@ -1524,24 +1524,19 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, * rejected by png_set_IHDR(). To accept any PNG datastream * regardless of dimensions, set both limits to 0x7ffffffL. */ - if (png_ptr == NULL) - return; - - png_ptr->user_width_max = user_width_max; - png_ptr->user_height_max = user_height_max; + if (png_ptr != NULL) + { + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; + } } /* This function was added to libpng 1.4.0 */ void PNGAPI png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) { -# ifdef PNG_READ_SUPPORTED - if (png_ptr) - png_ptr->user_chunk_cache_max = user_chunk_cache_max; -# else - PNG_UNUSED(png_ptr) - PNG_UNUSED(user_chunk_cache_max) -# endif + if (png_ptr != NULL) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; } /* This function was added to libpng 1.4.1 */ @@ -1549,13 +1544,8 @@ void PNGAPI png_set_chunk_malloc_max (png_structrp png_ptr, png_alloc_size_t user_chunk_malloc_max) { -# ifdef PNG_READ_SUPPORTED - if (png_ptr) - png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; -# else - PNG_UNUSED(png_ptr) - PNG_UNUSED(user_chunk_malloc_max) -# endif + if (png_ptr != NULL) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; } #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ diff --git a/pngstruct.h b/pngstruct.h index 87b8c1564..44d4751be 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -243,18 +243,21 @@ struct png_struct_def #endif #endif /* PNG_READ_SUPPORTED */ -#ifdef PNG_USER_LIMITS_SUPPORTED - /* The limits only affect read from libpng 1.7 */ - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; /* Maximum width on read */ + png_uint_32 user_height_max; /* Maximum height on read */ + /* Total memory that a single zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. This field is a counter + * - it is decremented as memory is allocated. */ png_alloc_size_t user_chunk_malloc_max; +#endif +#ifdef PNG_USER_LIMITS_SUPPORTED /* limit on total *number* of sPLT, text and unknown chunks that can be - * stored. 0 means unlimited. + * stored. 0 means unlimited. This field is a counter - it is decremented + * as chunks are encountered. */ png_uint_32 user_chunk_cache_max; - png_uint_32 user_width_max; - png_uint_32 user_height_max; #endif /* The progressive reader gets passed data and calls application handling diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa index 4cc620ec9..6f1882bee 100644 --- a/scripts/pnglibconf.dfa +++ b/scripts/pnglibconf.dfa @@ -276,40 +276,28 @@ option USER_MEM option IO_STATE -# This is only for PowerPC big-endian and 680x0 systems -# some testing, not enabled by default. -# NO LONGER USED - -#option READ_BIG_ENDIAN disabled - -# Allow users to control limits on what the READ code will -# read: - -# Added at libpng-1.2.43; adds limit fields to png_struct, -# allows some usages of these fields, from 1.7.0 only limits read +# Libpng limits: limit the size of images and data on read. +# +# If this option is disabled all the limit checking code will be disabled: option USER_LIMITS requires READ -# Added at libpng-1.2.6; adds setting APIs, allows additional -# usage of this field (UTSL) - -option SET_USER_LIMITS requires USER_LIMITS - -# Feature added at libpng-1.4.0, this flag added at 1.4.1 -option SET_USER_LIMITS enables SET_CHUNK_CACHE_LIMIT -# Feature added at libpng-1.4.1, this flag added at 1.4.1 - -option SET_USER_LIMITS enables SET_CHUNK_MALLOC_LIMIT - -# Libpng limits. -# -# If these settings are *not* set libpng will not limit the size of +# If the following settings are *not* set libpng will not limit the size of # images or the size of data in ancilliary chunks. This does lead to -# security issues if PNG files come from untrusted sources. +# security issues if PNG files come from untrusted sources. Settings have the +# following interpretations: +# +# USER_WIDTH_MAX: maximum width of an image that will be read +# USER_HEIGHT_MAX: maximum height +# USER_CHUNK_MALLOC_MAX: maximum in-memory (decompressed) size of a single chunk +# USER_CHUNK_CACHE_MAX: maximum number of chunks to be cached +# +# Only chunks that are variable in number are counted towards the +# USER_CHUNK_CACHE_MAX limit setting USER_WIDTH_MAX setting USER_HEIGHT_MAX -setting USER_CHUNK_CACHE_MAX setting USER_CHUNK_MALLOC_MAX +setting USER_CHUNK_CACHE_MAX # To default all these settings to values that are large but probably # safe turn the SAFE_LIMITS option on; this will cause the value in @@ -318,6 +306,10 @@ setting USER_CHUNK_MALLOC_MAX option SAFE_LIMITS enables USER_LIMITS disabled = SAFE_LIMITS SAFE_LIMITS +# If this option is enabled APIs to set the above limits at run time are added; +# without these the hardwired (compile time) limits will be used. +option SET_USER_LIMITS requires USER_LIMITS + # All of the following options relate to code capabilities for # processing image data before creating a PNG or after reading one. # You can remove these capabilities safely and still be PNG