Commit ecffcfc8 for libheif
commit ecffcfc85e82735e3d7b611fc5378566eebb739d
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Thu Jul 2 12:20:53 2026 +0200
Resolve 'mini' and 'moov' boxes with size 0 to end of file (#1857)
Apply the same handling that was added for the 'meta' box: a top-level
'mini' or 'moov' box with a box size of 0 extends to the end of the file
(ISO/IEC 14496-12 clause 4.2), which is legal for the last box. Resolve
the size via request_range() and parse normally, instead of rejecting
the file outright.
This removes the remaining "Cannot read <box> with unspecified size"
TODOs in FileLayout::read(). The known-size paths are unchanged.
diff --git a/libheif/file_layout.cc b/libheif/file_layout.cc
index d66c20a6..387331c4 100644
--- a/libheif/file_layout.cc
+++ b/libheif/file_layout.cc
@@ -176,19 +176,29 @@ Error FileLayout::read(const std::shared_ptr<StreamReader>& stream, const heif_s
// TODO: this is basically the same as the meta box case above, with different error handling.
if (box_header.get_short_type() == fourcc("mini")) {
const uint64_t mini_box_start = next_box_start;
- if (box_header.get_box_size() == 0) {
- // TODO: get file-size from stream and compute box size
- return {heif_error_Invalid_input,
- heif_suberror_Invalid_mini_box,
- "Cannot read mini box with unspecified size"};
+ uint64_t end_of_mini_box;
+ if (box_header.get_box_size() == BoxHeader::size_until_end_of_file) {
+ // A box size of 0 means the box extends to the end of the file
+ // (ISO/IEC 14496-12 clause 4.2), which is legal for the last box.
+ // Resolve it to the file size.
+ end_of_mini_box = m_stream_reader->request_range(mini_box_start,
+ std::numeric_limits<uint64_t>::max());
+ m_max_length = end_of_mini_box;
+ if (end_of_mini_box <= mini_box_start) {
+ return {heif_error_Invalid_input,
+ heif_suberror_Invalid_mini_box,
+ "Cannot read mini box with unspecified size"};
+ }
}
- uint64_t end_of_mini_box = box_header.get_box_size();
- if (end_of_mini_box > std::numeric_limits<uint64_t>::max() - mini_box_start) {
- return {heif_error_Invalid_input,
- heif_suberror_Invalid_mini_box,
- "Cannot read mini box with invalid size"};
+ else {
+ end_of_mini_box = box_header.get_box_size();
+ if (end_of_mini_box > std::numeric_limits<uint64_t>::max() - mini_box_start) {
+ return {heif_error_Invalid_input,
+ heif_suberror_Invalid_mini_box,
+ "Cannot read mini box with invalid size"};
+ }
+ end_of_mini_box += mini_box_start;
}
- end_of_mini_box += mini_box_start;
if (m_max_length < end_of_mini_box) {
m_max_length = m_stream_reader->request_range(mini_box_start, end_of_mini_box);
}
@@ -213,20 +223,29 @@ Error FileLayout::read(const std::shared_ptr<StreamReader>& stream, const heif_s
if (box_header.get_short_type() == fourcc("moov")) {
const uint64_t moov_box_start = next_box_start;
- if (box_header.get_box_size() == 0) {
- // TODO: get file-size from stream and compute box size
- return {heif_error_Invalid_input,
- heif_suberror_No_moov_box,
- "Cannot read moov box with unspecified size"};
+ uint64_t end_of_moov_box;
+ if (box_header.get_box_size() == BoxHeader::size_until_end_of_file) {
+ // A box size of 0 means the box extends to the end of the file
+ // (ISO/IEC 14496-12 clause 4.2), which is legal for the last box.
+ // Resolve it to the file size.
+ end_of_moov_box = m_stream_reader->request_range(moov_box_start,
+ std::numeric_limits<uint64_t>::max());
+ m_max_length = end_of_moov_box;
+ if (end_of_moov_box <= moov_box_start) {
+ return {heif_error_Invalid_input,
+ heif_suberror_No_moov_box,
+ "Cannot read moov box with unspecified size"};
+ }
}
-
- uint64_t end_of_moov_box = box_header.get_box_size();
- if (end_of_moov_box > std::numeric_limits<uint64_t>::max() - moov_box_start) {
- return {heif_error_Invalid_input,
- heif_suberror_No_moov_box,
- "Cannot read moov box with invalid size"};
+ else {
+ end_of_moov_box = box_header.get_box_size();
+ if (end_of_moov_box > std::numeric_limits<uint64_t>::max() - moov_box_start) {
+ return {heif_error_Invalid_input,
+ heif_suberror_No_moov_box,
+ "Cannot read moov box with invalid size"};
+ }
+ end_of_moov_box += moov_box_start;
}
- end_of_moov_box += moov_box_start;
if (m_max_length < end_of_moov_box) {
m_max_length = m_stream_reader->request_range(moov_box_start, end_of_moov_box);
}