Commit 7283380e for libheif
commit 7283380ec21003a6812d8a1e7e4328bdda8b2026
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Thu Apr 30 15:09:42 2026 +0200
J2K: fix integer underflow and file overread on malicious input (#1776)
diff --git a/libheif/codecs/jpeg2000_boxes.cc b/libheif/codecs/jpeg2000_boxes.cc
index d09ae507..fd88b7c2 100644
--- a/libheif/codecs/jpeg2000_boxes.cc
+++ b/libheif/codecs/jpeg2000_boxes.cc
@@ -430,7 +430,7 @@ Error JPEG2000MainHeader::parse_SIZ_segment()
heif_suberror_Invalid_J2K_codestream,
std::string("Out of range Csiz value"));
}
- if (cursor > headerData.size() - (3 * csiz)) {
+ if (3 * static_cast<size_t>(csiz) > headerData.size() - cursor) {
return Error(heif_error_Invalid_input,
heif_suberror_Invalid_J2K_codestream);
}
@@ -449,7 +449,8 @@ Error JPEG2000MainHeader::parse_SIZ_segment()
Error JPEG2000MainHeader::parse_CAP_segment_body()
{
- if (cursor > headerData.size() - 8) {
+ // Need at least Lcap (2) + Pcap (4) = 6 bytes.
+ if (headerData.size() - cursor < 6) {
return Error(heif_error_Invalid_input,
heif_suberror_Invalid_J2K_codestream);
}
@@ -459,15 +460,25 @@ Error JPEG2000MainHeader::parse_CAP_segment_body()
heif_suberror_Invalid_J2K_codestream,
std::string("Out of range Lcap value"));
}
+ // Lcap counts the Lcap field itself, so Lcap-2 bytes must follow it.
+ if (headerData.size() - cursor < static_cast<size_t>(lcap) - 2) {
+ return Error(heif_error_Invalid_input,
+ heif_suberror_Invalid_J2K_codestream);
+ }
uint32_t pcap = read32();
+ size_t segment_end = cursor + (static_cast<size_t>(lcap) - 6);
for (uint8_t i = 2; i <= 32; i++) {
- if (pcap & (1 << (32 - i))) {
+ if (pcap & (1u << (32 - i))) {
+ if (segment_end - cursor < 2) {
+ return Error(heif_error_Invalid_input,
+ heif_suberror_Invalid_J2K_codestream,
+ std::string("CAP segment Pcap inconsistent with Lcap"));
+ }
switch (i) {
case JPEG2000_Extension_Capability_HT::IDENT:
parse_Ccap15();
break;
default:
- std::cout << "unhandled extended capabilities value: " << (int)i << std::endl;
read16();
}
}
diff --git a/libheif/codecs/jpeg2000_boxes.h b/libheif/codecs/jpeg2000_boxes.h
index c313a85c..d6b5c306 100644
--- a/libheif/codecs/jpeg2000_boxes.h
+++ b/libheif/codecs/jpeg2000_boxes.h
@@ -507,7 +507,10 @@ private:
uint32_t read32()
{
- uint32_t res = (headerData[cursor] << 24) | (headerData[cursor + 1] << 16) | (headerData[cursor + 2] << 8) | headerData[cursor + 3];
+ uint32_t res = (uint32_t{headerData[cursor]} << 24) |
+ (uint32_t{headerData[cursor + 1]} << 16) |
+ (uint32_t{headerData[cursor + 2]} << 8) |
+ uint32_t{headerData[cursor + 3]};
cursor += 4;
return res;
}