From 2374ade0a24f107d5de8fb6bd5f9ceef04b6c510 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Mon, 7 Oct 2024 12:48:05 +0200 Subject: [PATCH] use context-local security limits that can be overwritten by client --- libheif/CMakeLists.txt | 1 + libheif/api/libheif/heif.cc | 35 +++++- libheif/api/libheif/heif.h | 34 ++++++ libheif/api/libheif/heif_experimental.h | 2 - libheif/box.cc | 137 ++++++++++++----------- libheif/box.h | 84 +++++++------- libheif/codecs/avc_boxes.cc | 2 +- libheif/codecs/avc_boxes.h | 2 +- libheif/codecs/avif_boxes.cc | 6 +- libheif/codecs/avif_boxes.h | 6 +- libheif/codecs/hevc_boxes.cc | 2 +- libheif/codecs/hevc_boxes.h | 2 +- libheif/codecs/jpeg2000_boxes.cc | 12 +- libheif/codecs/jpeg2000_boxes.h | 10 +- libheif/codecs/jpeg_boxes.cc | 5 +- libheif/codecs/jpeg_boxes.h | 2 +- libheif/codecs/uncompressed/unc_boxes.cc | 15 +-- libheif/codecs/uncompressed/unc_boxes.h | 10 +- libheif/codecs/vvc_boxes.cc | 2 +- libheif/codecs/vvc_boxes.h | 2 +- libheif/context.cc | 43 ++++++- libheif/context.h | 16 +-- libheif/file.cc | 24 ++-- libheif/file.h | 6 + libheif/file_layout.cc | 6 +- libheif/file_layout.h | 2 +- libheif/image-items/mask_image.cc | 2 +- libheif/image-items/mask_image.h | 2 +- libheif/image-items/tild.cc | 17 ++- libheif/image-items/tild.h | 4 +- libheif/nclx.cc | 7 +- libheif/nclx.h | 2 +- libheif/pixelimage.cc | 2 +- libheif/security_limits.cc | 42 +++++++ libheif/security_limits.h | 17 +-- tests/avc_box.cc | 2 +- tests/file_layout.cc | 2 +- tests/idat.cc | 2 +- tests/uncompressed_box.cc | 24 ++-- 39 files changed, 376 insertions(+), 217 deletions(-) create mode 100644 libheif/security_limits.cc diff --git a/libheif/CMakeLists.txt b/libheif/CMakeLists.txt index 00117daed5..a5abcaac9e 100644 --- a/libheif/CMakeLists.txt +++ b/libheif/CMakeLists.txt @@ -36,6 +36,7 @@ set(libheif_sources nclx.cc nclx.h plugin_registry.h + security_limits.cc security_limits.h init.cc init.h diff --git a/libheif/api/libheif/heif.cc b/libheif/api/libheif/heif.cc index f34e63cd95..ade20d9917 100644 --- a/libheif/api/libheif/heif.cc +++ b/libheif/api/libheif/heif.cc @@ -19,6 +19,7 @@ */ #include "heif_plugin.h" +#include "security_limits.h" #include "region.h" #include "common_utils.h" #include @@ -323,7 +324,7 @@ int heif_has_compatible_brand(const uint8_t* data, int len, const char* brand_fo BitstreamRange range(stream, len); std::shared_ptr box; - Error err = Box::read(range, &box); + Error err = Box::read(range, &box, heif_get_global_security_limits()); if (err) { if (err.sub_error_code == heif_suberror_End_of_data) { return -1; @@ -355,7 +356,7 @@ struct heif_error heif_list_compatible_brands(const uint8_t* data, int len, heif BitstreamRange range(stream, len); std::shared_ptr box; - Error err = Box::read(range, &box); + Error err = Box::read(range, &box, heif_get_global_security_limits()); if (err) { if (err.sub_error_code == heif_suberror_End_of_data) { return {err.error_code, err.sub_error_code, "insufficient input data"}; @@ -479,6 +480,36 @@ const char* heif_get_file_mime_type(const uint8_t* data, int len) } +const struct heif_security_limits* heif_get_global_security_limits() +{ + return &global_security_limits; +} + + +struct heif_security_limits* heif_context_get_security_limits(const struct heif_context* ctx) +{ + if (!ctx) { + return nullptr; + } + + return ctx->context->get_security_limits(); +} + + +struct heif_error heif_context_set_security_limits(struct heif_context* ctx, const struct heif_security_limits* limits) +{ + if (ctx==nullptr || limits==nullptr) { + return {heif_error_Usage_error, + heif_suberror_Null_pointer_argument}; + } + + ctx->context->set_security_limits(limits); + + return heif_error_ok; +} + + + heif_context* heif_context_alloc() { load_plugins_if_not_initialized_yet(); diff --git a/libheif/api/libheif/heif.h b/libheif/api/libheif/heif.h index 60efef75c9..c766c8f2f7 100644 --- a/libheif/api/libheif/heif.h +++ b/libheif/api/libheif/heif.h @@ -933,6 +933,7 @@ LIBHEIF_API void heif_context_free(struct heif_context*); + struct heif_reading_options; enum heif_reader_grow_status @@ -1100,6 +1101,39 @@ LIBHEIF_API void heif_context_set_max_decoding_threads(struct heif_context* ctx, int max_threads); +// --- security limits + +// If you set a limit to 0, the limit is disabled. +struct heif_security_limits { + uint8_t version; + + // --- version 1 + + // Artificial limit to avoid allocating too much memory. + // 32768^2 = 1.5 GB as YUV-4:2:0 or 4 GB as RGB32 + uint64_t max_image_size_pixels ; + uint32_t max_bayer_pattern_pixels; + + uint32_t max_iref_references; + uint32_t max_iloc_items; + uint32_t max_iloc_extents_per_item; + uint32_t max_children_per_box; + uint64_t max_number_of_tiles; + + uint32_t max_color_profile_size; + uint64_t max_memory_block_size; +}; + +LIBHEIF_API +const struct heif_security_limits* heif_get_global_security_limits(); + +LIBHEIF_API +struct heif_security_limits* heif_context_get_security_limits(const struct heif_context*); + +LIBHEIF_API +struct heif_error heif_context_set_security_limits(struct heif_context*, const struct heif_security_limits*); + + // ========================= heif_image_handle ========================= // An heif_image_handle is a handle to a logical image in the HEIF file. diff --git a/libheif/api/libheif/heif_experimental.h b/libheif/api/libheif/heif_experimental.h index 35da331ce0..01b75aa877 100644 --- a/libheif/api/libheif/heif_experimental.h +++ b/libheif/api/libheif/heif_experimental.h @@ -334,8 +334,6 @@ struct heif_complex64* heif_image_get_channel_complex64(struct heif_image*, enum heif_channel channel, uint32_t* out_stride); - - #ifdef __cplusplus } #endif diff --git a/libheif/box.cc b/libheif/box.cc index 9cf7df7373..a380c00fc6 100644 --- a/libheif/box.cc +++ b/libheif/box.cc @@ -397,7 +397,7 @@ std::string BoxHeader::dump(Indent& indent) const } -Error Box::parse(BitstreamRange& range) +Error Box::parse(BitstreamRange& range, const heif_security_limits* limits) { // skip box @@ -439,7 +439,7 @@ Error FullBox::parse_full_box_header(BitstreamRange& range) } -Error Box::read(BitstreamRange& range, std::shared_ptr* result) +Error Box::read(BitstreamRange& range, std::shared_ptr* result, const heif_security_limits* limits) { BoxHeader hdr; Error err = hdr.parse_header(range); @@ -759,7 +759,7 @@ Error Box::read(BitstreamRange& range, std::shared_ptr* result) box_size_without_header, &range); - err = box->parse(boxrange); + err = box->parse(boxrange, limits); boxrange.skip_to_end_of_box(); if (err == Error::Ok) { @@ -845,20 +845,21 @@ bool Box::equal(const std::shared_ptr& box1, const std::shared_ptr& bo } -Error Box::read_children(BitstreamRange& range, int max_number) +Error Box::read_children(BitstreamRange& range, int max_number, const heif_security_limits* limits) { int count = 0; while (!range.eof() && !range.error()) { std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, limits); if (error != Error::Ok && (!box || box->get_parse_error_fatality() == parse_error_fatality::fatal)) { return error; } - if (m_children.size() > MAX_CHILDREN_PER_BOX) { + auto max_children_per_box = limits->max_children_per_box; + if (max_children_per_box && m_children.size() > max_children_per_box) { std::stringstream sstr; - sstr << "Maximum number of child boxes " << MAX_CHILDREN_PER_BOX << " exceeded."; + sstr << "Maximum number of child boxes " << max_children_per_box << " exceeded."; // Sanity check. return Error(heif_error_Memory_allocation_error, @@ -935,7 +936,7 @@ void Box::derive_box_version_recursive() } -Error Box_other::parse(BitstreamRange& range) +Error Box_other::parse(BitstreamRange& range, const heif_security_limits* limits) { if (has_fixed_box_size()) { size_t len; @@ -1027,7 +1028,7 @@ parse_error_fatality Box_Error::get_parse_error_fatality() const } -Error Box_ftyp::parse(BitstreamRange& range) +Error Box_ftyp::parse(BitstreamRange& range, const heif_security_limits* limits) { m_major_brand = range.read32(); m_minor_version = range.read32(); @@ -1107,7 +1108,7 @@ Error Box_ftyp::write(StreamWriter& writer) const } -Error Box_meta::parse(BitstreamRange& range) +Error Box_meta::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -1125,7 +1126,7 @@ Error Box_meta::parse(BitstreamRange& range) } */ - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } @@ -1150,7 +1151,7 @@ Error FullBox::unsupported_version_error(const char* box) const } -Error Box_hdlr::parse(BitstreamRange& range) +Error Box_hdlr::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -1202,7 +1203,7 @@ Error Box_hdlr::write(StreamWriter& writer) const } -Error Box_pitm::parse(BitstreamRange& range) +Error Box_pitm::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -1261,7 +1262,7 @@ Error Box_pitm::write(StreamWriter& writer) const } -Error Box_iloc::parse(BitstreamRange& range) +Error Box_iloc::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -1291,10 +1292,11 @@ Error Box_iloc::parse(BitstreamRange& range) } // Sanity check. - if (item_count > MAX_ILOC_ITEMS) { + auto max_iloc_items = limits->max_iloc_items; + if (max_iloc_items && item_count > max_iloc_items) { std::stringstream sstr; sstr << "iloc box contains " << item_count << " items, which exceeds the security limit of " - << MAX_ILOC_ITEMS << " items."; + << max_iloc_items << " items."; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -1327,13 +1329,14 @@ Error Box_iloc::parse(BitstreamRange& range) item.base_offset |= range.read32(); } - int extent_count = range.read16(); + uint16_t extent_count = range.read16(); // Sanity check. - if (extent_count > MAX_ILOC_EXTENTS_PER_ITEM) { + auto max_iloc_extents = limits->max_iloc_extents_per_item; + if (max_iloc_extents && extent_count > max_iloc_extents) { std::stringstream sstr; sstr << "Number of extents in iloc box (" << extent_count << ") exceeds security limit (" - << MAX_ILOC_EXTENTS_PER_ITEM << ")\n"; + << max_iloc_extents << ")\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -1451,9 +1454,10 @@ std::string Box_iloc::dump(Indent& indent) const Error Box_iloc::read_data(heif_item_id item, const std::shared_ptr& istr, const std::shared_ptr& idat, - std::vector* dest) const + std::vector* dest, + const heif_security_limits* limits) const { - return read_data(item, istr, idat, dest, 0, std::numeric_limits::max()); + return read_data(item, istr, idat, dest, 0, std::numeric_limits::max(), limits); } @@ -1461,7 +1465,8 @@ Error Box_iloc::read_data(heif_item_id item_id, const std::shared_ptr& istr, const std::shared_ptr& idat, std::vector* dest, - uint64_t offset, uint64_t size) const + uint64_t offset, uint64_t size, + const heif_security_limits* limits) const { const Item* item = nullptr; for (auto& i : m_items) { @@ -1547,11 +1552,12 @@ Error Box_iloc::read_data(heif_item_id item_id, // --- security check that we do not allocate too much memory - if (MAX_MEMORY_BLOCK_SIZE - old_size < read_len) { + auto max_memory_block_size = limits->max_memory_block_size; + if (max_memory_block_size && max_memory_block_size - old_size < read_len) { std::stringstream sstr; sstr << "iloc box contained " << extent.length << " bytes, total memory size would be " << (old_size + extent.length) << " bytes, exceeding the security limit of " - << MAX_MEMORY_BLOCK_SIZE << " bytes"; + << max_memory_block_size << " bytes"; return {heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -1599,7 +1605,7 @@ Error Box_iloc::read_data(heif_item_id item_id, idat->read_data(istr, extent.offset + item->base_offset, extent.length, - *dest); + *dest, limits); size -= extent.length; } @@ -2043,7 +2049,7 @@ void Box_iloc::patch_iloc_header(StreamWriter& writer) const * Note: HEIF does not allow version 0 and version 1 boxes ! (see 23008-12, 10.2.1) */ -Error Box_infe::parse(BitstreamRange& range) +Error Box_infe::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2189,7 +2195,7 @@ std::string Box_infe::dump(Indent& indent) const } -Error Box_iinf::parse(BitstreamRange& range) +Error Box_iinf::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2213,7 +2219,7 @@ Error Box_iinf::parse(BitstreamRange& range) } // TODO: Only try to read "item_count" children. - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } @@ -2228,11 +2234,11 @@ std::string Box_iinf::dump(Indent& indent) const } -Error Box_iprp::parse(BitstreamRange& range) +Error Box_iprp::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } @@ -2286,11 +2292,11 @@ int Box_ipco::find_or_append_child_box(const std::shared_ptr& box) } -Error Box_ipco::parse(BitstreamRange& range) +Error Box_ipco::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } @@ -2305,7 +2311,7 @@ std::string Box_ipco::dump(Indent& indent) const } -Error Box_pixi::parse(BitstreamRange& range) +Error Box_pixi::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2370,7 +2376,7 @@ Error Box_pixi::write(StreamWriter& writer) const } -Error Box_pasp::parse(BitstreamRange& range) +Error Box_pasp::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -2406,7 +2412,7 @@ Error Box_pasp::write(StreamWriter& writer) const } -Error Box_lsel::parse(BitstreamRange& range) +Error Box_lsel::parse(BitstreamRange& range, const heif_security_limits* limits) { layer_id = range.read16(); @@ -2437,7 +2443,7 @@ Error Box_lsel::write(StreamWriter& writer) const } -Error Box_clli::parse(BitstreamRange& range) +Error Box_clli::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -2481,7 +2487,7 @@ Box_mdcv::Box_mdcv() } -Error Box_mdcv::parse(BitstreamRange& range) +Error Box_mdcv::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -2616,7 +2622,7 @@ bool Box_ipco::is_property_essential_for_item(heif_item_id itemId, } -Error Box_ispe::parse(BitstreamRange& range) +Error Box_ispe::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2668,7 +2674,7 @@ bool Box_ispe::operator==(const Box& other) const } -Error Box_ipma::parse(BitstreamRange& range) +Error Box_ipma::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2856,7 +2862,7 @@ void Box_ipma::insert_entries_from_other_ipma_box(const Box_ipma& b) } -Error Box_auxC::parse(BitstreamRange& range) +Error Box_auxC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -2907,7 +2913,7 @@ std::string Box_auxC::dump(Indent& indent) const } -Error Box_irot::parse(BitstreamRange& range) +Error Box_irot::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -2943,7 +2949,7 @@ std::string Box_irot::dump(Indent& indent) const } -Error Box_imir::parse(BitstreamRange& range) +Error Box_imir::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -2993,7 +2999,7 @@ std::string Box_imir::dump(Indent& indent) const } -Error Box_clap::parse(BitstreamRange& range) +Error Box_clap::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -3147,7 +3153,7 @@ void Box_clap::set(uint32_t clap_width, uint32_t clap_height, } -Error Box_iref::parse(BitstreamRange& range) +Error Box_iref::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -3195,7 +3201,8 @@ Error Box_iref::parse(BitstreamRange& range) nTotalRefs += ref.to_item_ID.size(); } - if (nTotalRefs > MAX_IREF_REFERENCES) { + auto max_iref_references = limits->max_iref_references; + if (max_iref_references && nTotalRefs > max_iref_references) { return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, "Number of iref references exceeds security limit."); } @@ -3393,7 +3400,7 @@ void Box_iref::add_references(heif_item_id from_id, uint32_t type, const std::ve } -Error Box_idat::parse(BitstreamRange& range) +Error Box_idat::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -3432,17 +3439,19 @@ std::string Box_idat::dump(Indent& indent) const Error Box_idat::read_data(const std::shared_ptr& istr, uint64_t start, uint64_t length, - std::vector& out_data) const + std::vector& out_data, + const heif_security_limits* limits) const { // --- security check that we do not allocate too much data auto curr_size = out_data.size(); - if (MAX_MEMORY_BLOCK_SIZE - curr_size < length) { + auto max_memory_block_size = limits->max_memory_block_size; + if (max_memory_block_size && max_memory_block_size - curr_size < length) { std::stringstream sstr; sstr << "idat box contained " << length << " bytes, total memory size would be " << (curr_size + length) << " bytes, exceeding the security limit of " - << MAX_MEMORY_BLOCK_SIZE << " bytes"; + << max_memory_block_size << " bytes"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -3487,11 +3496,11 @@ Error Box_idat::read_data(const std::shared_ptr& istr, } -Error Box_grpl::parse(BitstreamRange& range) +Error Box_grpl::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); - return read_children(range); // should we pass the parsing context 'grpl' or are the box types unique? + return read_children(range, READ_CHILDREN_ALL, limits); // should we pass the parsing context 'grpl' or are the box types unique? } @@ -3504,7 +3513,7 @@ std::string Box_grpl::dump(Indent& indent) const } -Error Box_EntityToGroup::parse(BitstreamRange& range) +Error Box_EntityToGroup::parse(BitstreamRange& range, const heif_security_limits* limits) { Error err = parse_full_box_header(range); if (err != Error::Ok) { @@ -3576,9 +3585,9 @@ std::string Box_EntityToGroup::dump(Indent& indent) const } -Error Box_ster::parse(BitstreamRange& range) +Error Box_ster::parse(BitstreamRange& range, const heif_security_limits* limits) { - Error err = Box_EntityToGroup::parse(range); + Error err = Box_EntityToGroup::parse(range, limits); if (err) { return err; } @@ -3607,9 +3616,9 @@ std::string Box_ster::dump(Indent& indent) const -Error Box_pymd::parse(BitstreamRange& range) +Error Box_pymd::parse(BitstreamRange& range, const heif_security_limits* limits) { - Error err = Box_EntityToGroup::parse(range); + Error err = Box_EntityToGroup::parse(range, limits); if (err) { return err; } @@ -3673,11 +3682,11 @@ std::string Box_pymd::dump(Indent& indent) const } -Error Box_dinf::parse(BitstreamRange& range) +Error Box_dinf::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } @@ -3691,7 +3700,7 @@ std::string Box_dinf::dump(Indent& indent) const } -Error Box_dref::parse(BitstreamRange& range) +Error Box_dref::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -3715,7 +3724,7 @@ Error Box_dref::parse(BitstreamRange& range) "Too many entities in dref box."); } - Error err = read_children(range, (int)nEntities); + Error err = read_children(range, (int)nEntities, limits); if (err) { return err; } @@ -3738,7 +3747,7 @@ std::string Box_dref::dump(Indent& indent) const } -Error Box_url::parse(BitstreamRange& range) +Error Box_url::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -3770,7 +3779,7 @@ std::string Box_url::dump(Indent& indent) const } -Error Box_udes::parse(BitstreamRange& range) +Error Box_udes::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -3859,7 +3868,7 @@ std::string Box_cmin::dump(Indent& indent) const } -Error Box_cmin::parse(BitstreamRange& range) +Error Box_cmin::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -4046,7 +4055,7 @@ std::array Box_cmex::ExtrinsicMatrix::calculate_rotation_matrix() cons } -Error Box_cmex::parse(BitstreamRange& range) +Error Box_cmex::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); diff --git a/libheif/box.h b/libheif/box.h index 9bc302905c..4759f62e21 100644 --- a/libheif/box.h +++ b/libheif/box.h @@ -24,6 +24,7 @@ #include #include "common_utils.h" #include "libheif/heif.h" +#include "libheif/heif_experimental.h" #include "libheif/heif_properties.h" #include #include @@ -181,7 +182,7 @@ class Box : public BoxHeader // header size without the FullBox fields (if applicable) int calculate_header_size(bool data64bit) const; - static Error read(BitstreamRange& range, std::shared_ptr* box); + static Error read(BitstreamRange& range, std::shared_ptr* box, const heif_security_limits*); virtual Error write(StreamWriter& writer) const; @@ -245,7 +246,7 @@ class Box : public BoxHeader void set_is_essential(bool flag) { m_is_essential = flag; } protected: - virtual Error parse(BitstreamRange& range); + virtual Error parse(BitstreamRange& range, const heif_security_limits* limits); std::vector> m_children; @@ -263,7 +264,7 @@ class Box : public BoxHeader const static int READ_CHILDREN_ALL = -1; - Error read_children(BitstreamRange& range, int number = READ_CHILDREN_ALL); + Error read_children(BitstreamRange& range, int number /* READ_CHILDREN_ALL */, const heif_security_limits* limits); Error write_children(StreamWriter& writer) const; @@ -333,7 +334,7 @@ class Box_other : public Box std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; std::vector m_data; }; @@ -361,7 +362,7 @@ class Box_Error : public Box [[nodiscard]] Error get_error() const { return m_error; } protected: - Error parse(BitstreamRange& range) override { assert(false); return Error::Ok; } + Error parse(BitstreamRange& range, const heif_security_limits*) override { assert(false); return Error::Ok; } uint32_t m_box_type_with_parse_error; Error m_error; @@ -396,7 +397,7 @@ class Box_ftyp : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: uint32_t m_major_brand = 0; @@ -416,7 +417,7 @@ class Box_meta : public FullBox std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -439,7 +440,7 @@ class Box_hdlr : public FullBox void set_name(std::string name) { m_name = std::move(name); } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: uint32_t m_pre_defined = 0; @@ -468,7 +469,7 @@ class Box_pitm : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: heif_item_id m_item_ID = 0; @@ -510,14 +511,16 @@ class Box_iloc : public FullBox Error read_data(heif_item_id item, const std::shared_ptr& istr, const std::shared_ptr&, - std::vector* dest) const; + std::vector* dest, + const heif_security_limits* limits) const; // Note: size==std::numeric_limits::max() reads the data until the end Error read_data(heif_item_id item, const std::shared_ptr& istr, const std::shared_ptr&, std::vector* dest, - uint64_t offset, uint64_t size) const; + uint64_t offset, uint64_t size, + const heif_security_limits* limits) const; void set_min_version(uint8_t min_version) { m_user_defined_min_version = min_version; } @@ -549,7 +552,7 @@ class Box_iloc : public FullBox Error write_mdat_after_iloc(StreamWriter& writer); protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: std::vector m_items; @@ -614,7 +617,7 @@ class Box_infe : public FullBox void set_item_uri_type(const std::string& uritype) { m_item_uri_type = uritype; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: heif_item_id m_item_ID = 0; @@ -646,7 +649,7 @@ class Box_iinf : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: //std::vector< std::shared_ptr > m_iteminfos; @@ -664,7 +667,7 @@ class Box_iprp : public Box std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -693,7 +696,7 @@ class Box_ipco : public Box std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -724,7 +727,7 @@ class Box_ispe : public FullBox bool is_essential() const override { return false; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: uint32_t m_image_width = 0; @@ -762,7 +765,7 @@ class Box_ipma : public FullBox void insert_entries_from_other_ipma_box(const Box_ipma& b); protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; struct Entry { @@ -793,7 +796,7 @@ class Box_auxC : public FullBox std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -823,7 +826,7 @@ class Box_irot : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::ignorable; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -851,7 +854,7 @@ class Box_imir : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::ignorable; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -890,7 +893,7 @@ class Box_clap : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::ignorable; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -930,7 +933,7 @@ class Box_iref : public FullBox void add_references(heif_item_id from_id, uint32_t type, const std::vector& to_ids); protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -948,7 +951,8 @@ class Box_idat : public Box Error read_data(const std::shared_ptr& istr, uint64_t start, uint64_t length, - std::vector& out_data) const; + std::vector& out_data, + const heif_security_limits* limits) const; int append_data(const std::vector& data) { @@ -964,7 +968,7 @@ class Box_idat : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; std::streampos m_data_start_pos; @@ -983,7 +987,7 @@ class Box_grpl : public Box std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1006,7 +1010,7 @@ class Box_EntityToGroup : public FullBox heif_entity_group_id group_id = 0; std::vector entity_ids; - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; void write_entity_group_ids(StreamWriter& writer) const; }; @@ -1027,7 +1031,7 @@ class Box_ster : public Box_EntityToGroup protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1070,7 +1074,7 @@ class Box_pymd : public Box_EntityToGroup std::vector m_layer_infos; - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1082,7 +1086,7 @@ class Box_dinf : public Box std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1092,7 +1096,7 @@ class Box_dref : public FullBox std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1104,7 +1108,7 @@ class Box_url : public FullBox bool is_same_file() const { return m_location.empty(); } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; std::string m_location; }; @@ -1133,7 +1137,7 @@ class Box_pixi : public FullBox [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: std::vector m_bits_per_channel; @@ -1158,7 +1162,7 @@ class Box_pasp : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1179,7 +1183,7 @@ class Box_lsel : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1203,7 +1207,7 @@ class Box_clli : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1221,7 +1225,7 @@ class Box_mdcv : public Box [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; }; @@ -1293,7 +1297,7 @@ class Box_cmin : public FullBox [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -1348,7 +1352,7 @@ class Box_cmex : public FullBox [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; Error write(StreamWriter& writer) const override; @@ -1460,7 +1464,7 @@ class Box_udes : public FullBox [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::optional; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits*) override; private: std::string m_lang; diff --git a/libheif/codecs/avc_boxes.cc b/libheif/codecs/avc_boxes.cc index 5b205bd1ec..b49d9e4b6d 100644 --- a/libheif/codecs/avc_boxes.cc +++ b/libheif/codecs/avc_boxes.cc @@ -28,7 +28,7 @@ #include "avc_dec.h" -Error Box_avcC::parse(BitstreamRange& range) +Error Box_avcC::parse(BitstreamRange& range, const heif_security_limits* limits) { m_configuration.configuration_version = range.read8(); m_configuration.AVCProfileIndication = range.read8(); diff --git a/libheif/codecs/avc_boxes.h b/libheif/codecs/avc_boxes.h index 47cf782898..983ab0c2e0 100644 --- a/libheif/codecs/avc_boxes.h +++ b/libheif/codecs/avc_boxes.h @@ -79,7 +79,7 @@ class Box_avcC : public Box { Error write(StreamWriter &writer) const override; protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; std::string profileIndicationAsText() const; diff --git a/libheif/codecs/avif_boxes.cc b/libheif/codecs/avif_boxes.cc index 4eead97dcc..584a5072b2 100644 --- a/libheif/codecs/avif_boxes.cc +++ b/libheif/codecs/avif_boxes.cc @@ -33,7 +33,7 @@ // https://aomediacodec.github.io/av1-spec/av1-spec.pdf -Error Box_av1C::parse(BitstreamRange& range) +Error Box_av1C::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); @@ -189,7 +189,7 @@ Error fill_av1C_configuration(Box_av1C::configuration* inout_config, const std:: } -Error Box_a1op::parse(BitstreamRange& range) +Error Box_a1op::parse(BitstreamRange& range, const heif_security_limits* limits) { op_index = range.read8(); @@ -220,7 +220,7 @@ Error Box_a1op::write(StreamWriter& writer) const } -Error Box_a1lx::parse(BitstreamRange& range) +Error Box_a1lx::parse(BitstreamRange& range, const heif_security_limits* limits) { uint8_t flags = range.read8(); diff --git a/libheif/codecs/avif_boxes.h b/libheif/codecs/avif_boxes.h index 8ce380c28e..b233c6c2d7 100644 --- a/libheif/codecs/avif_boxes.h +++ b/libheif/codecs/avif_boxes.h @@ -98,7 +98,7 @@ class Box_av1C : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: configuration m_configuration; @@ -122,7 +122,7 @@ class Box_a1op : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; }; @@ -141,7 +141,7 @@ class Box_a1lx : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; }; diff --git a/libheif/codecs/hevc_boxes.cc b/libheif/codecs/hevc_boxes.cc index 47fe7a8438..e568cdddcc 100644 --- a/libheif/codecs/hevc_boxes.cc +++ b/libheif/codecs/hevc_boxes.cc @@ -33,7 +33,7 @@ #include -Error Box_hvcC::parse(BitstreamRange& range) +Error Box_hvcC::parse(BitstreamRange& range, const heif_security_limits* limits) { //parse_full_box_header(range); diff --git a/libheif/codecs/hevc_boxes.h b/libheif/codecs/hevc_boxes.h index 1224b6a8ad..9b2a4971e2 100644 --- a/libheif/codecs/hevc_boxes.h +++ b/libheif/codecs/hevc_boxes.h @@ -82,7 +82,7 @@ class Box_hvcC : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: struct NalArray diff --git a/libheif/codecs/jpeg2000_boxes.cc b/libheif/codecs/jpeg2000_boxes.cc index 15ed6e1af1..b41c28388a 100644 --- a/libheif/codecs/jpeg2000_boxes.cc +++ b/libheif/codecs/jpeg2000_boxes.cc @@ -29,7 +29,7 @@ static const uint16_t JPEG2000_SIZ_MARKER = 0xFF51; static const uint16_t JPEG2000_SOC_MARKER = 0xFF4F; -Error Box_cdef::parse(BitstreamRange& range) +Error Box_cdef::parse(BitstreamRange& range, const heif_security_limits* limits) { int channel_count = range.read16(); @@ -112,7 +112,7 @@ void Box_cdef::set_channels(heif_colorspace colorspace) } } -Error Box_cmap::parse(BitstreamRange& range) +Error Box_cmap::parse(BitstreamRange& range, const heif_security_limits* limits) { while (!range.eof() && !range.error()) { Component component; @@ -157,7 +157,7 @@ Error Box_cmap::write(StreamWriter& writer) const } -Error Box_pclr::parse(BitstreamRange& range) +Error Box_pclr::parse(BitstreamRange& range, const heif_security_limits* limits) { uint16_t num_entries = range.read16(); uint8_t num_palette_columns = range.read8(); @@ -249,7 +249,7 @@ void Box_pclr::set_columns(uint8_t num_columns, uint8_t bit_depth) } } -Error Box_j2kL::parse(BitstreamRange& range) +Error Box_j2kL::parse(BitstreamRange& range, const heif_security_limits* limits) { int layer_count = range.read16(); @@ -296,9 +296,9 @@ Error Box_j2kL::write(StreamWriter& writer) const } -Error Box_j2kH::parse(BitstreamRange& range) +Error Box_j2kH::parse(BitstreamRange& range, const heif_security_limits* limits) { - return read_children(range); + return read_children(range, READ_CHILDREN_ALL, limits); } std::string Box_j2kH::dump(Indent& indent) const diff --git a/libheif/codecs/jpeg2000_boxes.h b/libheif/codecs/jpeg2000_boxes.h index 230bfc0b3f..c07e60467d 100644 --- a/libheif/codecs/jpeg2000_boxes.h +++ b/libheif/codecs/jpeg2000_boxes.h @@ -108,7 +108,7 @@ class Box_cdef : public Box { void set_channels(heif_colorspace colorspace); protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; private: std::vector m_channels; @@ -165,7 +165,7 @@ class Box_cmap : public Box void add_component(Component component) { m_components.push_back(component); } protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; private: std::vector m_components; @@ -245,7 +245,7 @@ class Box_pclr : public Box void set_columns(uint8_t num_columns, uint8_t bit_depth); protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; private: std::vector m_bitDepths; @@ -301,7 +301,7 @@ class Box_j2kL : public FullBox void add_layer(Layer layer) { m_layers.push_back(layer); } protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; private: std::vector m_layers; @@ -319,7 +319,7 @@ class Box_j2kH : public Box // Default write behaviour for a container is to write children protected: - Error parse(BitstreamRange &range) override; + Error parse(BitstreamRange &range, const heif_security_limits* limits) override; }; class Jpeg2000ImageCodec diff --git a/libheif/codecs/jpeg_boxes.cc b/libheif/codecs/jpeg_boxes.cc index b8cde160bf..bcb145850a 100644 --- a/libheif/codecs/jpeg_boxes.cc +++ b/libheif/codecs/jpeg_boxes.cc @@ -22,6 +22,7 @@ #include #include "security_limits.h" #include +#include "libheif/heif_experimental.h" // returns 0 if the marker_type was not found @@ -60,14 +61,14 @@ Error Box_jpgC::write(StreamWriter& writer) const } -Error Box_jpgC::parse(BitstreamRange& range) +Error Box_jpgC::parse(BitstreamRange& range, const heif_security_limits* limits) { if (!has_fixed_box_size()) { return Error{heif_error_Unsupported_feature, heif_suberror_Unspecified, "jpgC with unspecified size are not supported"}; } size_t nBytes = range.get_remaining_bytes(); - if (nBytes > MAX_MEMORY_BLOCK_SIZE) { + if (nBytes > limits->max_memory_block_size) { return Error{heif_error_Invalid_input, heif_suberror_Unspecified, "jpgC block exceeds maximum size"}; } diff --git a/libheif/codecs/jpeg_boxes.h b/libheif/codecs/jpeg_boxes.h index 5df25bcd30..8a9e56a0bc 100644 --- a/libheif/codecs/jpeg_boxes.h +++ b/libheif/codecs/jpeg_boxes.h @@ -45,7 +45,7 @@ class Box_jpgC : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: std::vector m_data; diff --git a/libheif/codecs/uncompressed/unc_boxes.cc b/libheif/codecs/uncompressed/unc_boxes.cc index 7524010c06..82085e4b62 100644 --- a/libheif/codecs/uncompressed/unc_boxes.cc +++ b/libheif/codecs/uncompressed/unc_boxes.cc @@ -28,7 +28,7 @@ #include #include "libheif/heif.h" -#include "security_limits.h" +#include "libheif/heif_experimental.h" #include "unc_types.h" #include "unc_boxes.h" @@ -129,7 +129,7 @@ template const char* get_name(T val, const std::map } } -Error Box_cmpd::parse(BitstreamRange& range) +Error Box_cmpd::parse(BitstreamRange& range, const heif_security_limits* limits) { unsigned int component_count = range.read32(); @@ -196,7 +196,7 @@ Error Box_cmpd::write(StreamWriter& writer) const return Error::Ok; } -Error Box_uncC::parse(BitstreamRange& range) +Error Box_uncC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); m_profile = range.read32(); @@ -402,7 +402,7 @@ uint64_t Box_uncC::compute_tile_data_size_bytes(uint32_t tile_width, uint32_t ti } -Error Box_cmpC::parse(BitstreamRange& range) +Error Box_cmpC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -438,7 +438,7 @@ Error Box_cmpC::write(StreamWriter& writer) const } -Error Box_icef::parse(BitstreamRange& range) +Error Box_icef::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -616,7 +616,7 @@ const uint8_t Box_icef::get_required_size_code(uint64_t size) const } -Error Box_cpat::parse(BitstreamRange& range) +Error Box_cpat::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -627,7 +627,8 @@ Error Box_cpat::parse(BitstreamRange& range) m_pattern_width = range.read16(); m_pattern_height = range.read16(); - if (m_pattern_width * m_pattern_height > MAX_BAYER_PATTERN_PIXELS) { + auto max_bayer_pattern_size = limits->max_bayer_pattern_pixels; + if (max_bayer_pattern_size && m_pattern_width * m_pattern_height > max_bayer_pattern_size) { return {heif_error_Invalid_input, heif_suberror_Security_limit_exceeded, "Maximum Bayer pattern size exceeded."}; diff --git a/libheif/codecs/uncompressed/unc_boxes.h b/libheif/codecs/uncompressed/unc_boxes.h index 1397b2345f..294157987f 100644 --- a/libheif/codecs/uncompressed/unc_boxes.h +++ b/libheif/codecs/uncompressed/unc_boxes.h @@ -65,7 +65,7 @@ class Box_cmpd : public Box } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; std::vector m_components; }; @@ -206,7 +206,7 @@ class Box_uncC : public FullBox uint64_t compute_tile_data_size_bytes(uint32_t tile_width, uint32_t tile_height) const; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; uint32_t m_profile = 0; // 0 = not compliant to any profile @@ -261,7 +261,7 @@ class Box_cmpC : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; uint32_t m_compression_type; uint8_t m_compressed_unit_type; @@ -309,7 +309,7 @@ class Box_icef : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; std::vector m_unit_infos; @@ -357,7 +357,7 @@ class Box_cpat : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; uint16_t m_pattern_width; uint16_t m_pattern_height; diff --git a/libheif/codecs/vvc_boxes.cc b/libheif/codecs/vvc_boxes.cc index f8bb73cefc..10839ab8ad 100644 --- a/libheif/codecs/vvc_boxes.cc +++ b/libheif/codecs/vvc_boxes.cc @@ -28,7 +28,7 @@ #include -Error Box_vvcC::parse(BitstreamRange& range) +Error Box_vvcC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); diff --git a/libheif/codecs/vvc_boxes.h b/libheif/codecs/vvc_boxes.h index 38fdc3e627..bf6322306d 100644 --- a/libheif/codecs/vvc_boxes.h +++ b/libheif/codecs/vvc_boxes.h @@ -85,7 +85,7 @@ class Box_vvcC : public FullBox Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: struct NalArray diff --git a/libheif/context.cc b/libheif/context.cc index 1c6084acc1..f4c901e215 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -95,11 +95,12 @@ struct heif_error heif_encoder::alloc() HeifContext::HeifContext() { - m_maximum_image_size_limit = MAX_IMAGE_SIZE; + m_limits = global_security_limits; reset_to_empty_heif(); } + HeifContext::~HeifContext() { // Break circular references between Images (when a faulty input image has circular image references) @@ -109,9 +110,38 @@ HeifContext::~HeifContext() } } + +void HeifContext::set_maximum_image_size_limit(uint32_t maximum_size) +{ + m_limits.max_image_size_pixels = maximum_size; +} + + +static void copy_security_limits(heif_security_limits* dst, const heif_security_limits* src) +{ + dst->version = 1; + dst->max_image_size_pixels = src->max_image_size_pixels; + dst->max_bayer_pattern_pixels = src->max_bayer_pattern_pixels; + dst->max_iref_references = src->max_iref_references; + dst->max_iloc_items = src->max_iloc_items; + dst->max_iloc_extents_per_item = src->max_iloc_extents_per_item; + dst->max_children_per_box = src->max_children_per_box; + dst->max_number_of_tiles = src->max_number_of_tiles; + dst->max_color_profile_size = src->max_color_profile_size; + dst->max_memory_block_size = src->max_memory_block_size; +} + + +void HeifContext::set_security_limits(const heif_security_limits* limits) +{ + copy_security_limits(&m_limits, limits); +} + + Error HeifContext::read(const std::shared_ptr& reader) { m_heif_file = std::make_shared(); + m_heif_file->set_security_limits(&m_limits); Error err = m_heif_file->read(reader); if (err) { return err; @@ -123,6 +153,7 @@ Error HeifContext::read(const std::shared_ptr& reader) Error HeifContext::read_from_file(const char* input_filename) { m_heif_file = std::make_shared(); + m_heif_file->set_security_limits(&m_limits); Error err = m_heif_file->read_from_file(input_filename); if (err) { return err; @@ -134,6 +165,7 @@ Error HeifContext::read_from_file(const char* input_filename) Error HeifContext::read_from_memory(const void* data, size_t size, bool copy) { m_heif_file = std::make_shared(); + m_heif_file->set_security_limits(&m_limits); Error err = m_heif_file->read_from_memory(data, size, copy); if (err) { return err; @@ -145,6 +177,7 @@ Error HeifContext::read_from_memory(const void* data, size_t size, bool copy) void HeifContext::reset_to_empty_heif() { m_heif_file = std::make_shared(); + m_heif_file->set_security_limits(&m_limits); m_heif_file->new_empty_file(); m_all_images.clear(); @@ -159,10 +192,10 @@ Error HeifContext::check_resolution(uint32_t width, uint32_t height) const { // --- check whether the image size is "too large" uint32_t max_width_height = static_cast(std::numeric_limits::max()); if ((width > max_width_height || height > max_width_height) || - (height != 0 && width > m_maximum_image_size_limit / height)) { + (height != 0 && width > get_security_limits()->max_image_size_pixels / height)) { std::stringstream sstr; sstr << "Image size " << width << "x" << height << " exceeds the maximum image size " - << m_maximum_image_size_limit << "\n"; + << get_security_limits()->max_image_size_pixels << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -375,7 +408,7 @@ Error HeifContext::interpret_heif_file() if (width >= max_width_height || height >= max_width_height) { std::stringstream sstr; sstr << "Image size " << width << "x" << height << " exceeds the maximum image size " - << m_maximum_image_size_limit << "\n"; + << get_security_limits()->max_image_size_pixels << "\n"; return Error(heif_error_Memory_allocation_error, heif_suberror_Security_limit_exceeded, @@ -780,7 +813,7 @@ Error HeifContext::interpret_heif_file() std::shared_ptr region_item = std::make_shared(); region_item->item_id = id; std::vector region_data; - Error err = m_heif_file->get_uncompressed_item_data(id, &(region_data)); + Error err = m_heif_file->get_uncompressed_item_data(id, ®ion_data); if (err) { return err; } diff --git a/libheif/context.h b/libheif/context.h index 07d78e0326..7bae2ec3a9 100644 --- a/libheif/context.h +++ b/libheif/context.h @@ -69,16 +69,19 @@ class HeifContext : public ErrorBuffer int get_max_decoding_threads() const { return m_max_decoding_threads; } + void set_security_limits(const heif_security_limits* limits); + + [[nodiscard]] heif_security_limits* get_security_limits() { return &m_limits; } + + [[nodiscard]] const heif_security_limits* get_security_limits() const { return &m_limits; } + // 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(uint32_t maximum_size) - { - m_maximum_image_size_limit = uint64_t(maximum_size) * maximum_size; - } + void set_maximum_image_size_limit(uint32_t maximum_size); uint64_t get_maximum_image_size_limit() const { - return m_maximum_image_size_limit; + return get_security_limits()->max_image_size_pixels; } Error read(const std::shared_ptr& reader); @@ -231,8 +234,7 @@ class HeifContext : public ErrorBuffer int m_max_decoding_threads = 4; - // Maximum image size in pixels (width * height). - uint64_t m_maximum_image_size_limit; + heif_security_limits m_limits; std::vector> m_region_items; diff --git a/libheif/file.cc b/libheif/file.cc index ae28f84126..5196b252c3 100644 --- a/libheif/file.cc +++ b/libheif/file.cc @@ -124,10 +124,12 @@ Error HeifFile::read_from_memory(const void* data, size_t size, bool copy) Error HeifFile::read(const std::shared_ptr& reader) { + assert(m_limits); + m_input_stream = reader; Error err; - err = m_file_layout->read(reader); + err = m_file_layout->read(reader, m_limits); if (err) { return err; } @@ -528,6 +530,8 @@ Error HeifFile::get_properties(heif_item_id imageID, Error HeifFile::get_uncompressed_item_data(heif_item_id ID, std::vector* data) const { + assert(m_limits); + #if ENABLE_PARALLEL_TILE_DECODING // std::lock_guard guard(m_read_mutex); // TODO: I think that this is not needed anymore because this function is not used for image data anymore. #endif @@ -557,7 +561,7 @@ Error HeifFile::get_uncompressed_item_data(heif_item_id ID, std::vector #if HAVE_ZLIB read_uncompressed = false; std::vector compressed_data; - error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data); + error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data, m_limits); if (error) { return error; } @@ -575,7 +579,7 @@ Error HeifFile::get_uncompressed_item_data(heif_item_id ID, std::vector #if HAVE_ZLIB read_uncompressed = false; std::vector compressed_data; - error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data); + error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data, m_limits); if (error) { return error; } @@ -593,7 +597,7 @@ Error HeifFile::get_uncompressed_item_data(heif_item_id ID, std::vector #if HAVE_BROTLI read_uncompressed = false; std::vector compressed_data; - error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data); + error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data, m_limits); if (error) { return error; } @@ -610,7 +614,7 @@ Error HeifFile::get_uncompressed_item_data(heif_item_id ID, std::vector } if (read_uncompressed) { - return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, data); + return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, data, m_limits); } return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_codec); @@ -636,7 +640,7 @@ Error HeifFile::append_data_from_iloc(heif_item_id ID, std::vector& out sstr.str()}; } - return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &out_data, offset, size); + return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &out_data, offset, size, m_limits); } @@ -644,6 +648,8 @@ Error HeifFile::get_item_data(heif_item_id ID, std::vector* out_data, h { Error error; + assert(m_limits); + auto infe_box = get_infe_box(ID); if (!infe_box) { return {heif_error_Usage_error, @@ -660,7 +666,7 @@ Error HeifFile::get_item_data(heif_item_id ID, std::vector* out_data, h *out_compression = heif_metadata_compression_off; } - return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, out_data); + return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, out_data, m_limits); } @@ -677,7 +683,7 @@ Error HeifFile::get_item_data(heif_item_id ID, std::vector* out_data, h *out_compression = heif_metadata_compression_off; } - return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, out_data); + return m_iloc_box->read_data(ID, m_input_stream, m_idat_box, out_data, m_limits); } else if (encoding == "compress_zlib") { compression = heif_metadata_compression_zlib; @@ -695,7 +701,7 @@ Error HeifFile::get_item_data(heif_item_id ID, std::vector* out_data, h // read compressed data std::vector compressed_data; - error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data); + error = m_iloc_box->read_data(ID, m_input_stream, m_idat_box, &compressed_data, m_limits); if (error) { return error; } diff --git a/libheif/file.h b/libheif/file.h index 3b1c42bfac..be17c336d5 100644 --- a/libheif/file.h +++ b/libheif/file.h @@ -56,6 +56,10 @@ class HeifFile ~HeifFile(); + // The limits will be shared from the HeifContext limits. + // You have to make sure that the pointer points to a valid object as long as the HeifFile is used. + void set_security_limits(const heif_security_limits* limits) { m_limits = limits; } + Error read(const std::shared_ptr& reader); Error read_from_file(const char* input_filename); @@ -219,6 +223,8 @@ class HeifFile std::map > m_infe_boxes; + const heif_security_limits* m_limits = nullptr; + Error parse_heif_file(); Error check_for_ref_cycle(heif_item_id ID, diff --git a/libheif/file_layout.cc b/libheif/file_layout.cc index 8d1fc02629..dcc1947c17 100644 --- a/libheif/file_layout.cc +++ b/libheif/file_layout.cc @@ -33,7 +33,7 @@ FileLayout::FileLayout() } -Error FileLayout::read(const std::shared_ptr& stream) +Error FileLayout::read(const std::shared_ptr& stream, const heif_security_limits* limits) { m_boxes.clear(); @@ -85,7 +85,7 @@ Error FileLayout::read(const std::shared_ptr& stream) BitstreamRange ftyp_range(m_stream_reader, 0, ftyp_size); std::shared_ptr ftyp_box; - err = Box::read(ftyp_range, &ftyp_box); + err = Box::read(ftyp_range, &ftyp_box, limits); m_boxes.push_back(ftyp_box); m_ftyp_box = std::dynamic_pointer_cast(ftyp_box); @@ -138,7 +138,7 @@ Error FileLayout::read(const std::shared_ptr& stream) BitstreamRange meta_box_range(m_stream_reader, meta_box_start, end_of_meta_box); std::shared_ptr meta_box; - err = Box::read(meta_box_range, &meta_box); + err = Box::read(meta_box_range, &meta_box, limits); if (err) { return err; } diff --git a/libheif/file_layout.h b/libheif/file_layout.h index 05dcfa9ac4..5700a130d0 100644 --- a/libheif/file_layout.h +++ b/libheif/file_layout.h @@ -40,7 +40,7 @@ class FileLayout // Generate a file in WriteMode::Floating FileLayout(); - Error read(const std::shared_ptr& stream); + Error read(const std::shared_ptr& stream, const heif_security_limits* limits); // For WriteMode::Streaming, writer cannot be null. void set_write_mode(WriteMode writeMode, const std::shared_ptr& writer = nullptr); diff --git a/libheif/image-items/mask_image.cc b/libheif/image-items/mask_image.cc index a7dd59d5f2..da21641ba7 100644 --- a/libheif/image-items/mask_image.cc +++ b/libheif/image-items/mask_image.cc @@ -32,7 +32,7 @@ #include "mask_image.h" #include "image_item.h" -Error Box_mskC::parse(BitstreamRange& range) +Error Box_mskC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); m_bits_per_pixel = range.read8(); diff --git a/libheif/image-items/mask_image.h b/libheif/image-items/mask_image.h index 4b0fed6980..c61befdb2c 100644 --- a/libheif/image-items/mask_image.h +++ b/libheif/image-items/mask_image.h @@ -63,7 +63,7 @@ class Box_mskC : public FullBox { m_bits_per_pixel = bits_per_pixel; } protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: uint8_t m_bits_per_pixel; diff --git a/libheif/image-items/tild.cc b/libheif/image-items/tild.cc index ae2413c19f..d0475d460f 100644 --- a/libheif/image-items/tild.cc +++ b/libheif/image-items/tild.cc @@ -161,7 +161,7 @@ std::string Box_tilC::dump(Indent& indent) const } -Error Box_tilC::parse(BitstreamRange& range) +Error Box_tilC::parse(BitstreamRange& range, const heif_security_limits* limits) { parse_full_box_header(range); @@ -252,7 +252,9 @@ Error TildHeader::set_parameters(const heif_tild_image_parameters& params) { m_parameters = params; - if (number_of_tiles(params) > MAX_TILD_TILES) { + auto max_tiles = heif_get_global_security_limits()->max_number_of_tiles; + + if (max_tiles && number_of_tiles(params) > max_tiles) { return {heif_error_Unsupported_filetype, heif_suberror_Security_limit_exceeded, "Number of tiles exceeds security limit"}; @@ -268,10 +270,12 @@ Error TildHeader::set_parameters(const heif_tild_image_parameters& params) } -Error TildHeader::read_full_offset_table(const std::shared_ptr& file, heif_item_id tild_id) +Error TildHeader::read_full_offset_table(const std::shared_ptr& file, heif_item_id tild_id, const heif_security_limits* limits) { + auto max_tiles = heif_get_global_security_limits()->max_number_of_tiles; + uint64_t nTiles = number_of_tiles(m_parameters); - if (nTiles > MAX_TILD_TILES) { + if (max_tiles && nTiles > max_tiles) { return {heif_error_Invalid_input, heif_suberror_Security_limit_exceeded, "Number of tiles exceeds security limit."}; @@ -485,7 +489,7 @@ Error ImageItem_Tild::on_load_file() } if (m_preload_offset_table) { - if (Error err = m_tild_header.read_full_offset_table(heif_file, get_id())) { + if (Error err = m_tild_header.read_full_offset_table(heif_file, get_id(), get_context()->get_security_limits())) { return err; } } @@ -497,7 +501,8 @@ Error ImageItem_Tild::on_load_file() Result> ImageItem_Tild::add_new_tild_item(HeifContext* ctx, const heif_tild_image_parameters* parameters) { - if (number_of_tiles(*parameters) > MAX_TILD_TILES) { + auto max_tild_tiles = ctx->get_security_limits()->max_number_of_tiles; + if (max_tild_tiles && number_of_tiles(*parameters) > max_tild_tiles) { return Error{heif_error_Usage_error, heif_suberror_Security_limit_exceeded, "Number of tiles exceeds security limit."}; diff --git a/libheif/image-items/tild.h b/libheif/image-items/tild.h index 73b2710213..c32f288614 100644 --- a/libheif/image-items/tild.h +++ b/libheif/image-items/tild.h @@ -66,7 +66,7 @@ class Box_tilC : public FullBox std::string dump(Indent&) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: heif_tild_image_parameters m_parameters; @@ -84,7 +84,7 @@ class TildHeader const heif_tild_image_parameters& get_parameters() const { return m_parameters; } - Error read_full_offset_table(const std::shared_ptr& file, heif_item_id tild_id); + Error read_full_offset_table(const std::shared_ptr& file, heif_item_id tild_id, const heif_security_limits* limits); Error read_offset_table_range(const std::shared_ptr& file, heif_item_id tild_id, uint64_t start, uint64_t end); diff --git a/libheif/nclx.cc b/libheif/nclx.cc index 80535c4e68..92f0483393 100644 --- a/libheif/nclx.cc +++ b/libheif/nclx.cc @@ -20,10 +20,9 @@ #include "nclx.h" -#include "security_limits.h" +#include "libheif/heif_experimental.h" #include -#include #include #include #include @@ -359,7 +358,7 @@ void color_profile_nclx::replace_undefined_values_with_sRGB_defaults() } -Error Box_colr::parse(BitstreamRange& range) +Error Box_colr::parse(BitstreamRange& range, const heif_security_limits* limits) { StreamReader::grow_status status; uint32_t colour_type = range.read32(); @@ -379,7 +378,7 @@ Error Box_colr::parse(BitstreamRange& range) } uint64_t profile_size_64 = get_box_size() - get_header_size() - 4; - if (profile_size_64 > MAX_COLOR_PROFILE_SIZE) { + if (profile_size_64 > limits->max_color_profile_size) { return Error(heif_error_Invalid_input, heif_suberror_Security_limit_exceeded, "Color profile exceeds maximum supported size"); } diff --git a/libheif/nclx.h b/libheif/nclx.h index 5779e440e3..3938479fcb 100644 --- a/libheif/nclx.h +++ b/libheif/nclx.h @@ -189,7 +189,7 @@ class Box_colr : public Box Error write(StreamWriter& writer) const override; protected: - Error parse(BitstreamRange& range) override; + Error parse(BitstreamRange& range, const heif_security_limits* limits) override; private: std::shared_ptr m_color_profile; diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc index fc1abc7138..18f1a27078 100644 --- a/libheif/pixelimage.cc +++ b/libheif/pixelimage.cc @@ -259,7 +259,7 @@ bool HeifPixelImage::ImagePlane::alloc(uint32_t width, uint32_t height, heif_cha stride = m_mem_width * bytes_per_pixel; stride = (stride + alignment - 1U) & ~(alignment - 1U); - if ((MAX_MEMORY_BLOCK_SIZE - (alignment + 1)) / stride < m_mem_height) { + if ((heif_get_global_security_limits()->max_memory_block_size - (alignment + 1)) / stride < m_mem_height) { return false; } diff --git a/libheif/security_limits.cc b/libheif/security_limits.cc new file mode 100644 index 0000000000..e039293eb7 --- /dev/null +++ b/libheif/security_limits.cc @@ -0,0 +1,42 @@ +/* + * HEIF codec. + * Copyright (c) 2024 Dirk Farin + * + * This file is part of libheif. + * + * libheif is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libheif is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libheif. If not, see . + */ + +#include "security_limits.h" + + +struct heif_security_limits global_security_limits { + .version = 1, + + // --- version 1 + + // Artificial limit to avoid allocating too much memory. + // 32768^2 = 1.5 GB as YUV-4:2:0 or 4 GB as RGB32 + .max_image_size_pixels = 32768 * 32768, + .max_bayer_pattern_pixels = 16*16, + + .max_iref_references = 0, + .max_iloc_items = 0, + .max_iloc_extents_per_item = 32, + .max_children_per_box = 65536, + .max_number_of_tiles = 4096 * 4096, + + .max_color_profile_size = 100 * 1024 * 1024, // 100 MB + .max_memory_block_size = 512 * 1024 * 1024 // 512 MB +}; diff --git a/libheif/security_limits.h b/libheif/security_limits.h index 6ca8691449..2e735986d8 100644 --- a/libheif/security_limits.h +++ b/libheif/security_limits.h @@ -20,18 +20,11 @@ #ifndef LIBHEIF_SECURITY_LIMITS_H #define LIBHEIF_SECURITY_LIMITS_H +#include "libheif/heif.h" #include #include -static const size_t MAX_CHILDREN_PER_BOX = 20000; -static const int MAX_ILOC_ITEMS = 20000; -static const int MAX_ILOC_EXTENTS_PER_ITEM = 32; -static const int MAX_MEMORY_BLOCK_SIZE = 512 * 1024 * 1024; // 512 MB -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 int64_t MAX_IMAGE_SIZE = 32768 * 32768; +extern heif_security_limits global_security_limits; // Maximum nesting level of boxes in input files. // We put a limit on this to avoid unlimited stack usage by malicious input files. @@ -42,10 +35,4 @@ static const int64_t MAX_LARGE_BOX_SIZE = 0x0FFFFFFFFFFFFFFF; static const int64_t MAX_FILE_POS = 0x007FFFFFFFFFFFFFLL; // maximum file position static const int MAX_FRACTION_VALUE = 0x10000; -static const int MAX_IREF_REFERENCES = 10000; - -static const int MAX_TILD_TILES = 4100*4100; - -static const uint32_t MAX_BAYER_PATTERN_PIXELS = 16*16; // maximum size of Bayer pattern - #endif // LIBHEIF_SECURITY_LIMITS_H diff --git a/tests/avc_box.cc b/tests/avc_box.cc index 53efb5efb6..2866d3d5ad 100644 --- a/tests/avc_box.cc +++ b/tests/avc_box.cc @@ -44,7 +44,7 @@ TEST_CASE("avcC") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); diff --git a/tests/file_layout.cc b/tests/file_layout.cc index b5b496a503..084406ee8b 100644 --- a/tests/file_layout.cc +++ b/tests/file_layout.cc @@ -41,7 +41,7 @@ TEST_CASE("parse file layout") { auto reader = std::make_shared(std::move(istr)); FileLayout file; - Error err = file.read(reader); + Error err = file.read(reader, heif_get_global_security_limits()); REQUIRE(err.error_code == heif_error_Ok); diff --git a/tests/idat.cc b/tests/idat.cc index 7782516891..ca43db05b6 100644 --- a/tests/idat.cc +++ b/tests/idat.cc @@ -38,7 +38,7 @@ TEST_CASE("idat bad") { BitstreamRange range(reader, testData.size()); for (;;) { std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); if (error != Error::Ok || range.error()) { break; } diff --git a/tests/uncompressed_box.cc b/tests/uncompressed_box.cc index 76c0f2b535..6b0506010d 100644 --- a/tests/uncompressed_box.cc +++ b/tests/uncompressed_box.cc @@ -234,7 +234,7 @@ TEST_CASE("uncC_parse") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -296,7 +296,7 @@ TEST_CASE("uncC_parse_no_overflow") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -323,7 +323,7 @@ TEST_CASE("uncC_parse_excess_tile_cols") { byteArray.size(), false); BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(range.error() == 0); REQUIRE(error.error_code == 6); REQUIRE(error.sub_error_code == 1000); @@ -346,7 +346,7 @@ TEST_CASE("uncC_parse_excess_tile_rows") { byteArray.size(), false); BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(range.error() == 0); REQUIRE(error.error_code == 6); REQUIRE(error.sub_error_code == 1000); @@ -365,7 +365,7 @@ TEST_CASE("cmpC_defl") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -401,7 +401,7 @@ TEST_CASE("cmpC_zlib") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -436,7 +436,7 @@ TEST_CASE("cmpC_brot") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -475,7 +475,7 @@ TEST_CASE("icef_24_8_bit") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -513,7 +513,7 @@ TEST_CASE("icef_0_16_bit") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -555,7 +555,7 @@ TEST_CASE("icef_32bit") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -599,7 +599,7 @@ TEST_CASE("icef_uint64") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error == Error::Ok); REQUIRE(range.error() == 0); @@ -641,7 +641,7 @@ TEST_CASE("icef_bad_version") { BitstreamRange range(reader, byteArray.size()); std::shared_ptr box; - Error error = Box::read(range, &box); + Error error = Box::read(range, &box, heif_get_global_security_limits()); REQUIRE(error.error_code == heif_error_Unsupported_feature); REQUIRE(error.sub_error_code == heif_suberror_Unsupported_data_version); REQUIRE(error.message == std::string("icef box data version 1 is not implemented yet"));