Skip to content

Commit

Permalink
fix bits/bytes confusion and disable security limits for edge-case test
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Oct 20, 2024
1 parent 6ace1c0 commit 338a9e4
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 10 deletions.
6 changes: 6 additions & 0 deletions libheif/api/libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,12 @@ const struct heif_security_limits* heif_get_global_security_limits()
}


const struct heif_security_limits* heif_get_disabled_security_limits()
{
return &disabled_security_limits;
}


struct heif_security_limits* heif_context_get_security_limits(const struct heif_context* ctx)
{
if (!ctx) {
Expand Down
4 changes: 4 additions & 0 deletions libheif/api/libheif/heif.h
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,10 @@ struct heif_security_limits {
LIBHEIF_API
const struct heif_security_limits* heif_get_global_security_limits();

// Returns a set of fully disabled security limits. Use with care and only after user confirmation.
LIBHEIF_API
const struct heif_security_limits* heif_get_disabled_security_limits();

// Returns the security limits for a heif_context.
// By default, the limits are set to the global limits, but you can change them in the returned object.
LIBHEIF_API
Expand Down
2 changes: 2 additions & 0 deletions libheif/bitstream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ uint64_t BitstreamRange::read_uint(int len)
return read8();
case 16:
return read16();
case 24:
return read24();
case 32:
return read32();
case 64:
Expand Down
18 changes: 9 additions & 9 deletions libheif/codecs/uncompressed/unc_boxes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,8 @@ Error Box_cmpC::write(StreamWriter& writer) const
}


static uint8_t unit_offset_length_table[] = { 0,2,3,4,8 };
static uint8_t unit_size_length_table[] = { 1,2,3,4,8 };
static uint8_t unit_offset_bits_table[] = {0, 16, 24, 32, 64 };
static uint8_t unit_size_bits_table[] = {8, 16, 24, 32, 64 };

Error Box_icef::parse(BitstreamRange& range, const heif_security_limits* limits)
{
Expand All @@ -513,14 +513,14 @@ Error Box_icef::parse(BitstreamRange& range, const heif_security_limits* limits)

// --- precompute fields lengths

uint8_t unit_offset_length = unit_offset_length_table[unit_offset_code];
uint8_t unit_size_length = unit_size_length_table[unit_size_code];
uint8_t unit_offset_bits = unit_offset_bits_table[unit_offset_code];
uint8_t unit_size_bits = unit_size_bits_table[unit_size_code];

// --- check if box is large enough for all the data

uint64_t data_size = num_compressed_units * (unit_offset_length + unit_size_length);
if (data_size > range.get_remaining_bytes()) {
uint64_t contained_units = range.get_remaining_bytes() / (unit_offset_length + unit_size_length);
uint64_t data_size_bytes = num_compressed_units * (unit_offset_bits + unit_size_bits) / 8;
if (data_size_bytes > range.get_remaining_bytes()) {
uint64_t contained_units = range.get_remaining_bytes() / ((unit_offset_bits + unit_size_bits) * 8);
std::stringstream sstr;
sstr << "icef box declares " << num_compressed_units << " units, but only " << contained_units
<< " were contained in the file";
Expand All @@ -540,10 +540,10 @@ Error Box_icef::parse(BitstreamRange& range, const heif_security_limits* limits)
if (unit_offset_code == 0) {
unitInfo.unit_offset = implied_offset;
} else {
unitInfo.unit_offset = range.read_uint(unit_offset_length);
unitInfo.unit_offset = range.read_uint(unit_offset_bits);
}

unitInfo.unit_size = range.read_uint(unit_size_length);
unitInfo.unit_size = range.read_uint(unit_size_bits);

if (unitInfo.unit_size >= UINT64_MAX - implied_offset) {
return {heif_error_Invalid_input,
Expand Down
5 changes: 5 additions & 0 deletions libheif/security_limits.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ struct heif_security_limits global_security_limits {
};


struct heif_security_limits disabled_security_limits{
.version = 1
};


Error check_for_valid_image_size(const heif_security_limits* limits, uint32_t width, uint32_t height)
{
uint64_t maximum_image_size_limit = limits->max_image_size_pixels;
Expand Down
1 change: 1 addition & 0 deletions libheif/security_limits.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@


extern heif_security_limits global_security_limits;
extern heif_security_limits disabled_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.
Expand Down
2 changes: 1 addition & 1 deletion tests/uncompressed_box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ TEST_CASE("uncC_parse_no_overflow") {

BitstreamRange range(reader, byteArray.size());
std::shared_ptr<Box> box;
Error error = Box::read(range, &box, heif_get_global_security_limits());
Error error = Box::read(range, &box, heif_get_disabled_security_limits());
REQUIRE(error == Error::Ok);
REQUIRE(range.error() == 0);

Expand Down

0 comments on commit 338a9e4

Please sign in to comment.