[devel] Improve IHDR checking and error reporting

Move redundant IHDR checking into new png_check_IHDR() in png.c
and report all errors found in the IHDR data.  Report problems
with width and height separately.
This commit is contained in:
Glenn Randers-Pehrson
2009-09-24 18:10:49 -05:00
parent 3243fea0ac
commit 134bbe416d
6 changed files with 200 additions and 120 deletions

150
png.c
View File

@@ -1,7 +1,7 @@
/* png.c - location for general purpose libpng functions
*
* Last changed in libpng 1.4.0 [September 23, 2009]
* Last changed in libpng 1.4.0 [September 24, 2009]
* Copyright (c) 1998-2009 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.)
@@ -546,13 +546,13 @@ png_get_copyright(png_structp png_ptr)
#else
#ifdef __STDC__
return ((png_charp) PNG_STRING_NEWLINE \
"libpng version x 1.4.0beta82 - September 23, 2009" PNG_STRING_NEWLINE \
"libpng version x 1.4.0beta82 - September 24, 2009" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2009 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE);
#else
return ((png_charp) "libpng version 1.4.0beta82 - September 23, 2009\
return ((png_charp) "libpng version 1.4.0beta82 - September 24, 2009\
Copyright (c) 1998-2009 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
@@ -766,4 +766,148 @@ png_check_cHRM_fixed(png_structp png_ptr,
}
#endif /* PNG_CHECK_cHRM_SUPPORTED */
#endif /* PNG_cHRM_SUPPORTED */
void /* PRIVATE */
png_check_IHDR(png_structp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
{
int error = 0;
/* Check for width and height valid values */
if (width == 0)
{
png_warning(png_ptr, "Image width is zero in IHDR");
error = 1;
}
if (height == 0)
{
png_warning(png_ptr, "Image height is zero in IHDR");
error = 1;
}
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX)
{
png_warning(png_ptr, "Image width exceeds user limit in IHDR");
error = 1;
}
if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX)
{
png_warning(png_ptr, "Image height exceeds user limit in IHDR");
error = 1;
}
#else
if (width > PNG_USER_WIDTH_MAX
{
png_warning(png_ptr, "Image width exceeds user limit in IHDR");
error = 1;
}
if (height > PNG_USER_HEIGHT_MAX)
{
png_warning(png_ptr, "Image height exceeds user limit in IHDR");
error = 1;
}
#endif
if (height > PNG_UINT_31_MAX)
{
png_warning(png_ptr, "Invalid image height in IHDR");
error = 1;
}
if ( height > PNG_UINT_31_MAX)
{
png_warning(png_ptr, "Invalid image width in IHDR");
error = 1;
}
if ( width > (PNG_UINT_32_MAX
>> 3) /* 8-byte RGBA pixels */
- 64 /* bigrowbuf hack */
- 1 /* filter byte */
- 7*8 /* rounding of width to multiple of 8 pixels */
- 8) /* extra max_pixel_depth pad */
png_warning(png_ptr, "Width is too large for libpng to process pixels");
/* Check other values */
if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
bit_depth != 8 && bit_depth != 16)
{
png_warning(png_ptr, "Invalid bit depth in IHDR");
error = 1;
}
if (color_type < 0 || color_type == 1 ||
color_type == 5 || color_type > 6)
{
png_warning(png_ptr, "Invalid color type in IHDR");
error = 1;
}
if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
((color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
{
png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
error = 1;
}
if (interlace_type >= PNG_INTERLACE_LAST)
{
png_warning(png_ptr, "Unknown interlace method in IHDR");
error = 1;
}
if (compression_type != PNG_COMPRESSION_TYPE_BASE)
{
png_warning(png_ptr, "Unknown compression method in IHDR");
error = 1;
}
#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Accept filter_method 64 (intrapixel differencing) only if
* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
* 2. Libpng did not read a PNG signature (this filter_method is only
* used in PNG datastreams that are embedded in MNG datastreams) and
* 3. The application called png_permit_mng_features with a mask that
* included PNG_FLAG_MNG_FILTER_64 and
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
png_ptr->mng_features_permitted)
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
if (filter_type != PNG_FILTER_TYPE_BASE)
{
if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
(filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
(color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
png_warning(png_ptr, "Unknown filter method in IHDR");
error = 1;
}
if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
png_warning(png_ptr, "Invalid filter method in IHDR");
#else
if (filter_type != PNG_FILTER_TYPE_BASE)
{
png_warning(png_ptr, "Unknown filter method in IHDR");
error = 1;
}
#endif
if (error == 1)
png_error(png_ptr, "Invalid IHDR data");
}
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */