Blame SOURCES/exiv2-CVE-2017-17725.patch

fac8f1
diff --git a/src/actions.cpp b/src/actions.cpp
fac8f1
index 35c7965..cb905f6 100644
fac8f1
--- a/src/actions.cpp
fac8f1
+++ b/src/actions.cpp
fac8f1
@@ -59,6 +59,7 @@ EXIV2_RCSID("@(#) $Id: actions.cpp 4719 2017-03-08 20:42:28Z robinwmills $")
fac8f1
 #include <ctime>
fac8f1
 #include <cmath>
fac8f1
 #include <cassert>
fac8f1
+#include <stdexcept>
fac8f1
 #include <sys/types.h>                  // for stat()
fac8f1
 #include <sys/stat.h>                   // for stat()
fac8f1
 #ifdef EXV_HAVE_UNISTD_H
fac8f1
@@ -236,33 +237,43 @@ namespace Action {
fac8f1
     }
fac8f1
fac8f1
     int Print::run(const std::string& path)
fac8f1
-    try {
fac8f1
-        path_ = path;
fac8f1
-        int rc = 0;
fac8f1
-        Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
fac8f1
-        switch (Params::instance().printMode_) {
fac8f1
-            case Params::pmSummary:   rc = printSummary();     break;
fac8f1
-            case Params::pmList:      rc = printList();        break;
fac8f1
-            case Params::pmComment:   rc = printComment();     break;
fac8f1
-            case Params::pmPreview:   rc = printPreviewList(); break;
fac8f1
-            case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic)     ; break;
fac8f1
-            case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive) ; break;
fac8f1
-
fac8f1
-            case Params::pmXMP:
fac8f1
-                 option = option == Exiv2::kpsNone ? Exiv2::kpsXMP        : option;  // drop
fac8f1
-            case Params::pmIccProfile:{
fac8f1
-                 option = option == Exiv2::kpsNone ? Exiv2::kpsIccProfile : option;
fac8f1
-                 _setmode(_fileno(stdout),O_BINARY);
fac8f1
-                 rc = printStructure(std::cout,option);
fac8f1
-            } break;
fac8f1
+    {
fac8f1
+        try {
fac8f1
+            path_ = path;
fac8f1
+            int rc = 0;
fac8f1
+            Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
fac8f1
+            switch (Params::instance().printMode_) {
fac8f1
+                case Params::pmSummary:   rc = printSummary();     break;
fac8f1
+                case Params::pmList:      rc = printList();        break;
fac8f1
+                case Params::pmComment:   rc = printComment();     break;
fac8f1
+                case Params::pmPreview:   rc = printPreviewList(); break;
fac8f1
+                case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic)     ; break;
fac8f1
+                case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive) ; break;
fac8f1
+
fac8f1
+                case Params::pmXMP:
fac8f1
+                    if (option == Exiv2::kpsNone)
fac8f1
+                        option = Exiv2::kpsXMP;
fac8f1
+                    // drop
fac8f1
+                case Params::pmIccProfile:
fac8f1
+                    if (option == Exiv2::kpsNone)
fac8f1
+                        option = Exiv2::kpsIccProfile;
fac8f1
+                    _setmode(_fileno(stdout),O_BINARY);
fac8f1
+                    rc = printStructure(std::cout,option);
fac8f1
+                    break;
fac8f1
+            }
fac8f1
+            return rc;
fac8f1
+        }
fac8f1
+        catch(const Exiv2::AnyError& e) {
fac8f1
+            std::cerr << "Exiv2 exception in print action for file "
fac8f1
+                      << path << ":\n" << e << "\n";
fac8f1
+            return 1;
fac8f1
+        }
fac8f1
+        catch(const std::overflow_error& e) {
fac8f1
+            std::cerr << "std::overflow_error exception in print action for file "
fac8f1
+                      << path << ":\n" << e.what() << "\n";
fac8f1
+            return 1;
fac8f1
         }
fac8f1
-        return rc;
fac8f1
     }
fac8f1
-    catch(const Exiv2::AnyError& e) {
fac8f1
-        std::cerr << "Exiv2 exception in print action for file "
fac8f1
-                  << path << ":\n" << e << "\n";
fac8f1
-        return 1;
fac8f1
-    } // Print::run
fac8f1
fac8f1
     int Print::printStructure(std::ostream& out, Exiv2::PrintStructureOption option)
fac8f1
     {
fac8f1
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
fac8f1
index ac31257..4c072d7 100644
fac8f1
--- a/src/jp2image.cpp
fac8f1
+++ b/src/jp2image.cpp
fac8f1
@@ -41,6 +41,7 @@ EXIV2_RCSID("@(#) $Id: jp2image.cpp 4759 2017-04-23 10:58:54Z robinwmills $")
fac8f1
 #include "error.hpp"
fac8f1
 #include "futils.hpp"
fac8f1
 #include "types.hpp"
fac8f1
+#include "safe_op.hpp"
fac8f1
fac8f1
 // + standard includes
fac8f1
 #include <string>
fac8f1
@@ -269,8 +270,9 @@ namespace Exiv2
fac8f1
                             std::cout << "Exiv2::Jp2Image::readMetadata: "
fac8f1
                                      << "Color data found" << std::endl;
fac8f1
 #endif
fac8f1
+
fac8f1
                             long pad = 3 ; // 3 padding bytes 2 0 0
fac8f1
-                            DataBuf data(subBox.length+8);
fac8f1
+                            DataBuf data(Safe::add(subBox.length, static_cast<uint32_t>(8)));
fac8f1
                             io_->read(data.pData_,data.size_);
fac8f1
                             long    iccLength = getULong(data.pData_+pad, bigEndian);
fac8f1
                             DataBuf icc(iccLength);
fac8f1
diff --git a/src/safe_op.hpp b/src/safe_op.hpp
fac8f1
new file mode 100644
fac8f1
index 0000000..014b7f3
fac8f1
--- /dev/null
fac8f1
+++ b/src/safe_op.hpp
fac8f1
@@ -0,0 +1,310 @@
fac8f1
+// ********************************************************* -*- C++ -*-
fac8f1
+/*
fac8f1
+ * Copyright (C) 2004-2017 Exiv2 maintainers
fac8f1
+ *
fac8f1
+ * This program is part of the Exiv2 distribution.
fac8f1
+ *
fac8f1
+ * This program is free software; you can redistribute it and/or
fac8f1
+ * modify it under the terms of the GNU General Public License
fac8f1
+ * as published by the Free Software Foundation; either version 2
fac8f1
+ * of the License, or (at your option) any later version.
fac8f1
+ *
fac8f1
+ * This program is distributed in the hope that it will be useful,
fac8f1
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
fac8f1
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
fac8f1
+ * GNU General Public License for more details.
fac8f1
+ *
fac8f1
+ * You should have received a copy of the GNU General Public License
fac8f1
+ * along with this program; if not, write to the Free Software
fac8f1
+ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
fac8f1
+ */
fac8f1
+/*!
fac8f1
+  @file    safe_op.hpp
fac8f1
+  @brief   Overflow checks for integers
fac8f1
+  @author  Dan Čermák (D4N)
fac8f1
+           dan.cermak@cgc-instruments.com
fac8f1
+  @date    14-Dec-17, D4N: created
fac8f1
+ */
fac8f1
+
fac8f1
+#ifndef SAFE_OP_HPP_
fac8f1
+#define SAFE_OP_HPP_
fac8f1
+
fac8f1
+#include <limits>
fac8f1
+#include <stdexcept>
fac8f1
+
fac8f1
+#ifdef _MSC_VER
fac8f1
+#include <Intsafe.h>
fac8f1
+#endif
fac8f1
+
fac8f1
+/*!
fac8f1
+ * @brief Arithmetic operations with overflow checks
fac8f1
+ */
fac8f1
+namespace Safe
fac8f1
+{
fac8f1
+    /*!
fac8f1
+     * @brief Helper structs for providing integer overflow checks.
fac8f1
+     *
fac8f1
+     * This namespace contains the internal helper structs fallback_add_overflow
fac8f1
+     * and builtin_add_overflow. Both have a public static member function add
fac8f1
+     * with the following interface:
fac8f1
+     *
fac8f1
+     * bool add(T summand_1, T summand_2, T& result)
fac8f1
+     *
fac8f1
+     * where T is the type over which the struct is templated.
fac8f1
+     *
fac8f1
+     * The function performs a check whether the addition summand_1 + summand_2
fac8f1
+     * can be performed without an overflow. If the operation would overflow,
fac8f1
+     * true is returned and the addition is not performed if it would result in
fac8f1
+     * undefined behavior. If no overflow occurs, the sum is saved in result and
fac8f1
+     * false is returned.
fac8f1
+     *
fac8f1
+     * fallback_add_overflow implements a portable but slower overflow check.
fac8f1
+     * builtin_add_overflow uses compiler builtins (when available) and should
fac8f1
+     * be considerably faster. As builtins are not available for all types,
fac8f1
+     * builtin_add_overflow falls back to fallback_add_overflow when no builtin
fac8f1
+     * is available.
fac8f1
+     */
fac8f1
+    namespace Internal
fac8f1
+    {
fac8f1
+        /*!
fac8f1
+         * @brief Helper struct to determine whether a type is signed or unsigned
fac8f1
+
fac8f1
+         * This struct is a backport of std::is_signed from C++11. It has a public
fac8f1
+         * enum with the property VALUE which is true when the type is signed or
fac8f1
+         * false if it is unsigned.
fac8f1
+         */
fac8f1
+        template <typename T>
fac8f1
+        struct is_signed
fac8f1
+        {
fac8f1
+            enum
fac8f1
+            {
fac8f1
+                VALUE = T(-1) < T(0)
fac8f1
+            };
fac8f1
+        };
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Helper struct for SFINAE, from C++11
fac8f1
+
fac8f1
+         * This struct has a public typedef called type typedef'd to T if B is
fac8f1
+         * true. Otherwise there is no typedef.
fac8f1
+         */
fac8f1
+        template <bool B, class T = void>
fac8f1
+        struct enable_if
fac8f1
+        {
fac8f1
+        };
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Specialization of enable_if for the case B == true
fac8f1
+         */
fac8f1
+        template <class T>
fac8f1
+        struct enable_if<true, T>
fac8f1
+        {
fac8f1
+            typedef T type;
fac8f1
+        };
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Fallback overflow checker, specialized via SFINAE
fac8f1
+         *
fac8f1
+         * This struct implements a 'fallback' addition with an overflow check,
fac8f1
+         * i.e. it does not rely on compiler intrinsics.  It is specialized via
fac8f1
+         * SFINAE for signed and unsigned integer types and provides a public
fac8f1
+         * static member function add.
fac8f1
+         */
fac8f1
+        template <typename T, typename = void>
fac8f1
+        struct fallback_add_overflow;
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Overload of fallback_add_overflow for signed integers
fac8f1
+         */
fac8f1
+        template <typename T>
fac8f1
+        struct fallback_add_overflow<T, typename enable_if<is_signed<T>::VALUE>::type>
fac8f1
+        {
fac8f1
+            /*!
fac8f1
+             * @brief Adds the two summands only if no overflow occurs
fac8f1
+             *
fac8f1
+             * This function performs a check if summand_1 + summand_2 would
fac8f1
+             * overflow and returns true in that case. If no overflow occurs,
fac8f1
+             * the sum is saved in result and false is returned.
fac8f1
+             *
fac8f1
+             * @return true on overflow, false on no overflow
fac8f1
+             *
fac8f1
+             * The check for an overflow is performed before the addition to
fac8f1
+             * ensure that no undefined behavior occurs. The value in result is
fac8f1
+             * only valid when the function returns false.
fac8f1
+             *
fac8f1
+             * Further information:
fac8f1
+             * https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
fac8f1
+             */
fac8f1
+            static bool add(T summand_1, T summand_2, T& result)
fac8f1
+            {
fac8f1
+                if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
fac8f1
+                    ((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
fac8f1
+                    return true;
fac8f1
+                } else {
fac8f1
+                    result = summand_1 + summand_2;
fac8f1
+                    return false;
fac8f1
+                }
fac8f1
+            }
fac8f1
+        };
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Overload of fallback_add_overflow for unsigned integers
fac8f1
+         */
fac8f1
+        template <typename T>
fac8f1
+        struct fallback_add_overflow<T, typename enable_if<!is_signed<T>::VALUE>::type>
fac8f1
+        {
fac8f1
+            /*!
fac8f1
+             * @brief Adds the two summands only if no overflow occurs
fac8f1
+             *
fac8f1
+             * This function performs a check if summand_1 + summand_2 would
fac8f1
+             * overflow and returns true in that case. If no overflow occurs,
fac8f1
+             * the sum is saved in result and false is returned.
fac8f1
+             *
fac8f1
+             * @return true on overflow, false on no overflow
fac8f1
+             *
fac8f1
+             * Further information:
fac8f1
+             * https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
fac8f1
+             */
fac8f1
+            static bool add(T summand_1, T summand_2, T& result)
fac8f1
+            {
fac8f1
+                if (summand_1 > std::numeric_limits<T>::max() - summand_2) {
fac8f1
+                    return true;
fac8f1
+                } else {
fac8f1
+                    result = summand_1 + summand_2;
fac8f1
+                    return false;
fac8f1
+                }
fac8f1
+            }
fac8f1
+        };
fac8f1
+
fac8f1
+        /*!
fac8f1
+         * @brief Overflow checker using compiler intrinsics
fac8f1
+         *
fac8f1
+         * This struct provides an add function with the same interface &
fac8f1
+         * behavior as fallback_add_overload::add but it relies on compiler
fac8f1
+         * intrinsics instead. This version should be considerably faster than
fac8f1
+         * the fallback version as it can fully utilize available CPU
fac8f1
+         * instructions & the compiler's diagnostic.
fac8f1
+         *
fac8f1
+         * However, as some compilers don't provide intrinsics for certain
fac8f1
+         * types, the default implementation of add is the version from falback.
fac8f1
+         *
fac8f1
+         * The struct is explicitly specialized for each type via #ifdefs for
fac8f1
+         * each compiler.
fac8f1
+         */
fac8f1
+        template <typename T>
fac8f1
+        struct builtin_add_overflow
fac8f1
+        {
fac8f1
+            /*!
fac8f1
+             * @brief Add summand_1 and summand_2 and check for overflows.
fac8f1
+             *
fac8f1
+             * This is the default add() function that uses
fac8f1
+             * fallback_add_overflow<T>::add(). All specializations must have
fac8f1
+             * exactly the same interface and behave the same way.
fac8f1
+             */
fac8f1
+            static inline bool add(T summand_1, T summand_2, T& result)
fac8f1
+            {
fac8f1
+                return fallback_add_overflow<T>::add(summand_1, summand_2, result);
fac8f1
+            }
fac8f1
+        };
fac8f1
+
fac8f1
+#if defined(__GNUC__) || defined(__clang__)
fac8f1
+#if __GNUC__ >= 5
fac8f1
+
fac8f1
+/*!
fac8f1
+ * This macro pastes a specialization of builtin_add_overflow using gcc's &
fac8f1
+ * clang's __builtin_(s/u)add(l)(l)_overlow()
fac8f1
+ *
fac8f1
+ * The add function is implemented by forwarding the parameters to the intrinsic
fac8f1
+ * and returning its value.
fac8f1
+ *
fac8f1
+ * The intrinsics are documented here:
fac8f1
+ * https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html#Integer-Overflow-Builtins
fac8f1
+ */
fac8f1
+#define SPECIALIZE_builtin_add_overflow(type, builtin_name)                  \
fac8f1
+    template <>                                                              \
fac8f1
+    struct builtin_add_overflow<type>                                        \
fac8f1
+    {                                                                        \
fac8f1
+        static inline bool add(type summand_1, type summand_2, type& result) \
fac8f1
+        {                                                                    \
fac8f1
+            return builtin_name(summand_1, summand_2, &result);              \
fac8f1
+        }                                                                    \
fac8f1
+    }
fac8f1
+
fac8f1
+        SPECIALIZE_builtin_add_overflow(int, __builtin_sadd_overflow);
fac8f1
+        SPECIALIZE_builtin_add_overflow(long, __builtin_saddl_overflow);
fac8f1
+        SPECIALIZE_builtin_add_overflow(long long, __builtin_saddll_overflow);
fac8f1
+
fac8f1
+        SPECIALIZE_builtin_add_overflow(unsigned int, __builtin_uadd_overflow);
fac8f1
+        SPECIALIZE_builtin_add_overflow(unsigned long, __builtin_uaddl_overflow);
fac8f1
+        SPECIALIZE_builtin_add_overflow(unsigned long long, __builtin_uaddll_overflow);
fac8f1
+
fac8f1
+#undef SPECIALIZE_builtin_add_overflow
fac8f1
+#endif
fac8f1
+
fac8f1
+#elif defined(_MSC_VER)
fac8f1
+
fac8f1
+/*!
fac8f1
+ * This macro pastes a specialization of builtin_add_overflow using MSVC's
fac8f1
+ * U(Int/Long/LongLong)Add.
fac8f1
+ *
fac8f1
+ * The add function is implemented by forwarding the parameters to the
fac8f1
+ * intrinsic. As MSVC's intrinsics return S_OK on success, this specialization
fac8f1
+ * returns whether the intrinsics return value does not equal S_OK. This ensures
fac8f1
+ * a uniform interface of the add function (false is returned when no overflow
fac8f1
+ * occurs, true on overflow).
fac8f1
+ *
fac8f1
+ * The intrinsics are documented here:
fac8f1
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ff516460(v=vs.85).aspx
fac8f1
+ */
fac8f1
+#define SPECIALIZE_builtin_add_overflow_WIN(type, builtin_name)              \
fac8f1
+    template <>                                                              \
fac8f1
+    struct builtin_add_overflow<type>                                        \
fac8f1
+    {                                                                        \
fac8f1
+        static inline bool add(type summand_1, type summand_2, type& result) \
fac8f1
+        {                                                                    \
fac8f1
+            return builtin_name(summand_1, summand_2, &result) != S_OK;      \
fac8f1
+        }                                                                    \
fac8f1
+    }
fac8f1
+
fac8f1
+        SPECIALIZE_builtin_add_overflow_WIN(unsigned int, UIntAdd);
fac8f1
+        SPECIALIZE_builtin_add_overflow_WIN(unsigned long, ULongAdd);
fac8f1
+        SPECIALIZE_builtin_add_overflow_WIN(unsigned long long, ULongLongAdd);
fac8f1
+
fac8f1
+#undef SPECIALIZE_builtin_add_overflow_WIN
fac8f1
+
fac8f1
+#endif
fac8f1
+
fac8f1
+    }  // namespace Internal
fac8f1
+
fac8f1
+    /*!
fac8f1
+     * @brief Safe addition, throws an exception on overflow.
fac8f1
+     *
fac8f1
+     * This function returns the result of summand_1 and summand_2 only when the
fac8f1
+     * operation would not overflow, otherwise an exception of type
fac8f1
+     * std::overflow_error is thrown.
fac8f1
+     *
fac8f1
+     * @param[in] summand_1, summand_2  summands to be summed up
fac8f1
+     * @return  the sum of summand_1 and summand_2
fac8f1
+     * @throws  std::overflow_error if the addition would overflow
fac8f1
+     *
fac8f1
+     * This function utilizes compiler builtins when available and should have a
fac8f1
+     * very small performance hit then. When builtins are unavailable, a more
fac8f1
+     * extensive check is required.
fac8f1
+     *
fac8f1
+     * Builtins are available for the following configurations:
fac8f1
+     * - GCC/Clang for signed and unsigned int, long and long long (not char & short)
fac8f1
+     * - MSVC for unsigned int, long and long long
fac8f1
+     */
fac8f1
+    template <typename T>
fac8f1
+    T add(T summand_1, T summand_2)
fac8f1
+    {
fac8f1
+        T res = 0;
fac8f1
+        if (Internal::builtin_add_overflow<T>::add(summand_1, summand_2, res)) {
fac8f1
+            throw std::overflow_error("Overflow in addition");
fac8f1
+        }
fac8f1
+        return res;
fac8f1
+    }
fac8f1
+
fac8f1
+}  // namespace Safe
fac8f1
+
fac8f1
+#endif  // SAFE_OP_HPP_