1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
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 "
|