Attached patch fixes most open security issues in testing/sid
(as applied by Leonidas S. Barbosa in Ubuntu), but needs
additional work to deal with the versioned symbols fallout
caused by GCC changes which happened after the last exiv upload
to sid.
diff -Nru exiv2-0.25/debian/patches/CVE-2017-11591.patch exiv2-0.25/debian/patches/CVE-2017-11591.patch
--- exiv2-0.25/debian/patches/CVE-2017-11591.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2017-11591.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,27 @@
+Index: exiv2-0.25/include/exiv2/value.hpp
+===================================================================
+--- exiv2-0.25.orig/include/exiv2/value.hpp
++++ exiv2-0.25/include/exiv2/value.hpp
+@@ -1657,11 +1657,12 @@ namespace Exiv2 {
+         ok_ = true;
+         return static_cast<long>(value_[n]);
+     }
++#define LARGE_INT 1000000
+     // Specialization for rational
+     template<>
+     inline long ValueType<Rational>::toLong(long n) const
+     {
+-        ok_ = (value_[n].second != 0);
++        ok_ = (value_[n].second != 0 && -LARGE_INT < value_[n].first && value_[n].first < LARGE_INT);
+         if (!ok_) return 0;
+         return value_[n].first / value_[n].second;
+     }
+@@ -1669,7 +1670,7 @@ namespace Exiv2 {
+     template<>
+     inline long ValueType<URational>::toLong(long n) const
+     {
+-        ok_ = (value_[n].second != 0);
++        ok_ = (value_[n].second != 0 && value_[n].first < LARGE_INT);
+         if (!ok_) return 0;
+         return value_[n].first / value_[n].second;
+     }
diff -Nru exiv2-0.25/debian/patches/CVE-2017-11683.patch exiv2-0.25/debian/patches/CVE-2017-11683.patch
--- exiv2-0.25/debian/patches/CVE-2017-11683.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2017-11683.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,42 @@
+From 1f1715c086d8dcdf5165b19164af9aee7aa12e98 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cer...@cgc-instruments.com>
+Date: Fri, 6 Oct 2017 00:37:43 +0200
+Subject: [PATCH] =?UTF-8?q?Use=20nullptr=20check=20instead=20of=20assertio?=
+ =?UTF-8?q?n,=20by=20Rapha=C3=ABl=20Hertzog?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Source:
+https://github.com/Exiv2/exiv2/issues/57#issuecomment-333086302
+
+tc can be a null pointer when the TIFF tag is unknown (the factory
+then returns an auto_ptr(0)) => as this can happen for corrupted
+files, an explicit check should be used because an assertion can be
+turned of in release mode (with NDEBUG defined)
+
+This also fixes #57
+---
+ src/tiffvisitor.cpp | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/src/tiffvisitor.cpp
++++ b/src/tiffvisitor.cpp
+@@ -1290,11 +1290,12 @@ namespace Exiv2 {
+             }
+             uint16_t tag = getUShort(p, byteOrder());
+             TiffComponent::AutoPtr tc = TiffCreator::create(tag, object->group());
+-            // The assertion typically fails if a component is not configured in
+-            // the TIFF structure table
+-            assert(tc.get());
+-            tc->setStart(p);
+-            object->addChild(tc);
++            if (tc.get()) {
++                tc->setStart(p);
++                object->addChild(tc);
++            } else {
++               EXV_WARNING << "Unable to handle tag " << tag << ".\n";
++            }
+             p += 12;
+         }
+ 
diff -Nru exiv2-0.25/debian/patches/CVE-2017-14859_14862_14864.patch exiv2-0.25/debian/patches/CVE-2017-14859_14862_14864.patch
--- exiv2-0.25/debian/patches/CVE-2017-14859_14862_14864.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2017-14859_14862_14864.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,74 @@
+Backported of:
+
+Description: Fix CVE-2017-14864, CVE-2017-14862 and CVE-2017-14859
+Origin: backport, https://github.com/Exiv2/exiv2/pull/110
+Last-Update: 2017-10-25
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+Index: exiv2-0.25/src/error.cpp
+===================================================================
+--- exiv2-0.25.orig/src/error.cpp
++++ exiv2-0.25/src/error.cpp
+@@ -106,7 +106,9 @@ namespace {
+         { 50, N_("Multiple TIFF array element tags %1 in one directory") }, // %1=tag number
+         { 51, N_("TIFF array element tag %1 has wrong type") }, // %1=tag number
+         { 52, N_("%1 has invalid XMP value type `%2'") }, // %1=key, %2=value type
+-        { 58, N_("corrupted image metadata") }
++        { 57, N_("invalid memory allocation request") },
++        { 58, N_("corrupted image metadata") },
++        { 59, N_("Arithmetic operation overflow") },
+     };
+ 
+ }
+Index: exiv2-0.25/src/tiffvisitor.cpp
+===================================================================
+--- exiv2-0.25.orig/src/tiffvisitor.cpp
++++ exiv2-0.25/src/tiffvisitor.cpp
+@@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id: tiffvisitor.cpp 3
+ #include <iostream>
+ #include <iomanip>
+ #include <cassert>
++#include <limits>
+ 
+ // *****************************************************************************
+ namespace {
+@@ -1490,6 +1491,9 @@ namespace Exiv2 {
+             return;
+         }
+         p += 4;
++        if (count > std::numeric_limits<uint32_t>::max() / typeSize) {
++            throw Error(59);
++        }
+         uint32_t size = typeSize * count;
+         int32_t offset = getLong(p, byteOrder());
+         byte* pData = p;
+@@ -1508,7 +1512,18 @@ 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 "
+@@ -1528,7 +1543,9 @@ namespace Exiv2 {
+             }
+         }
+         Value::AutoPtr v = Value::create(typeId);
+-        assert(v.get());
++        if (!v.get()) {
++	    throw Error(58);
++	}
+         v->read(pData, size, byteOrder());
+ 
+         object->setValue(v);
diff -Nru exiv2-0.25/debian/patches/CVE-2017-17669.patch exiv2-0.25/debian/patches/CVE-2017-17669.patch
--- exiv2-0.25/debian/patches/CVE-2017-17669.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2017-17669.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,37 @@
+From 4429b962e10e9f2e905e20b183ba008c616cd366 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cer...@cgc-instruments.com>
+Date: Mon, 22 Jan 2018 23:56:08 +0100
+Subject: [PATCH 1/3] Fix out of bounds read in src/pngchunk_int.cpp by
+ @brianmay
+
+- consider that key is advanced by 8 bytes if stripHeader is true
+  => length is reduced by same amount
+  Fixed by adding offset to the check in the loop
+- Rewrote loop so that keysize is checked before the next
+  iteration (preventing an out of bounds read)
+Index: exiv2-0.25/src/pngchunk.cpp
+===================================================================
+--- exiv2-0.25.orig/src/pngchunk.cpp
++++ exiv2-0.25/src/pngchunk.cpp
+@@ -103,15 +103,17 @@ namespace Exiv2 {
+     {
+         // From a tEXt, zTXt, or iTXt chunk,
+         // we get the key, it's a null terminated string at the chunk start
+-        if (data.size_ <= (stripHeader ? 8 : 0)) throw Error(14);
+-        const byte *key = data.pData_ + (stripHeader ? 8 : 0);
++        const int offset = stripHeader ? 8 : 0;
++        if (data.size_ <= offset) throw Error(14);
++        const byte *key = data.pData_ + offset;
+ 
+         // Find null string at end of key.
+         int keysize=0;
+-        for ( ; key[keysize] != 0 ; keysize++)
++        while (key[keysize] != 0)
+         {
++            keysize++;
+             // look if keysize is valid.
+-            if (keysize >= data.size_)
++            if (keysize+offset >= data.size_)
+                 throw Error(14);
+         }
+ 
diff -Nru exiv2-0.25/debian/patches/CVE-2018-10958_10999-minor-fix.patch exiv2-0.25/debian/patches/CVE-2018-10958_10999-minor-fix.patch
--- exiv2-0.25/debian/patches/CVE-2018-10958_10999-minor-fix.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2018-10958_10999-minor-fix.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,21 @@
+Backported of:
+
+From c0a879aea41348481d5b286e34a85f4744a7446a Mon Sep 17 00:00:00 2001
+From: Luis Diaz Mas <pipon...@gmail.com>
+Date: Wed, 23 May 2018 11:10:38 +0200
+Subject: [PATCH] Fix call to std::count, so that we count until the end of the
+ array
+
+Index: exiv2-0.25/src/pngchunk.cpp
+===================================================================
+--- exiv2-0.25.orig/src/pngchunk.cpp
++++ exiv2-0.25/src/pngchunk.cpp
+@@ -173,7 +173,7 @@ namespace Exiv2 {
+         else if(type == iTXt_Chunk)
+         {
+             if (data.size_ < Safe::add(keysize, 3)) throw Error(58);
+-            const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_-1], '\0');
++            const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0');
+             if (nullSeparators < 2) throw Error(58, "iTXt chunk: not enough null separators");
+ 
+             // Extract a deflate compressed or uncompressed UTF-8 text chunk
diff -Nru exiv2-0.25/debian/patches/CVE-2018-16336.patch exiv2-0.25/debian/patches/CVE-2018-16336.patch
--- exiv2-0.25/debian/patches/CVE-2018-16336.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2018-16336.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,130 @@
+Backported of:
+
+From 35b3e596edacd2437c2c5d3dd2b5c9502626163d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cer...@cgc-instruments.com>
+Date: Fri, 17 Aug 2018 16:41:05 +0200
+Subject: [PATCH] Add overflow & overread checks to PngChunk::parseTXTChunk()
+
+This function was creating a lot of new pointers and strings without
+properly checking the array bounds. This commit adds several calls
+to enforce(), making sure that the pointers stay within bounds.
+Strings are now created using the helper function
+string_from_unterminated() to prevent overreads in the constructor of
+std::string.
+
+This fixes #400
+Index: exiv2-0.25/src/pngchunk.cpp
+===================================================================
+--- exiv2-0.25.orig/src/pngchunk.cpp
++++ exiv2-0.25/src/pngchunk.cpp
+@@ -40,6 +40,8 @@ EXIV2_RCSID("@(#) $Id: pngchunk.cpp 3777
+ #include "iptc.hpp"
+ #include "image.hpp"
+ #include "error.hpp"
++#include "helper_functions.hpp"
++#include "safe_op.hpp"
+ 
+ // + standard includes
+ #include <sstream>
+@@ -129,6 +131,8 @@ namespace Exiv2 {
+ 
+         if(type == zTXt_Chunk)
+         {
++            if (data.size_ < Safe::add(keysize, 2)) throw Error(58);
++
+             // Extract a deflate compressed Latin-1 text chunk
+ 
+             // we get the compression method after the key
+@@ -145,11 +149,13 @@ namespace Exiv2 {
+             // compressed string after the compression technique spec
+             const byte* compressedText      = data.pData_ + keysize + 2;
+             unsigned int compressedTextSize = data.size_  - keysize - 2;
++            if (compressedTextSize >= data.size_) throw Error(58);
+ 
+             zlibUncompress(compressedText, compressedTextSize, arr);
+         }
+         else if(type == tEXt_Chunk)
+         {
++            if (data.size_ < Safe::add(keysize, 1)) throw Error(58);
+             // Extract a non-compressed Latin-1 text chunk
+ 
+             // the text comes after the key, but isn't null terminated
+@@ -160,6 +166,7 @@ namespace Exiv2 {
+         }
+         else if(type == iTXt_Chunk)
+         {
++            if (data.size_ < Safe::add(keysize, 3)) throw Error(58);
+             const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_-1], '\0');
+             if (nullSeparators < 2) throw Error(58, "iTXt chunk: not enough null separators");
+ 
+@@ -180,41 +187,43 @@ namespace Exiv2 {
+             }
+ 
+             // language description string after the compression technique spec
+-            std::string languageText((const char*)(data.pData_ + keysize + 3));
+-            unsigned int languageTextSize = static_cast<unsigned int>(languageText.size());
+-            // translated keyword string after the language description
+-            std::string translatedKeyText((const char*)(data.pData_ + keysize + 3 + languageTextSize +1));
+-            unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
++            const size_t languageTextMaxSize = data.size_ - keysize - 3;
++            std::string languageText =
++                string_from_unterminated((const char*)(data.pData_ + Safe::add(keysize, 3)), languageTextMaxSize);
++            const unsigned int languageTextSize = static_cast<unsigned int>(languageText.size());
+ 
+-            if ( compressionFlag == 0x00 )
+-            {
+-                // then it's an uncompressed iTXt chunk
+-#ifdef DEBUG
+-                std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
+-#endif
++            if (data.size_ < Safe::add(static_cast<unsigned int>(Safe::add(keysize, 4)), languageTextSize)) throw Error(58);
++            // translated keyword string after the language description
++            std::string translatedKeyText =
++                string_from_unterminated((const char*)(data.pData_ + keysize + 3 + languageTextSize + 1),
++                                         data.size_ - (keysize + 3 + languageTextSize + 1));
++            const unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
++
++            if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) {
++                if (Safe::add(static_cast<unsigned int>(keysize + 3 + languageTextSize + 1),
++                                  Safe::add(translatedKeyTextSize, 1u)) > data.size_) throw Error(58);
+ 
+-                // the text comes after the translated keyword, but isn't null terminated
+                 const byte* text = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1;
+-                long textsize    = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
++                const long textsize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
+ 
+-                arr.alloc(textsize);
+-                arr = DataBuf(text, textsize);
+-            }
+-            else if ( compressionFlag == 0x01 && compressionMethod == 0x00 )
+-            {
+-                // then it's a zlib compressed iTXt chunk
++                if (compressionFlag == 0x00) {
++                    // then it's an uncompressed iTXt chunk
+ #ifdef DEBUG
+-                std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n";
++                    std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
+ #endif
+ 
+-                // the compressed text comes after the translated keyword, but isn't null terminated
+-                const byte* compressedText = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1;
+-                long compressedTextSize    = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
++                    arr.alloc(textsize);
++                    arr = DataBuf(text, textsize);
++                } else if (compressionFlag == 0x01 && compressionMethod == 0x00) {
++                    // then it's a zlib compressed iTXt chunk
++#ifdef DEBUG
++                    std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n";
++#endif
+ 
+-                zlibUncompress(compressedText, compressedTextSize, arr);
+-            }
+-            else
+-            {
++                    // the compressed text comes after the translated keyword, but isn't null terminated
++                    zlibUncompress(text, textsize, arr);
++                }
++            } else {
+                 // then it isn't zlib compressed and we are sunk
+ #ifdef DEBUG
+                 std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard iTXt compression method.\n";
diff -Nru exiv2-0.25/debian/patches/CVE-2018-16336-support-funcs.patch exiv2-0.25/debian/patches/CVE-2018-16336-support-funcs.patch
--- exiv2-0.25/debian/patches/CVE-2018-16336-support-funcs.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2018-16336-support-funcs.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,26 @@
+diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
+index 89b0931..fb27100 100644
+--- a/src/pngchunk.cpp
++++ b/src/pngchunk.cpp
+@@ -40,7 +40,6 @@ EXIV2_RCSID("@(#) $Id: pngchunk.cpp 3777 2015-05-02 11:55:40Z ahuggel $")
+ #include "iptc.hpp"
+ #include "image.hpp"
+ #include "error.hpp"
+-#include "helper_functions.hpp"
+ #include "safe_op.hpp"
+ 
+ // + standard includes
+@@ -55,6 +54,13 @@ EXIV2_RCSID("@(#) $Id: pngchunk.cpp 3777 2015-05-02 11:55:40Z ahuggel $")
+ 
+ #include <zlib.h>     // To uncompress or compress text chunk
+ 
++/* Added as support of CVE-2018-16336 */
++std::string string_from_unterminated(const char* data, size_t data_length)
++{
++    const size_t StringLength = strnlen(data, data_length);
++
++    return std::string(data, StringLength);
++}
+ /*
+ 
+ URLs to find informations about PNG chunks :
diff -Nru exiv2-0.25/debian/patches/CVE-2018-17581.patch exiv2-0.25/debian/patches/CVE-2018-17581.patch
--- exiv2-0.25/debian/patches/CVE-2018-17581.patch	1970-01-01 01:00:00.000000000 +0100
+++ exiv2-0.25/debian/patches/CVE-2018-17581.patch	2019-02-26 00:40:56.000000000 +0100
@@ -0,0 +1,30 @@
+From b3d077dcaefb6747fff8204490f33eba5a144edb Mon Sep 17 00:00:00 2001
+From: Robin Mills <ro...@clanmills.com>
+Date: Sat, 13 Oct 2018 11:38:56 +0200
+Subject: [PATCH] Fix #460 by adding more checks in
+ CiffDirectory::readDirectory
+Index: exiv2-0.25/src/crwimage.cpp
+===================================================================
+--- exiv2-0.25.orig/src/crwimage.cpp
++++ exiv2-0.25/src/crwimage.cpp
+@@ -447,6 +447,8 @@ namespace Exiv2 {
+                                       uint32_t    size,
+                                       ByteOrder   byteOrder)
+     {
++        if (size < 4)
++            throw Error(33);
+         uint32_t o = getULong(pData + size - 4, byteOrder);
+         if (o + 2 > size) throw Error(33);
+         uint16_t count = getUShort(pData + o, byteOrder);
+@@ -455,8 +457,10 @@ namespace Exiv2 {
+                   <<", " << count << " entries \n";
+ #endif
+         o += 2;
++        if ( (o + (count * 10)) > size )
++            throw Error(33);
++
+         for (uint16_t i = 0; i < count; ++i) {
+-            if (o + 10 > size) throw Error(33);
+             uint16_t tag = getUShort(pData + o, byteOrder);
+             CiffComponent::AutoPtr m;
+             switch (CiffComponent::typeId(tag)) {
diff -Nru exiv2-0.25/debian/patches/series exiv2-0.25/debian/patches/series
--- exiv2-0.25/debian/patches/series	2018-06-28 18:05:24.000000000 +0200
+++ exiv2-0.25/debian/patches/series	2019-02-26 00:40:56.000000000 +0100
@@ -10,3 +10,11 @@
 CVE-2018-12265_prereq.patch
 CVE-2018-12265.patch
 CVE-2018-12264.patch
+CVE-2017-11591.patch
+CVE-2017-11683.patch
+CVE-2017-14859_14862_14864.patch
+CVE-2017-17669.patch
+CVE-2018-17581.patch
+CVE-2018-16336.patch
+CVE-2018-16336-support-funcs.patch
+CVE-2018-10958_10999-minor-fix.patch

Reply via email to