已合并
Fix heif bugs 0909 #5861
Fix heif bugs 0909 #5861
已合并
hehaokun创建于 9月9日
共 4 个文件变更+33-6
@@ -92,7 +92,7 @@ public:
92 return (int) children_.size() - 1;92 return (int) children_.size() - 1;
93 }93 }
94 94 
95- const uint32_t MAX_RECURSION_COUNT = 300;95+ static const uint32_t MAX_RECURSION_COUNT = 300;
96 96 
97private:97private:
98 uint64_t boxSize_ = 0;98 uint64_t boxSize_ = 0;
@@ -144,7 +144,7 @@ const std::map<PixelFormat, GraphicPixelFormat> SURFACE_FORMAT_MAP = {
144#endif144#endif
145 145 
146namespace {146namespace {
147- const static size_t DEFAULT_OUTPUT_SIZE = 35 * 1024 * 1024; // 35M147+ const static size_t DEFAULT_OUTPUT_SIZE = 80 * 1024 * 1024; // 80M
148 const static uint16_t STATIC_METADATA_COLOR_SCALE = 50000;148 const static uint16_t STATIC_METADATA_COLOR_SCALE = 50000;
149 const static uint16_t STATIC_METADATA_LUM_SCALE = 10000;149 const static uint16_t STATIC_METADATA_LUM_SCALE = 10000;
150 const static uint8_t INDEX_ZERO = 0;150 const static uint8_t INDEX_ZERO = 0;
@@ -49,6 +49,17 @@ heif_error HeifIlocBox::ParseExtents(Item& item, HeifStreamReader &reader,
49 if (extentNum > MAX_HEIF_EXTENT_NUM) {49 if (extentNum > MAX_HEIF_EXTENT_NUM) {
50 return heif_error_extent_num_too_large;50 return heif_error_extent_num_too_large;
51 }51 }
52+ // Cross-validate: each extent consumes indexSize + offsetSize + lengthSize bytes.
53+ // When all field widths are 0, extents consume zero input but still allocate a 48-byte
54+ // struct each, causing uncontrolled memory allocation. Reject such zero-width extents
55+ // with a non-trivial count since they carry no useful data.
56+ size_t perExtentBytes = static_cast<size_t>(indexSize) + static_cast<size_t>(offsetSize) +
57+ static_cast<size_t>(lengthSize);
58+ if (perExtentBytes == 0 && extentNum > 1) {
59+ return heif_error_invalid_data;
60+ } else if (static_cast<size_t>(extentNum) * perExtentBytes > reader.GetRemainSize()) {
61+ return heif_error_invalid_data;
62+ }
52 item.extents.resize(extentNum);63 item.extents.resize(extentNum);
53 for (int extentIndex = 0; extentIndex < extentNum; extentIndex++) {64 for (int extentIndex = 0; extentIndex < extentNum; extentIndex++) {
54 // indexSize is taken from the set {0, 4, 8} and indicates the length in bytes of 'index'65 // indexSize is taken from the set {0, 4, 8} and indicates the length in bytes of 'index'
@@ -102,6 +113,18 @@ heif_error HeifIlocBox::ParseContent(HeifStreamReader &reader)
102 if (itemCount > MAX_HEIF_ITEM_COUNT) {113 if (itemCount > MAX_HEIF_ITEM_COUNT) {
103 return heif_error_too_many_item;114 return heif_error_too_many_item;
104 }115 }
116+ // Cross-validate declared item count against remaining input bytes to prevent memory exhaustion.
117+ // Only validate per-item fixed headers here; per-extent input bytes are validated in ParseExtents
118+ // for each item individually.
119+ // Per-item fixed header: itemId(2 or 4) + constructionMethod(0 or 2) + dataRefIndex(2) +
120+ // baseOffset(baseOffsetSize) + extent_count(2)
121+ size_t perItemFixed = (GetVersion() < HEIF_BOX_VERSION_TWO ? UINT16_BYTES_NUM : UINT32_BYTES_NUM) +
122+ (GetVersion() >= HEIF_BOX_VERSION_ONE ? UINT16_BYTES_NUM : 0) +
123+ UINT16_BYTES_NUM + static_cast<size_t>(baseOffsetSize) + UINT16_BYTES_NUM;
124+ size_t totalMinBytes = static_cast<size_t>(itemCount) * perItemFixed;
125+ if (totalMinBytes > reader.GetRemainSize()) {
126+ return heif_error_invalid_data;
127+ }
105 for (uint32_t itemIndex = 0; itemIndex < itemCount; ++itemIndex) {128 for (uint32_t itemIndex = 0; itemIndex < itemCount; ++itemIndex) {
106 Item item;129 Item item;
107 item.itemId = GetVersion() < HEIF_BOX_VERSION_TWO ? reader.Read16() : reader.Read32();130 item.itemId = GetVersion() < HEIF_BOX_VERSION_TWO ? reader.Read16() : reader.Read32();
@@ -297,7 +297,8 @@ heif_error HeifDrefBox::ParseContent(HeifStreamReader &reader)
297 return heif_error_invalid_dref;297 return heif_error_invalid_dref;
298 }298 }
299 for (uint32_t i = 0; i < entryCount_; i++) {299 for (uint32_t i = 0; i < entryCount_; i++) {
300- uint32_t recursionCount = recursionDepth_;300+ uint32_t recursionCount = recursionDepth_ + 1;
301+ CHECK_ERROR_RETURN_RET(recursionCount > MAX_RECURSION_COUNT, heif_error_too_many_recursion);
301 std::shared_ptr<HeifBox> entry;302 std::shared_ptr<HeifBox> entry;
302 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);303 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);
303 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);304 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);
@@ -330,7 +331,8 @@ heif_error HeifStsdBox::ParseContent(HeifStreamReader &reader)
330 return heif_error_invalid_stsd;331 return heif_error_invalid_stsd;
331 }332 }
332 for (uint32_t i = 0; i < entryCount_; i++) {333 for (uint32_t i = 0; i < entryCount_; i++) {
333- uint32_t recursionCount = recursionDepth_;334+ uint32_t recursionCount = recursionDepth_ + 1;
335+ CHECK_ERROR_RETURN_RET(recursionCount > MAX_RECURSION_COUNT, heif_error_too_many_recursion);
334 std::shared_ptr<HeifBox> entry;336 std::shared_ptr<HeifBox> entry;
335 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);337 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);
336 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);338 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);
@@ -599,7 +601,8 @@ heif_error HeifHvc1Box::ParseContent(HeifStreamReader &reader)
599 for (uint32_t i = 0; i < HVC1_SKIP_OFFSET; i++) {601 for (uint32_t i = 0; i < HVC1_SKIP_OFFSET; i++) {
600 reader.Read8();602 reader.Read8();
601 }603 }
602- uint32_t recursionCount = recursionDepth_;604+ uint32_t recursionCount = recursionDepth_ + 1;
605+ CHECK_ERROR_RETURN_RET(recursionCount > MAX_RECURSION_COUNT, heif_error_too_many_recursion);
603 heif_error error = HeifBox::MakeFromReader(reader, &hvccBox_, recursionCount);606 heif_error error = HeifBox::MakeFromReader(reader, &hvccBox_, recursionCount);
604 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);607 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);
605 return reader.GetError();608 return reader.GetError();
@@ -627,7 +630,8 @@ heif_error HeifAv01Box::ParseContent(HeifStreamReader &reader)
627 depth_ = reader.Read16();630 depth_ = reader.Read16();
628 SkipBytes(reader, PRE_DEFINED3_SIZE);631 SkipBytes(reader, PRE_DEFINED3_SIZE);
629 632 
630- uint32_t recursionCount = recursionDepth_;633+ uint32_t recursionCount = recursionDepth_ + 1;
634+ CHECK_ERROR_RETURN_RET(recursionCount > MAX_RECURSION_COUNT, heif_error_too_many_recursion);
631 heif_error error = HeifBox::MakeFromReader(reader, &av1cBox_, recursionCount);635 heif_error error = HeifBox::MakeFromReader(reader, &av1cBox_, recursionCount);
632 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);636 CHECK_ERROR_RETURN_RET(error != heif_error_ok, error);
633 return reader.GetError();637 return reader.GetError();