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