From 2fa930bf28fc95903ecc8dc37c802376e8c78deb Mon Sep 17 00:00:00 2001 From: Vchanger <348085547@qq.com> Date: Wed, 29 Apr 2020 11:49:10 +0800 Subject: [PATCH] exiv2: fix CVE-2019-13111 --- CVE-2019-13111.patch | 251 +++++++++++++++++++++++++++++++++++++++++++ exiv2.spec | 9 +- 2 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 CVE-2019-13111.patch diff --git a/CVE-2019-13111.patch b/CVE-2019-13111.patch new file mode 100644 index 0000000..a73c78f --- /dev/null +++ b/CVE-2019-13111.patch @@ -0,0 +1,251 @@ +From 6a2364d4694f176e9f81ab16d4f147ddb34ce625 Mon Sep 17 00:00:00 2001 +From: Kevin Backhouse +Date: Fri, 26 Apr 2019 10:21:46 +0100 +Subject: [PATCH] Avoid negative integer overflow when `filesize < + io_->tell()`. + +This fixes #791. +--- + include/exiv2/basicio.hpp | 21 +++++++++++++++++++++ + include/exiv2/webpimage.hpp | 2 +- + src/basicio.cpp | 14 ++++++++++++++ + src/webpimage.cpp | 26 +++++++++++++++----------- + test/data/issue_791_poc1.webp | Bin 0 -> 28 bytes + tests/bugfixes/github/test_issue_791.py | 27 +++++++++++++++++++++++++++ + 6 files changed, 78 insertions(+), 12 deletions(-) + create mode 100644 test/data/issue_791_poc1.webp + create mode 100644 tests/bugfixes/github/test_issue_791.py + +diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp +index 95713bf..2f00b4d 100644 +--- a/include/exiv2/basicio.hpp ++++ b/include/exiv2/basicio.hpp +@@ -29,6 +29,7 @@ + // included header files + #include "types.hpp" + #include "futils.hpp" ++#include "error.hpp" + + // + standard includes + #include +@@ -155,6 +156,26 @@ namespace Exiv2 { + */ + virtual long read(byte* buf, long rcount) = 0; + /*! ++ @brief Read data from the IO source. Reading starts at the current ++ IO position and the position is advanced by the number of bytes ++ read. Throw an exception if not enough bytes are available. ++ @param rcount Number of bytes to read. ++ @param err ErrorCode to throw if not enough bytes are available. ++ @return DataBuf instance containing the bytes read. ++ */ ++ DataBuf readOrThrow(long rcount, ErrorCode err); ++ /*! ++ @brief Read data from the IO source. Reading starts at the current ++ IO position and the position is advanced by the number of bytes ++ read. Throw an exception if not enough bytes are available. ++ @param buf Pointer to a block of memory into which the read data ++ is stored. The memory block must be at least \em rcount bytes ++ long. ++ @param err ErrorCode to throw if not enough bytes are available. ++ @param rcount Number of bytes to read. ++ */ ++ void readOrThrow(byte* buf, long rcount, ErrorCode err); ++ /*! + @brief Read one byte from the IO source. Current IO position is + advanced by one byte. + @return The byte read from the IO source if successful;
+diff --git a/include/exiv2/webpimage.hpp b/include/exiv2/webpimage.hpp +index e0b2df3..2088969 100644 +--- a/include/exiv2/webpimage.hpp ++++ b/include/exiv2/webpimage.hpp +@@ -95,7 +95,7 @@ namespace Exiv2 { + byte *header, long header_size); + bool equalsWebPTag(Exiv2::DataBuf& buf ,const char* str); + void debugPrintHex(byte *data, long size); +- void decodeChunks(uint64_t filesize); ++ void decodeChunks(uint32_t filesize); + void inject_VP8X(BasicIo& iIo, bool has_xmp, bool has_exif, + bool has_alpha, bool has_icc, int width, + int height); +diff --git a/src/basicio.cpp b/src/basicio.cpp +index f2e1518..790582c 100644 +--- a/src/basicio.cpp ++++ b/src/basicio.cpp +@@ -33,6 +33,7 @@ EXIV2_RCSID("@(#) $Id$") + #include "futils.hpp" + #include "types.hpp" + #include "error.hpp" ++#include "enforce.hpp" + #include "http.hpp" + #include "properties.hpp" + +@@ -84,6 +85,19 @@ namespace Exiv2 { + { + } + ++ DataBuf BasicIo::readOrThrow(long rcount, ErrorCode err) { ++ DataBuf result = read(rcount); ++ enforce(result.size_ == rcount, err); ++ enforce(!error(), err); ++ return result; ++ } ++ ++ void BasicIo::readOrThrow(byte* buf, long rcount, ErrorCode err) { ++ const long nread = read(buf, rcount); ++ enforce(nread == rcount, err); ++ enforce(!error(), err); ++ } ++ + //! Internal Pimpl structure of class FileIo. + class FileIo::Impl { + public: +diff --git a/src/webpimage.cpp b/src/webpimage.cpp +index 5f88556..1171efe 100644 +--- a/src/webpimage.cpp ++++ b/src/webpimage.cpp +@@ -493,7 +493,7 @@ namespace Exiv2 { + DataBuf chunkId(5); + chunkId.pData_[4] = '\0' ; + +- io_->read(data, WEBP_TAG_SIZE * 3); ++ io_->readOrThrow(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); +@@ -501,7 +501,7 @@ namespace Exiv2 { + + } // WebPImage::readMetadata + +- void WebPImage::decodeChunks(uint64_t filesize) ++ void WebPImage::decodeChunks(uint32_t filesize) + { + DataBuf chunkId(5); + byte size_buff[WEBP_TAG_SIZE]; +@@ -513,9 +513,10 @@ namespace Exiv2 { + + chunkId.pData_[4] = '\0' ; + while ( !io_->eof() && (uint64_t) io_->tell() < filesize) { +- io_->read(chunkId.pData_, WEBP_TAG_SIZE); +- io_->read(size_buff, WEBP_TAG_SIZE); ++ io_->readOrThrow(chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); ++ io_->readOrThrow(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); + + DataBuf payload(size); +@@ -526,7 +527,7 @@ namespace Exiv2 { + has_canvas_data = true; + byte size_buf[WEBP_TAG_SIZE]; + +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf, &payload.pData_[4], 3); +@@ -541,7 +542,7 @@ namespace Exiv2 { + enforce(size >= 10, Exiv2::kerCorruptedMetadata); + + has_canvas_data = true; +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + byte size_buf[WEBP_TAG_SIZE]; + + // Fetch width"" +@@ -562,7 +563,7 @@ namespace Exiv2 { + byte size_buf_w[2]; + byte size_buf_h[3]; + +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf_w, &payload.pData_[1], 2); +@@ -580,7 +581,7 @@ namespace Exiv2 { + has_canvas_data = true; + byte size_buf[WEBP_TAG_SIZE]; + +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + // Fetch width + memcpy(&size_buf, &payload.pData_[6], 3); +@@ -592,10 +593,10 @@ namespace Exiv2 { + size_buf[3] = 0; + pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1; + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ICCP)) { +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + this->setIccProfile(payload); + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF)) { +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); + + byte size_buff[2]; + byte exifLongHeader[] = { 0xFF, 0x01, 0xFF, 0xE1 }; +@@ -676,7 +677,7 @@ namespace Exiv2 { + + if (rawExifData) free(rawExifData); + } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) { +- io_->read(payload.pData_, payload.size_); ++ io_->readOrThrow(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 +@@ -709,6 +710,9 @@ namespace Exiv2 { + + bool isWebPType(BasicIo& iIo, bool /*advance*/) + { ++ if (iIo.size() < 12) { ++ return false; ++ } + const int32_t len = 4; + const unsigned char RiffImageId[4] = { 'R', 'I', 'F' ,'F'}; + const unsigned char WebPImageId[4] = { 'W', 'E', 'B' ,'P'}; +diff --git a/test/data/issue_791_poc1.webp b/test/data/issue_791_poc1.webp +new file mode 100644 +index 0000000000000000000000000000000000000000..a246a22d8fddc846617b5edaa49aee67d2849898 +GIT binary patch +literal 28 +gcmWIYbaUfoU| - 0.26-19 +- Type:cves +- ID:CVE-2019-13111 +- SUG:NA +- DESC:fix CVE-2019-13111 + * Thu Apr 16 2020 chenzhen - 0.26-18 - Type:cves - ID:CVE-2018-11037 -- Gitee