Blame SOURCES/exiv2-CVE-2017-14864-CVE-2017-14862-CVE-2017-14859.patch

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