From ccb5ae950d36c955cfe93f1bea379ef13023609a Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Aug 10 2017 15:02:04 +0000 Subject: adding patches for CVE back (cups-filters needed to rebuild) --- diff --git a/qpdf-CVE-2017-9208.patch b/qpdf-CVE-2017-9208.patch new file mode 100644 index 0000000..bdbeb2f --- /dev/null +++ b/qpdf-CVE-2017-9208.patch @@ -0,0 +1,36 @@ +diff -up qpdf-6.0.0/libqpdf/QPDF.cc.CVE-2017-9208 qpdf-6.0.0/libqpdf/QPDF.cc +--- qpdf-6.0.0/libqpdf/QPDF.cc.CVE-2017-9208 2017-08-10 14:13:32.120658345 +0200 ++++ qpdf-6.0.0/libqpdf/QPDF.cc 2017-08-10 14:16:20.567272498 +0200 +@@ -1340,6 +1340,13 @@ QPDF::readObjectAtOffset(bool try_recove + objid = atoi(tobjid.getValue().c_str()); + generation = atoi(tgen.getValue().c_str()); + ++ if (objid == 0) ++ { ++ throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), ++ this->last_object_description, offset, ++ "object with ID 0"); ++ } ++ + if ((exp_objid >= 0) && + (! ((objid == exp_objid) && (generation == exp_generation)))) + { +diff -up qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc.CVE-2017-9208 qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc +--- qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc.CVE-2017-9208 2017-08-10 14:13:44.474556707 +0200 ++++ qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc 2017-08-10 14:18:07.322394199 +0200 +@@ -1090,6 +1090,15 @@ QPDFObjectHandle::parseInternal(PointerH + QPDFObjectHandle + QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) + { ++ if (objid == 0) ++ { ++ // Special case: QPDF uses objid 0 as a sentinel for direct ++ // objects, and the PDF specification doesn't allow for object ++ // 0. Treat indirect references to object 0 as null so that we ++ // never create an indirect object with objid 0. ++ return newNull(); ++ } ++ + return QPDFObjectHandle(qpdf, objid, generation); + } + diff --git a/qpdf-CVE-2017-9209.patch b/qpdf-CVE-2017-9209.patch new file mode 100644 index 0000000..b2dc39d --- /dev/null +++ b/qpdf-CVE-2017-9209.patch @@ -0,0 +1,37 @@ +diff -up qpdf-6.0.0/include/qpdf/QPDF.hh.CVE-2017-9209 qpdf-6.0.0/include/qpdf/QPDF.hh +--- qpdf-6.0.0/include/qpdf/QPDF.hh.CVE-2017-9209 2017-08-10 14:21:20.411794523 +0200 ++++ qpdf-6.0.0/include/qpdf/QPDF.hh 2017-08-10 14:23:39.400636506 +0200 +@@ -1095,6 +1095,7 @@ class QPDF + // copied_stream_data_provider is owned by copied_streams + CopiedStreamDataProvider* copied_stream_data_provider; + std::set attachment_streams; ++ bool reconstructed_xref; + + // Linearization data + qpdf_offset_t first_xref_item_offset; // actual value from file +diff -up qpdf-6.0.0/libqpdf/QPDF.cc.CVE-2017-9209 qpdf-6.0.0/libqpdf/QPDF.cc +--- qpdf-6.0.0/libqpdf/QPDF.cc.CVE-2017-9209 2017-08-10 14:21:34.429677730 +0200 ++++ qpdf-6.0.0/libqpdf/QPDF.cc 2017-08-10 14:25:33.558685371 +0200 +@@ -93,6 +93,7 @@ QPDF::QPDF() : + cached_key_generation(0), + pushed_inherited_attributes_to_pages(false), + copied_stream_data_provider(0), ++ reconstructed_xref(false), + first_xref_item_offset(0), + uncompressed_after_compressed(false) + { +@@ -331,6 +332,14 @@ QPDF::setTrailer(QPDFObjectHandle obj) + void + QPDF::reconstruct_xref(QPDFExc& e) + { ++ if (this->reconstructed_xref) ++ { ++ // Avoid xref reconstruction infinite loops ++ throw e; ++ } ++ ++ this->reconstructed_xref = true; ++ + PCRE obj_re("^\\s*(\\d+)\\s+(\\d+)\\s+obj\\b"); + PCRE endobj_re("^\\s*endobj\\b"); + PCRE trailer_re("^\\s*trailer\\b"); diff --git a/qpdf-CVE-2017-9210.patch b/qpdf-CVE-2017-9210.patch new file mode 100644 index 0000000..af07590 --- /dev/null +++ b/qpdf-CVE-2017-9210.patch @@ -0,0 +1,13 @@ +diff -up qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc.CVE-2017-9210 qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc +--- qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc.CVE-2017-9210 2017-08-10 14:27:56.866491369 +0200 ++++ qpdf-6.0.0/libqpdf/QPDFObjectHandle.cc 2017-08-10 14:29:56.333496002 +0200 +@@ -1076,8 +1076,7 @@ QPDFObjectHandle::parseInternal(PointerH + throw QPDFExc( + qpdf_e_damaged_pdf, + input->getName(), object_description, offset, +- std::string("dictionary key not name (") + +- key_obj.unparse() + ")"); ++ std::string("dictionary key is not not a name token")); + } + dict[key_obj.getName()] = val; + } diff --git a/qpdf-detect-recursions.patch b/qpdf-detect-recursions.patch new file mode 100644 index 0000000..12d8481 --- /dev/null +++ b/qpdf-detect-recursions.patch @@ -0,0 +1,63 @@ +diff -up qpdf-6.0.0/include/qpdf/QPDF.hh.detect-recursions qpdf-6.0.0/include/qpdf/QPDF.hh +--- qpdf-6.0.0/include/qpdf/QPDF.hh.detect-recursions 2017-08-10 13:39:58.361068939 +0200 ++++ qpdf-6.0.0/include/qpdf/QPDF.hh 2017-08-10 13:44:51.610688987 +0200 +@@ -603,6 +603,25 @@ class QPDF + int gen; + }; + ++ class ResolveRecorder ++ { ++ public: ++ ResolveRecorder(QPDF* qpdf, QPDFObjGen const& og) : ++ qpdf(qpdf), ++ og(og) ++ { ++ qpdf->resolving.insert(og); ++ } ++ virtual ~ResolveRecorder() ++ { ++ this->qpdf->resolving.erase(og); ++ } ++ private: ++ QPDF* qpdf; ++ QPDFObjGen og; ++ }; ++ friend class ResolveRecorder; ++ + void parse(char const* password); + void warn(QPDFExc const& e); + void setTrailer(QPDFObjectHandle obj); +@@ -1065,6 +1084,7 @@ class QPDF + std::map xref_table; + std::set deleted_objects; + std::map obj_cache; ++ std::set resolving; + QPDFObjectHandle trailer; + std::vector all_pages; + std::map pageobj_to_pages_pos; +diff -up qpdf-6.0.0/libqpdf/QPDF.cc.detect-recursions qpdf-6.0.0/libqpdf/QPDF.cc +--- qpdf-6.0.0/libqpdf/QPDF.cc.detect-recursions 2017-08-10 13:40:01.265045371 +0200 ++++ qpdf-6.0.0/libqpdf/QPDF.cc 2017-08-10 13:47:21.742475258 +0200 +@@ -1453,7 +1453,21 @@ QPDF::resolve(int objid, int generation) + // to insert things into the object cache that don't actually + // exist in the file. + QPDFObjGen og(objid, generation); +- if (! this->obj_cache.count(og)) ++ if (this->resolving.count(og)) ++ { ++ // This can happen if an object references itself directly or ++ // indirectly in some key that has to be resolved during ++ // object parsing, such as stream length. ++ warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), ++ "", this->file->getLastOffset(), ++ "loop detected resolving object " + ++ QUtil::int_to_string(objid) + " " + ++ QUtil::int_to_string(generation))); ++ return new QPDF_Null; ++ } ++ ResolveRecorder rr(this, og); ++ ++ if (! this->obj_cache.count(og)) + { + if (! this->xref_table.count(og)) + { diff --git a/qpdf.spec b/qpdf.spec index 480ad09..25452a9 100644 --- a/qpdf.spec +++ b/qpdf.spec @@ -1,13 +1,17 @@ Summary: Command-line tools and library for transforming PDF files Name: qpdf Version: 6.0.0 -Release: 7%{?dist} +Release: 8%{?dist} # MIT: e.g. libqpdf/sha2.c License: Artistic 2.0 and MIT URL: http://qpdf.sourceforge.net/ Source0: http://downloads.sourceforge.net/sourceforge/qpdf/qpdf-%{version}.tar.gz Patch0: qpdf-doc.patch +Patch1: qpdf-detect-recursions.patch +Patch2: qpdf-CVE-2017-9208.patch +Patch3: qpdf-CVE-2017-9209.patch +Patch4: qpdf-CVE-2017-9210.patch BuildRequires: zlib-devel BuildRequires: pcre-devel @@ -63,6 +67,14 @@ QPDF Manual # fix 'complete manual location' note in man pages %patch0 -p1 -b .doc +# 1477213 - Detect recursions loop resolving objects +%patch1 -p1 -b .detect-recursions +# 1454815 - (CVE-2017-9208) CVE-2017-9208 qpdf: Infinite loop related to releaseResolved functions +%patch2 -p1 -b .CVE-2017-9208 +# 1454816 - (CVE-2017-9209) CVE-2017-9209 qpdf: Infinite loop related to QPDFObjectHandle::parseInternal +%patch3 -p1 -b .CVE-2017-9209 +# 1454819 - (CVE-2017-9210) CVE-2017-9210 qpdf: Infinite loop related to unparse functions +%patch4 -p1 -b .CVE-2017-9210 sed -i -e '1s,^#!/usr/bin/env perl,#!/usr/bin/perl,' qpdf/fix-qdf @@ -108,6 +120,9 @@ make check %changelog +* Thu Aug 10 2017 Zdenek Dohnal - 6.0.0-8 +- adding patches for CVE back (cups-filters needed to rebuild) + * Mon Aug 07 2017 Zdenek Dohnal - 6.0.0-7 - removing patches for CVEs, because they break other things now