diff -Nru exiv2-0.25/debian/changelog exiv2-0.25/debian/changelog --- exiv2-0.25/debian/changelog 2018-06-29 13:53:30.000000000 +0000 +++ exiv2-0.25/debian/changelog 2019-01-09 12:23:30.000000000 +0000 @@ -1,3 +1,35 @@ +exiv2 (0.25-3.1ubuntu0.18.04.2) bionic-security; urgency=medium + + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2017-11591.patch: fix in + include/exiv2/value.hpp. + - CVE-2017-11591 + * SECURITY UPDATE: Remote denial of service + - debian/patches/CVE-2017-11683.patch: fix in + src/tiffvisitor.cpp. + - CVE-2017-11683 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2017-14859_14862_14864.patch: fix in + src/error.cpp, src/tiffvisitor.cpp. + - CVE-2017-14859 + - CVE-2017-14862 + - CVE-2017-14864 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2017-17669.patch: fix in + src/pngchunk.cpp. + - CVE-2017-17669 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2018-17581.patch: fix in + src/crwimage.cpp. + - CVE-2018-17581 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-16336*.patch: fix in + src/pngchunk.cpp. + - CVE-2018-16336 + * Minor fix related to CVE-2018-10958_10999 in src/pngchunk.cpp. + + -- Leonidas S. Barbosa Wed, 09 Jan 2019 09:23:30 -0300 + exiv2 (0.25-3.1ubuntu0.18.04.1) bionic-security; urgency=medium * SECURITY UPDATE: denial of service through memory exhaustion 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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2017-11591.patch 2019-01-09 12:22:05.000000000 +0000 @@ -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(value_[n]); + } ++#define LARGE_INT 1000000 + // Specialization for rational + template<> + inline long ValueType::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::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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2017-11683.patch 2019-01-09 12:22:16.000000000 +0000 @@ -0,0 +1,42 @@ +From 1f1715c086d8dcdf5165b19164af9aee7aa12e98 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= +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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2017-14859_14862_14864.patch 2019-01-09 12:22:25.000000000 +0000 @@ -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 + #include + #include ++#include + + // ***************************************************************************** + namespace { +@@ -1490,6 +1491,9 @@ namespace Exiv2 { + return; + } + p += 4; ++ if (count > std::numeric_limits::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(baseOffset()) > std::numeric_limits::max() - static_cast(offset)) ++ || (static_cast(baseOffset() + offset) > std::numeric_limits::max() - reinterpret_cast(pData_))) ++ { ++ throw Error(59); ++ } ++ if (pData_ + static_cast(baseOffset()) + static_cast(offset) > pLast_) { ++ throw Error(58); ++ } + pData = const_cast(pData_) + baseOffset() + offset; ++ // check for size being invalid + if (size > static_cast(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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2017-17669.patch 2019-01-09 12:22:35.000000000 +0000 @@ -0,0 +1,37 @@ +From 4429b962e10e9f2e905e20b183ba008c616cd366 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= +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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2018-10958_10999-minor-fix.patch 2019-01-09 12:23:19.000000000 +0000 @@ -0,0 +1,21 @@ +Backported of: + +From c0a879aea41348481d5b286e34a85f4744a7446a Mon Sep 17 00:00:00 2001 +From: Luis Diaz Mas +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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2018-16336.patch 2019-01-09 12:23:00.000000000 +0000 @@ -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?= +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 +@@ -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(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(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(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(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(translatedKeyText.size()); ++ ++ if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) { ++ if (Safe::add(static_cast(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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2018-16336-support-funcs.patch 2019-01-09 12:23:06.000000000 +0000 @@ -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 // 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 00:00:00.000000000 +0000 +++ exiv2-0.25/debian/patches/CVE-2018-17581.patch 2019-01-09 12:22:49.000000000 +0000 @@ -0,0 +1,30 @@ +From b3d077dcaefb6747fff8204490f33eba5a144edb Mon Sep 17 00:00:00 2001 +From: Robin Mills +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-29 13:53:30.000000000 +0000 +++ exiv2-0.25/debian/patches/series 2019-01-09 12:23:19.000000000 +0000 @@ -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