aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2015-05-05 01:05:40 -0700
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2015-10-18 05:24:16 +0200
commitda4953d3c413bd171cea5ed5a0b8138f2a704e8b (patch)
tree086c681311942e490007cb333b465f08dafd9f9d
parent1c1a497260ca86a5907469e7218e0faef22f3873 (diff)
downloadexternal_libpng-master.zip
external_libpng-master.tar.gz
external_libpng-master.tar.bz2
Backport of fix for CVE-2015-0973 to libpng 1.2.HEADmaster
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
-rw-r--r--png.c78
1 files 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 */