Fix CVE-2017-14859, CVE-2017-14862 and CVE-2017-14864. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14859 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14862 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14864 Copied from upstream: https://github.com/Exiv2/exiv2/commit/8a586c74bbe3fbca64e86e42a42282c73f427607 From 8a586c74bbe3fbca64e86e42a42282c73f427607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com> Date: Sat, 7 Oct 2017 23:08:36 +0200 Subject: [PATCH] Fix for CVE-2017-14864, CVE-2017-14862 and CVE-2017-14859 The invalid memory dereference in Exiv2::getULong()/Exiv2::StringValueBase::read()/Exiv2::DataValue::read() is caused further up the call-stack, by v->read(pData, size, byteOrder) in TiffReader::readTiffEntry() passing an invalid pData pointer (pData points outside of the Tiff file). pData can be set out of bounds in the (size > 4) branch where baseOffset() and offset are added to pData_ without checking whether the result is still in the file. As offset comes from an untrusted source, an attacker can craft an arbitrarily large offset into the file. This commit adds a check into the problematic branch, whether the result of the addition would be out of bounds of the Tiff file. Furthermore the whole operation is checked for possible overflows. --- src/tiffvisitor.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp index 4ab733d4..ef13542e 100644 --- a/src/tiffvisitor.cpp +++ b/src/tiffvisitor.cpp @@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$") #include <iostream> #include <iomanip> #include <cassert> +#include <limits> // ***************************************************************************** namespace { @@ -1517,7 +1518,19 @@ namespace Exiv2 { size = 0; } if (size > 4) { + // setting pData to pData_ + baseOffset() + offset can result in pData pointing to invalid memory, + // as offset can be arbitrarily large + if ((static_cast<uintptr_t>(baseOffset()) > std::numeric_limits<uintptr_t>::max() - static_cast<uintptr_t>(offset)) + || (static_cast<uintptr_t>(baseOffset() + offset) > std::numeric_limits<uintptr_t>::max() - reinterpret_cast<uintptr_t>(pData_))) + { + throw Error(59); + } + if (pData_ + static_cast<uintptr_t>(baseOffset()) + static_cast<uintptr_t>(offset) > pLast_) { + throw Error(58); + } pData = const_cast<byte*>(pData_) + baseOffset() + offset; + + // check for size being invalid if (size > static_cast<uint32_t>(pLast_ - pData)) { #ifndef SUPPRESS_WARNINGS EXV_ERROR << "Upper boundary of data for "