diff --git a/pngrutil.c b/pngrutil.c index 1de7427..72a8b5e 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -503,7 +503,7 @@ void /* PRIVATE */ png_handle_PLTE(png_structp png_ptr, png_infop 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 @@ -555,8 +555,21 @@ png_handle_PLTE(png_structp png_ptr, png_infop 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++) { @@ -589,7 +602,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop 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 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ @@ -1097,7 +1110,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* There should be at least one zero (the compression type byte) * following the separator, and we should be on it */ - if ( profile >= png_ptr->chunkdata + slength - 1) + if ( slength < 1 || profile >= png_ptr->chunkdata + slength - 1) { png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; @@ -1225,7 +1238,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++entry_start; /* A sample depth should follow the separator, and we should be on it */ - if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + if (slength < 2 || entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) { png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; @@ -1699,7 +1712,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* We need to have at least 12 bytes after the purpose string in order to get the parameter information. */ - if (endptr <= buf + 12) + if (slength < 12 || endptr <= buf + 12) { png_warning(png_ptr, "Invalid pCAL data"); png_free(png_ptr, png_ptr->chunkdata); @@ -2155,7 +2168,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Empty loop */ ; /* zTXt must have some text after the chunkdataword */ - if (text >= png_ptr->chunkdata + slength - 2) + if (slength < 2 || text >= png_ptr->chunkdata + slength - 2) { png_warning(png_ptr, "Truncated zTXt chunk"); png_free(png_ptr, png_ptr->chunkdata); @@ -2281,7 +2294,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) * keyword */ - if (lang >= png_ptr->chunkdata + slength - 3) + if (slength < 3 || lang >= png_ptr->chunkdata + slength - 3) { png_warning(png_ptr, "Truncated iTXt chunk"); png_free(png_ptr, png_ptr->chunkdata); diff --git a/pngset.c b/pngset.c index 7a47b1e..54ac931 100644 --- a/pngset.c +++ b/pngset.c @@ -446,12 +446,17 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp palette, int num_palette) { + png_uint_32 max_palette_length; + png_debug1(1, "in %s storage function", "PLTE"); if (png_ptr == NULL || info_ptr == NULL) return; - if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + + if (num_palette < 0 || num_palette > (int) max_palette_length) { if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_error(png_ptr, "Invalid palette length"); diff --git a/pngwutil.c b/pngwutil.c index c75f53e..80128d6 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -575,17 +575,20 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) #ifdef PNG_USE_LOCAL_ARRAYS PNG_PLTE; #endif - png_uint_32 i; + png_uint_32 max_palette_length, i; png_colorp pal_ptr; png_byte buf[3]; png_debug(1, "in png_write_PLTE"); + max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + if (( #ifdef PNG_MNG_FEATURES_SUPPORTED !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && #endif - num_pal == 0) || num_pal > 256) + num_pal == 0) || num_pal > max_palette_length) { if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {