Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
exiv2.26596
CVE-2019-13111.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2019-13111.patch of Package exiv2.26596
From caa4e6745a76a23bb80127cf54c0d65096ae684c Mon Sep 17 00:00:00 2001 From: Kevin Backhouse <kev@semmle.com> Date: Tue, 30 Apr 2019 09:26:18 +0100 Subject: [PATCH] Avoid negative integer overflow when `filesize < io_->tell()`. This fixes #791. --- include/exiv2/webpimage.hpp | 2 +- src/webpimage.cpp | 35 ++++++++++++++++-------- test/data/issue_791_poc1.webp | Bin 0 -> 28 bytes tests/bugfixes/github/test_issue_791.py | 27 ++++++++++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 test/data/issue_791_poc1.webp create mode 100644 tests/bugfixes/github/test_issue_791.py Index: exiv2-0.26/include/exiv2/webpimage.hpp =================================================================== --- exiv2-0.26.orig/include/exiv2/webpimage.hpp +++ exiv2-0.26/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); Index: exiv2-0.26/src/webpimage.cpp =================================================================== --- exiv2-0.26.orig/src/webpimage.cpp +++ exiv2-0.26/src/webpimage.cpp @@ -66,6 +66,14 @@ 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) { @@ -477,6 +485,7 @@ namespace Exiv2 { /* =========================================== */ + void WebPImage::readMetadata() { if (io_->open() != 0) throw Error(9, io_->path(), strError()); @@ -492,7 +501,7 @@ namespace Exiv2 { DataBuf chunkId(5); chunkId.pData_[4] = '\0' ; - io_->read(data, WEBP_TAG_SIZE * 3); + 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); @@ -500,7 +509,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]; @@ -512,9 +521,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); + 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); DataBuf payload(size); @@ -523,7 +533,7 @@ namespace Exiv2 { has_canvas_data = true; byte size_buf[WEBP_TAG_SIZE]; - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf, &payload.pData_[4], 3); @@ -536,7 +546,7 @@ namespace Exiv2 { pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1; } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_canvas_data) { has_canvas_data = true; - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); byte size_buf[WEBP_TAG_SIZE]; // Fetch width"" @@ -555,7 +565,7 @@ namespace Exiv2 { byte size_buf_w[2]; byte size_buf_h[3]; - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf_w, &payload.pData_[1], 2); @@ -571,7 +581,7 @@ namespace Exiv2 { has_canvas_data = true; byte size_buf[WEBP_TAG_SIZE]; - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf, &payload.pData_[6], 3); @@ -583,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_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); this->setIccProfile(payload); } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF)) { - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); byte size_buff[2]; byte exifLongHeader[] = { 0xFF, 0x01, 0xFF, 0xE1 }; @@ -667,7 +677,7 @@ namespace Exiv2 { if (rawExifData) free(rawExifData); } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) { - io_->read(payload.pData_, payload.size_); + readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata); xmpPacket_.assign(reinterpret_cast<char*>(payload.pData_), payload.size_); if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_)) { #ifndef SUPPRESS_WARNINGS @@ -700,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'}; Index: exiv2-0.26/tests/bugfixes/github/test_issue_791.py =================================================================== --- /dev/null +++ exiv2-0.26/tests/bugfixes/github/test_issue_791.py @@ -0,0 +1,27 @@ +import system_tests + + +class IntegerOverflowInWebpImageReadMetadata( + metaclass=system_tests.CaseMeta): + """ + Regression test for the bug described in: + https://github.com/Exiv2/exiv2/issues/791 + + Due to an integer overflow bug (#791), this test triggers a 4GB + memory allocation. So the test will fail with a std::bad_alloc + exception if less than 4GB is available. On Linux, you can use + `ulimit -v 4000000` to reduce the available memory to slightly + less than 4GB. + """ + url = "https://github.com/Exiv2/exiv2/issues/791" + + filename = system_tests.path( + "$data_path/issue_791_poc1.webp" + ) + commands = ["$exiv2 $filename"] + stdout = [""] + stderr = ["""Exiv2 exception in print action for file $filename: +corrupted image metadata +""" +] + retval = [1]
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor