From da4953d3c413bd171cea5ed5a0b8138f2a704e8b Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Tue, 5 May 2015 01:05:40 -0700 Subject: Backport of fix for CVE-2015-0973 to libpng 1.2. This code hasn't changed very much between 1.2 (klp-dev) and 1.5 / 1.6, except for some rearrangement of checks. bug: 19499430 Change-Id: I5cc708f8952c48296cab7cb37c1649c438d0ad86 --- png.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/png.c b/png.c index 3f3ae0b..c62b22f 100644 --- a/png.c +++ b/png.c @@ -926,6 +926,17 @@ png_check_cHRM_fixed(png_structp png_ptr, #endif /* PNG_CHECK_cHRM_SUPPORTED */ #endif /* PNG_cHRM_SUPPORTED */ +#ifdef __GNUC__ +/* This exists solely to work round a warning from GNU C. */ +static int /* PRIVATE */ +png_gt(size_t a, size_t b) +{ + return a > b; +} +#else +# define png_gt(a,b) ((a) > (b)) +#endif + void /* PRIVATE */ png_check_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, @@ -940,44 +951,67 @@ png_check_IHDR(png_structp png_ptr, png_warning(png_ptr, "Image width is zero in IHDR"); error = 1; } - - if (height == 0) + else if (width > PNG_UINT_31_MAX) { - png_warning(png_ptr, "Image height is zero in IHDR"); + png_warning(png_ptr, "Invalid image width in IHDR"); error = 1; } - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) -#else - if (width > PNG_USER_WIDTH_MAX) -#endif + else if (png_gt(width, + (PNG_SIZE_MAX >> 3) /* 8-byte RGBA pixels */ + - 48 /* big_row_buf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding width to multiple of 8 pix */ + - 8)) /* extra max_pixel_depth pad */ { - png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + /* The size of the row must be within the limits of this architecture. + * Because the read code can perform arbitrary transformations the + * maximum size is checked here. Because the code in png_read_start_row + * adds extra space "for safety's sake" in several places a conservative + * limit is used here. + * + * NOTE: it would be far better to check the size that is actually used, + * but the effect in the real world is minor and the changes are more + * extensive, therefore much more dangerous and much more difficult to + * write in a way that avoids compiler warnings. + */ + png_warning(png_ptr, "Image width is too large for this architecture"); error = 1; } - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) -#else - if (height > PNG_USER_HEIGHT_MAX) -#endif + else { - png_warning(png_ptr, "Image height exceeds user limit in IHDR"); - error = 1; +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max) +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } } - if (width > PNG_UINT_31_MAX) + if (height == 0) { - png_warning(png_ptr, "Invalid image width in IHDR"); + png_warning(png_ptr, "Image height is zero in IHDR"); error = 1; } - - if ( height > PNG_UINT_31_MAX) + else if (height > PNG_UINT_31_MAX) { png_warning(png_ptr, "Invalid image height in IHDR"); error = 1; } + else + { +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + } if ( width > (PNG_UINT_32_MAX >> 3) /* 8-byte RGBA pixels */ -- cgit v1.1