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

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