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

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