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

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