diff --git a/backport-0001-CVE-2021-29463.patch b/backport-0001-CVE-2021-29463.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ea81399105e19f08b486650c1dda40b1bdda3f0 --- /dev/null +++ b/backport-0001-CVE-2021-29463.patch @@ -0,0 +1,26 @@ +From caa4e6745a76a23bb80127cf54c0d65096ae684c Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Tue, 30 Apr 2019 09:26:18 +0100 +Subject: [PATCH] Avoid negative integer overflow when `filesize < + io_->tell()`. + +This fixes #791. +--- + src/webpimage.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/webpimage.cpp b/src/webpimage.cpp +index 9d7272c..6fe2ddb 100644 +--- a/src/webpimage.cpp ++++ b/src/webpimage.cpp +@@ -45,6 +45,7 @@ + #include "tiffimage_int.hpp" + #include "convert.hpp" + #include "enforce.hpp" ++#include "safe_op.hpp" + + #include + #include +-- +2.23.0 + diff --git a/backport-0002-CVE-2021-29463.patch b/backport-0002-CVE-2021-29463.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab4e04bf87b8fdc3b3a3a6e3fa17b4bcd00a465b --- /dev/null +++ b/backport-0002-CVE-2021-29463.patch @@ -0,0 +1,116 @@ +From caa4e6745a76a23bb80127cf54c0d65096ae684c Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Tue, 30 Apr 2019 09:26:18 +0100 +Subject: [PATCH] Avoid negative integer overflow when `filesize < + io_->tell()`. + +This fixes #791. +--- + src/webpimage.cpp | 33 +++++++++++++++++++++------------ + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/src/webpimage.cpp b/src/webpimage.cpp +index 51a200b..9d7272c 100644 +--- a/src/webpimage.cpp ++++ b/src/webpimage.cpp +@@ -67,6 +67,15 @@ namespace Exiv2 { + namespace Exiv2 { + using namespace Exiv2::Internal; + ++ // This static function is a temporary fix in v0.27. In the next version, ++ // it will be added as a method of BasicIo. ++ static void readOrThrow(BasicIo& iIo, byte* buf, long rcount, ErrorCode err) { ++ const long nread = iIo.read(buf, rcount); ++ enforce(nread == rcount, err); ++ enforce(!iIo.error(), err); ++ } ++ ++ + WebPImage::WebPImage(BasicIo::AutoPtr io) + : Image(ImageType::webp, mdNone, io) + { +@@ -512,7 +521,7 @@ namespace Exiv2 { + DataBuf chunkId(5); + chunkId.pData_[4] = '\0' ; + +- io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); + + const uint32_t filesize = Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian) + 8; + enforce(filesize <= io_->size(), Exiv2::kerCorruptedMetadata); +@@ -532,8 +541,8 @@ namespace Exiv2 { + + chunkId.pData_[4] = '\0' ; + while ( !io_->eof() && (uint64_t) io_->tell() < filesize) { +- io_->readOrThrow(chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); +- io_->readOrThrow(size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); + const uint32_t size = Exiv2::getULong(size_buff, littleEndian); + enforce(io_->tell() <= filesize, Exiv2::kerCorruptedMetadata); + enforce(size <= (filesize - io_->tell()), Exiv2::kerCorruptedMetadata); +@@ -545,8 +554,8 @@ namespace Exiv2 { + + has_canvas_data = true; + byte size_buf[WEBP_TAG_SIZE]; +- +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf, &payload.pData_[4], 3); +@@ -561,7 +570,7 @@ namespace Exiv2 { + enforce(size >= 10, Exiv2::kerCorruptedMetadata); + + has_canvas_data = true; +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + byte size_buf[WEBP_TAG_SIZE]; + + // Fetch width"" +@@ -582,7 +591,7 @@ namespace Exiv2 { + byte size_buf_w[2]; + byte size_buf_h[3]; + +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf_w, &payload.pData_[1], 2); +@@ -599,8 +608,8 @@ namespace Exiv2 { + + has_canvas_data = true; + byte size_buf[WEBP_TAG_SIZE]; +- +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf, &payload.pData_[6], 3); +@@ -612,10 +621,10 @@ namespace Exiv2 { + size_buf[3] = 0; + pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1; + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ICCP)) { +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + this->setIccProfile(payload); + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF)) { +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + byte size_buff[2]; + byte exifLongHeader[] = { 0xFF, 0x01, 0xFF, 0xE1 }; +@@ -696,7 +705,7 @@ namespace Exiv2 { + + if (rawExifData) free(rawExifData); + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) { +- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + xmpPacket_.assign(reinterpret_cast(payload.pData_), payload.size_); + if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_)) { + #ifndef SUPPRESS_WARNINGS +-- +2.23.0 + diff --git a/backport-CVE-2021-29463.patch b/backport-CVE-2021-29463.patch new file mode 100644 index 0000000000000000000000000000000000000000..0acb82f0adbba2b7422d73b84b82ee5fd4efd2f4 --- /dev/null +++ b/backport-CVE-2021-29463.patch @@ -0,0 +1,123 @@ +From 783b3a6ff15ed6f82a8f8e6c8a6f3b84a9b04d4b Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Mon, 19 Apr 2021 18:06:00 +0100 +Subject: [PATCH] Improve bound checking in WebPImage::doWriteMetadata() + +--- + src/webpimage.cpp | 41 ++++++++++++++++++++++++++++++----------- + 1 file changed, 30 insertions(+), 11 deletions(-) + +diff --git a/src/webpimage.cpp b/src/webpimage.cpp +index c12e8fb..51a200b 100644 +--- a/src/webpimage.cpp ++++ b/src/webpimage.cpp +@@ -144,7 +144,7 @@ namespace Exiv2 { + DataBuf chunkId(WEBP_TAG_SIZE+1); + chunkId.pData_ [WEBP_TAG_SIZE] = '\0'; + +- io_->read(data, WEBP_TAG_SIZE * 3); ++ readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); + uint64_t filesize = Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian); + + /* Set up header */ +@@ -183,13 +183,20 @@ namespace Exiv2 { + case we have any exif or xmp data, also check + for any chunks with alpha frame/layer set */ + while ( !io_->eof() && (uint64_t) io_->tell() < filesize) { +- io_->read(chunkId.pData_, WEBP_TAG_SIZE); +- io_->read(size_buff, WEBP_TAG_SIZE); +- long size = Exiv2::getULong(size_buff, littleEndian); ++ readOrThrow(*io_, chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); ++ const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); ++ ++ // Check that `size_u32` is safe to cast to `long`. ++ enforce(size_u32 <= static_cast(std::numeric_limits::max()), ++ Exiv2::kerCorruptedMetadata); ++ const long size = static_cast(size_u32); + DataBuf payload(size); +- io_->read(payload.pData_, payload.size_); +- byte c; +- if ( payload.size_ % 2 ) io_->read(&c,1); ++ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); ++ if ( payload.size_ % 2 ) { ++ byte c; ++ readOrThrow(*io_, &c, 1, Exiv2::kerCorruptedMetadata); ++ } + + /* Chunk with information about features + used in the file. */ +@@ -197,6 +204,7 @@ namespace Exiv2 { + has_vp8x = true; + } + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_size) { ++ enforce(size >= 10, Exiv2::kerCorruptedMetadata); + has_size = true; + byte size_buf[WEBP_TAG_SIZE]; + +@@ -225,6 +233,7 @@ namespace Exiv2 { + } + #endif + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_size) { ++ enforce(size >= 10, Exiv2::kerCorruptedMetadata); + has_size = true; + byte size_buf[2]; + +@@ -242,11 +251,13 @@ namespace Exiv2 { + + /* Chunk with with lossless image data. */ + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_alpha) { ++ enforce(size >= 5, Exiv2::kerCorruptedMetadata); + if ((payload.pData_[5] & WEBP_VP8X_ALPHA_BIT) == WEBP_VP8X_ALPHA_BIT) { + has_alpha = true; + } + } + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_size) { ++ enforce(size >= 5, Exiv2::kerCorruptedMetadata); + has_size = true; + byte size_buf_w[2]; + byte size_buf_h[3]; +@@ -274,11 +285,13 @@ namespace Exiv2 { + + /* Chunk with animation frame. */ + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_alpha) { ++ enforce(size >= 6, Exiv2::kerCorruptedMetadata); + if ((payload.pData_[5] & 0x2) == 0x2) { + has_alpha = true; + } + } + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_size) { ++ enforce(size >= 12, Exiv2::kerCorruptedMetadata); + has_size = true; + byte size_buf[WEBP_TAG_SIZE]; + +@@ -307,16 +320,22 @@ namespace Exiv2 { + + io_->seek(12, BasicIo::beg); + while ( !io_->eof() && (uint64_t) io_->tell() < filesize) { +- io_->read(chunkId.pData_, 4); +- io_->read(size_buff, 4); ++ readOrThrow(*io_, chunkId.pData_, 4, Exiv2::kerCorruptedMetadata); ++ readOrThrow(*io_, size_buff, 4, Exiv2::kerCorruptedMetadata); ++ ++ const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); + +- long size = Exiv2::getULong(size_buff, littleEndian); ++ // Check that `size_u32` is safe to cast to `long`. ++ enforce(size_u32 <= static_cast(std::numeric_limits::max()), ++ Exiv2::kerCorruptedMetadata); ++ const long size = static_cast(size_u32); + + DataBuf payload(size); +- io_->read(payload.pData_, size); ++ readOrThrow(*io_, payload.pData_, size, Exiv2::kerCorruptedMetadata); + if ( io_->tell() % 2 ) io_->seek(+1,BasicIo::cur); // skip pad + + if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) { ++ enforce(size >= 1, Exiv2::kerCorruptedMetadata); + if (has_icc){ + payload.pData_[0] |= WEBP_VP8X_ICC_BIT; + } else { +-- +2.23.0 + diff --git a/backport-CVE-2021-29464.patch b/backport-CVE-2021-29464.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fcc2fff855fa6fb379e4ff20a41b77a19e5172f --- /dev/null +++ b/backport-CVE-2021-29464.patch @@ -0,0 +1,55 @@ +From f9308839198aca5e68a65194f151a1de92398f54 Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Tue, 20 Apr 2021 12:04:13 +0100 +Subject: [PATCH] Better bounds checking in Jp2Image::encodeJp2Header() + +--- + src/jp2image.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/jp2image.cpp b/src/jp2image.cpp +index 0825d99..f9be021 100644 +--- a/src/jp2image.cpp ++++ b/src/jp2image.cpp +@@ -650,6 +650,7 @@ namespace Exiv2 + #ifdef DEBUG + std::cout << "Jp2Image::encodeJp2Header subbox: "<< toAscii(subBox.type) << " length = " << subBox.length << std::endl; + #endif ++ enforce(subBox.length <= length - count, Exiv2::kerCorruptedMetadata); + count += subBox.length; + newBox.type = subBox.type; + } else { +@@ -658,12 +659,13 @@ namespace Exiv2 + count = length; + } + +- int32_t newlen = subBox.length; ++ uint32_t newlen = subBox.length; + if ( newBox.type == kJp2BoxTypeColorHeader ) { + bWroteColor = true ; + if ( ! iccProfileDefined() ) { + const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid"; + uint32_t psize = 15; ++ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata); + ul2Data((byte*)&newBox.length,psize ,bigEndian); + ul2Data((byte*)&newBox.type ,newBox.type,bigEndian); + ::memcpy(output.pData_+outlen ,&newBox ,sizeof(newBox)); +@@ -672,6 +674,7 @@ namespace Exiv2 + } else { + const char* pad = "\0x02\x00\x00"; + uint32_t psize = 3; ++ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata); + ul2Data((byte*)&newBox.length,psize+iccProfile_.size_,bigEndian); + ul2Data((byte*)&newBox.type,newBox.type,bigEndian); + ::memcpy(output.pData_+outlen ,&newBox ,sizeof(newBox) ); +@@ -680,6 +683,7 @@ namespace Exiv2 + newlen = psize + iccProfile_.size_; + } + } else { ++ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata); + ::memcpy(output.pData_+outlen,boxBuf.pData_+inlen,subBox.length); + } + +-- +2.23.0 + diff --git a/backport-CVE-2021-29473.patch b/backport-CVE-2021-29473.patch new file mode 100644 index 0000000000000000000000000000000000000000..f71c7a1bafeb036236218024ced4a349cba337d4 --- /dev/null +++ b/backport-CVE-2021-29473.patch @@ -0,0 +1,24 @@ +From e6a0982f7cd9282052b6e3485a458d60629ffa0b Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Fri, 23 Apr 2021 11:44:44 +0100 +Subject: [PATCH] Add bounds check in Jp2Image::doWriteMetadata(). + +--- + src/jp2image.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/jp2image.cpp b/src/jp2image.cpp +index f9be021..40eca0d 100644 +--- a/src/jp2image.cpp ++++ b/src/jp2image.cpp +@@ -888,6 +888,7 @@ namespace Exiv2 + + case kJp2BoxTypeUuid: + { ++ enforce(boxBuf.size_ >= 24, Exiv2::kerCorruptedMetadata); + if(memcmp(boxBuf.pData_ + 8, kJp2UuidExif, 16) == 0) + { + #ifdef DEBUG +-- +2.23.0 + diff --git a/exiv2.spec b/exiv2.spec index 610b7d777ded6db7ca6733a69bca1de812ec52f6..585e7402b62e0932fffdcf07db6ee0a8c69f3ae1 100644 --- a/exiv2.spec +++ b/exiv2.spec @@ -1,6 +1,6 @@ Name: exiv2 Version: 0.26 -Release: 24 +Release: 25 Summary: Exif, IPTC and XMP metadata and the ICC Profile License: GPLv2+ URL: http://www.exiv2.org/ @@ -62,6 +62,11 @@ Patch6029: backport-CVE-2021-29457.patch Patch6030: backport-CVE-2021-29458.patch Patch6031: backport-CVE-2021-3482.patch Patch6032: backport-CVE-2021-29470.patch +Patch6033: backport-0001-CVE-2021-29463.patch +Patch6034: backport-0002-CVE-2021-29463.patch +Patch6035: backport-CVE-2021-29464.patch +Patch6036: backport-CVE-2021-29463.patch +Patch6037: backport-CVE-2021-29473.patch Provides: exiv2-libs Obsoletes: exiv2-libs @@ -125,6 +130,12 @@ test -x %{buildroot}%{_libdir}/libexiv2.so %{_datadir}/doc/html/ %changelog +* Wed May 12 2021 wangkerong - 0.26-25 +- Type:cves +- ID:CVE-2021-29464 CVE-2021-29463 CVE-2021-29473 +- SUG:NA +- DESC:fix CVE-2021-29464,CVE-2021-29463,CVE-2021-29473 + * Sat May 08 2021 wangkerong - 0.26-24 - Type:cves - ID:CVE-2021-29470 CVE-2021-3482