From b66b4111f4bb1ac3d119ae042bef62318ead910d Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Fri, 28 Jun 2024 10:40:15 +0200 Subject: [PATCH] Limit total size of image instead of width and height individually. --- libheif/codecs/jpeg2000.h | 3 +-- libheif/codecs/mask_image.cc | 7 +++---- libheif/codecs/mask_image.h | 4 +--- libheif/codecs/uncompressed_image.cc | 9 ++++----- libheif/codecs/uncompressed_image.h | 3 +-- libheif/context.cc | 22 +++++++++------------- libheif/context.h | 9 +++++---- libheif/security_limits.h | 3 +-- 8 files changed, 25 insertions(+), 35 deletions(-) diff --git a/libheif/codecs/jpeg2000.h b/libheif/codecs/jpeg2000.h index e1b00486ab2..763433f170b 100644 --- a/libheif/codecs/jpeg2000.h +++ b/libheif/codecs/jpeg2000.h @@ -327,8 +327,7 @@ class Jpeg2000ImageCodec // static Error decode_jpeg2000_image(const std::shared_ptr& heif_file, // heif_item_id ID, // std::shared_ptr& img, -// uint32_t maximum_image_width_limit, -// uint32_t maximum_image_height_limit, +// uint32_t maximum_image_size_limit, // const std::vector& uncompressed_data); static Error encode_jpeg2000_image(const std::shared_ptr& heif_file, diff --git a/libheif/codecs/mask_image.cc b/libheif/codecs/mask_image.cc index fc977818b4f..065dc5318c3 100644 --- a/libheif/codecs/mask_image.cc +++ b/libheif/codecs/mask_image.cc @@ -58,8 +58,7 @@ Error Box_mskC::write(StreamWriter& writer) const Error MaskImageCodec::decode_mask_image(const std::shared_ptr& heif_file, heif_item_id ID, std::shared_ptr& img, - uint32_t maximum_image_width_limit, - uint32_t maximum_image_height_limit, + uint64_t maximum_image_size_limit, const std::vector& data) { std::vector> item_properties; @@ -77,10 +76,10 @@ Error MaskImageCodec::decode_mask_image(const std::shared_ptr& h width = ispe->get_width(); height = ispe->get_height(); - if (width >= maximum_image_width_limit || height >= maximum_image_height_limit) { + if (width > maximum_image_size_limit / height) { std::stringstream sstr; sstr << "Image size " << width << "x" << height << " exceeds the maximum image size " - << maximum_image_width_limit << "x" << maximum_image_height_limit << "\n"; + << maximum_image_size_limit << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, diff --git a/libheif/codecs/mask_image.h b/libheif/codecs/mask_image.h index a05842128db..427be55154f 100644 --- a/libheif/codecs/mask_image.h +++ b/libheif/codecs/mask_image.h @@ -73,8 +73,7 @@ class MaskImageCodec static Error decode_mask_image(const std::shared_ptr& heif_file, heif_item_id ID, std::shared_ptr& img, - uint32_t maximum_image_width_limit, - uint32_t maximum_image_height_limit, + uint64_t maximum_image_size_limit, const std::vector& data); static Error encode_mask_image(const std::shared_ptr& heif_file, const std::shared_ptr& src_image, @@ -84,4 +83,3 @@ class MaskImageCodec }; #endif //LIBHEIF_MASK_IMAGE_H - diff --git a/libheif/codecs/uncompressed_image.cc b/libheif/codecs/uncompressed_image.cc index c40b659ec9a..7fbbf9e1e13 100644 --- a/libheif/codecs/uncompressed_image.cc +++ b/libheif/codecs/uncompressed_image.cc @@ -552,7 +552,7 @@ class AbstractDecoder std::vector channelList; - void buildChannelList(std::shared_ptr& img) { + void buildChannelList(std::shared_ptr& img) { for (Box_uncC::Component component : m_uncC->get_components()) { ChannelListEntry entry = buildChannelListEntry(component, img); channelList.push_back(entry); @@ -853,8 +853,7 @@ static AbstractDecoder* makeDecoder(uint32_t width, uint32_t height, const std:: Error UncompressedImageCodec::decode_uncompressed_image(const std::shared_ptr& heif_file, heif_item_id ID, std::shared_ptr& img, - uint32_t maximum_image_width_limit, - uint32_t maximum_image_height_limit, + uint32_t maximum_image_size_limit, const std::vector& uncompressed_data) { if (uncompressed_data.empty()) { @@ -883,10 +882,10 @@ Error UncompressedImageCodec::decode_uncompressed_image(const std::shared_ptrget_width(); height = ispe->get_height(); - if (width >= maximum_image_width_limit || height >= maximum_image_height_limit) { + if (width > maximum_image_size_limit / height) { std::stringstream sstr; sstr << "Image size " << width << "x" << height << " exceeds the maximum image size " - << maximum_image_width_limit << "x" << maximum_image_height_limit << "\n"; + << maximum_image_size_limit << "\n"; printf("way too big\n"); return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, diff --git a/libheif/codecs/uncompressed_image.h b/libheif/codecs/uncompressed_image.h index 742f9a76f84..ff09aa4b489 100644 --- a/libheif/codecs/uncompressed_image.h +++ b/libheif/codecs/uncompressed_image.h @@ -40,8 +40,7 @@ class UncompressedImageCodec static Error decode_uncompressed_image(const std::shared_ptr& heif_file, heif_item_id ID, std::shared_ptr& img, - uint32_t maximum_image_width_limit, - uint32_t maximum_image_height_limit, + uint32_t maximum_image_size_limit, const std::vector& uncompressed_data); static Error encode_uncompressed_image(const std::shared_ptr& heif_file, diff --git a/libheif/context.cc b/libheif/context.cc index ef6edad258d..fb2730c4c18 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -399,8 +399,7 @@ void ImageOverlay::get_offset(size_t image_index, int32_t* x, int32_t* y) const HeifContext::HeifContext() { - m_maximum_image_width_limit = MAX_IMAGE_WIDTH; - m_maximum_image_height_limit = MAX_IMAGE_HEIGHT; + m_maximum_image_size_limit = MAX_IMAGE_SIZE; reset_to_empty_heif(); } @@ -596,11 +595,10 @@ Error HeifContext::interpret_heif_file() // --- check whether the image size is "too large" - if (width > m_maximum_image_width_limit || - height > m_maximum_image_height_limit) { + if (width > m_maximum_image_size_limit / height) { std::stringstream sstr; sstr << "Image size " << width << "x" << height << " exceeds the maximum image size " - << m_maximum_image_width_limit << "x" << m_maximum_image_height_limit << "\n"; + << m_maximum_image_size_limit << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -1503,8 +1501,7 @@ Error HeifContext::decode_image_planar(heif_item_id ID, error = UncompressedImageCodec::decode_uncompressed_image(m_heif_file, ID, img, - m_maximum_image_width_limit, - m_maximum_image_height_limit, + m_maximum_image_size_limit, data); if (error) { return error; @@ -1521,8 +1518,7 @@ Error HeifContext::decode_image_planar(heif_item_id ID, error = MaskImageCodec::decode_mask_image(m_heif_file, ID, img, - m_maximum_image_width_limit, - m_maximum_image_height_limit, + m_maximum_image_size_limit, data); if (error) { return error; @@ -1774,10 +1770,10 @@ Error HeifContext::decode_full_grid_image(heif_item_id ID, // --- generate image of full output size - if (w >= m_maximum_image_width_limit || h >= m_maximum_image_height_limit) { + if (w > m_maximum_image_size_limit / h) { std::stringstream sstr; sstr << "Image size " << w << "x" << h << " exceeds the maximum image size " - << m_maximum_image_width_limit << "x" << m_maximum_image_height_limit << "\n"; + << m_maximum_image_size_limit << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -2124,10 +2120,10 @@ Error HeifContext::decode_overlay_image(heif_item_id ID, uint32_t w = overlay.get_canvas_width(); uint32_t h = overlay.get_canvas_height(); - if (w >= m_maximum_image_width_limit || h >= m_maximum_image_height_limit) { + if (w > m_maximum_image_size_limit / h) { std::stringstream sstr; sstr << "Image size " << w << "x" << h << " exceeds the maximum image size " - << m_maximum_image_width_limit << "x" << m_maximum_image_height_limit << "\n"; + << m_maximum_image_size_limit << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, diff --git a/libheif/context.h b/libheif/context.h index 3928d539372..fb6c6e9042b 100644 --- a/libheif/context.h +++ b/libheif/context.h @@ -70,10 +70,11 @@ class HeifContext : public ErrorBuffer void set_max_decoding_threads(int max_threads) { m_max_decoding_threads = max_threads; } + // Sets the maximum size of both width and height of an image. The total limit + // of the image size (width * height) will be "maximum_size * maximum_size". void set_maximum_image_size_limit(int maximum_size) { - m_maximum_image_width_limit = maximum_size; - m_maximum_image_height_limit = maximum_size; + m_maximum_image_size_limit = int64_t(maximum_size) * maximum_size; } Error read(const std::shared_ptr& reader); @@ -522,8 +523,8 @@ class HeifContext : public ErrorBuffer int m_max_decoding_threads = 4; - uint32_t m_maximum_image_width_limit; - uint32_t m_maximum_image_height_limit; + // Maximum image size in pixels (width * height). + uint64_t m_maximum_image_size_limit; std::vector> m_region_items; diff --git a/libheif/security_limits.h b/libheif/security_limits.h index f1c177c0a15..302138127fe 100644 --- a/libheif/security_limits.h +++ b/libheif/security_limits.h @@ -31,8 +31,7 @@ static const int MAX_COLOR_PROFILE_SIZE = 100 * 1024 * 1024; // 100 MB // Artificial limit to avoid allocating too much memory. // 32768^2 = 1.5 GB as YUV-4:2:0 or 4 GB as RGB32 -static const int MAX_IMAGE_WIDTH = 32768; -static const int MAX_IMAGE_HEIGHT = 32768; +static const int64_t MAX_IMAGE_SIZE = 32768 * 32768; // Maximum nesting level of boxes in input files. // We put a limit on this to avoid unlimited stack usage by malicious input files.