From 664d4b82ac5156488b7e437d4cc54a3ef94d2811 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 23 Aug 2017 01:05:02 -0700 Subject: Reject oversized iCCP profile length in libpng. cherry-pick of https://github.com/glennrp/libpng/commit/92a7c79db2c962d04006b35e2603ba9d5ce75541 BUG=chromium:729673 Change-Id: I907b4920ed6d276a075a30269be1744aff678069 Reviewed-on: https://pdfium-review.googlesource.com/11690 Commit-Queue: Lei Zhang Reviewed-by: dsinclair --- third_party/libpng16/0004-invalid-icc.patch | 81 +++++++++++++++++++++++++++++ third_party/libpng16/README.pdfium | 1 + third_party/libpng16/png.c | 40 ++++++++++++-- third_party/libpng16/pngpriv.h | 2 + 4 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 third_party/libpng16/0004-invalid-icc.patch diff --git a/third_party/libpng16/0004-invalid-icc.patch b/third_party/libpng16/0004-invalid-icc.patch new file mode 100644 index 0000000000..0052c8e0f7 --- /dev/null +++ b/third_party/libpng16/0004-invalid-icc.patch @@ -0,0 +1,81 @@ +diff --git a/png.c b/png.c +index 35e14f63d..01d8d9bae 100644 +--- a/png.c ++++ b/png.c +@@ -1931,8 +1931,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, + static const png_byte D50_nCIEXYZ[12] = + { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; + +-int /* PRIVATE */ +-png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, ++static int /* bool */ ++icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) + { + if (profile_length < 132) +@@ -1942,6 +1942,40 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + return 1; + } + ++#ifdef PNG_READ_iCCP_SUPPORTED ++int /* PRIVATE */ ++png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, ++ png_const_charp name, png_uint_32 profile_length) ++{ ++ if (!icc_check_length(png_ptr, colorspace, name, profile_length)) ++ return 0; ++ ++ /* This needs to be here because the 'normal' check is in ++ * png_decompress_chunk, yet this happens after the attempt to ++ * png_malloc_base the required data. We only need this on read; on write ++ * the caller supplies the profile buffer so libpng doesn't allocate it. See ++ * the call to icc_check_length below (the write case). ++ */ ++# ifdef PNG_SET_USER_LIMITS_SUPPORTED ++ else if (png_ptr->user_chunk_malloc_max > 0 && ++ png_ptr->user_chunk_malloc_max < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds application limits"); ++# elif PNG_USER_CHUNK_MALLOC_MAX > 0 ++ else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds libpng limits"); ++# else /* !SET_USER_LIMITS */ ++ /* This will get compiled out on all 32-bit and better systems. */ ++ else if (PNG_SIZE_MAX < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds system limits"); ++# endif /* !SET_USER_LIMITS */ ++ ++ return 1; ++} ++#endif /* READ_iCCP */ ++ + int /* PRIVATE */ + png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, +@@ -2379,7 +2413,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, + if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) + return 0; + +- if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && ++ if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, + color_type) != 0 && + png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, +diff --git a/pngpriv.h b/pngpriv.h +index 9ea023fea..633671352 100644 +--- a/pngpriv.h ++++ b/pngpriv.h +@@ -1541,9 +1541,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, + /* The 'name' is used for information only */ + + /* Routines for checking parts of an ICC profile. */ ++#ifdef PNG_READ_iCCP_SUPPORTED + PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length), PNG_EMPTY); ++#endif /* READ_iCCP */ + PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, diff --git a/third_party/libpng16/README.pdfium b/third_party/libpng16/README.pdfium index 47af52f8b6..faa59590c8 100644 --- a/third_party/libpng16/README.pdfium +++ b/third_party/libpng16/README.pdfium @@ -18,3 +18,4 @@ pngprefix.h: manually-created redefinitions to avoid conflicts with Chromium. 0000-build-config.patch: Local build configuration changes. 0002-static-png-gt.patch: Unconditionally use static png_gt() in png.c to avoid compilation warning. 0003-check-errors-in-set-pcal.patch: Backported github.com/glennrp/libpng/pull/135 +0004-invalid-icc.patch: Fix for large allocation for invalid ICC https://github.com/glennrp/libpng/commit/92a7c79db2c962d04006b35e2603ba9d5ce75541 diff --git a/third_party/libpng16/png.c b/third_party/libpng16/png.c index 35e14f63d8..01d8d9bae6 100644 --- a/third_party/libpng16/png.c +++ b/third_party/libpng16/png.c @@ -1931,8 +1931,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, static const png_byte D50_nCIEXYZ[12] = { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; -int /* PRIVATE */ -png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, +static int /* bool */ +icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length) { if (profile_length < 132) @@ -1942,6 +1942,40 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, return 1; } +#ifdef PNG_READ_iCCP_SUPPORTED +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (!icc_check_length(png_ptr, colorspace, name, profile_length)) + return 0; + + /* This needs to be here because the 'normal' check is in + * png_decompress_chunk, yet this happens after the attempt to + * png_malloc_base the required data. We only need this on read; on write + * the caller supplies the profile buffer so libpng doesn't allocate it. See + * the call to icc_check_length below (the write case). + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + else if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds application limits"); +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds libpng limits"); +# else /* !SET_USER_LIMITS */ + /* This will get compiled out on all 32-bit and better systems. */ + else if (PNG_SIZE_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds system limits"); +# endif /* !SET_USER_LIMITS */ + + return 1; +} +#endif /* READ_iCCP */ + int /* PRIVATE */ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, @@ -2379,7 +2413,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; - if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, color_type) != 0 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, diff --git a/third_party/libpng16/pngpriv.h b/third_party/libpng16/pngpriv.h index 9ea023fea7..6336713526 100644 --- a/third_party/libpng16/pngpriv.h +++ b/third_party/libpng16/pngpriv.h @@ -1541,9 +1541,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, /* The 'name' is used for information only */ /* Routines for checking parts of an ICC profile. */ +#ifdef PNG_READ_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length), PNG_EMPTY); +#endif /* READ_iCCP */ PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, -- cgit v1.2.3