Hello community, here is the log from the commit of package podofo for openSUSE:Factory checked in at 2018-03-22 12:05:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/podofo (Old) and /work/SRC/openSUSE:Factory/.podofo.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "podofo" Thu Mar 22 12:05:05 2018 rev:26 rq:589243 version:0.9.5 Changes: -------- --- /work/SRC/openSUSE:Factory/podofo/podofo.changes 2017-12-19 10:51:43.840921123 +0100 +++ /work/SRC/openSUSE:Factory/.podofo.new/podofo.changes 2018-03-22 12:10:41.725676771 +0100 @@ -1,0 +2,51 @@ +Thu Mar 15 16:39:19 UTC 2018 - alarr...@suse.com + +- Add patches from upstream to fix many issues + (CVE-2017-5852, boo#1023067, CVE-2017-5853, boo#1023069, + CVE-2017-5854, boo#1023070, CVE-2017-5855, boo#1023071, + CVE-2017-5886, boo#1023380, CVE-2017-6840, boo#1027787, + CVE-2017-6844, boo#1027782, CVE-2017-6845, boo#1027779, + CVE-2017-6847, boo#1027778, CVE-2017-7378, boo#1032017, + CVE-2017-7379, boo#1032018, CVE-2017-7380, boo#1032019, + CVE-2017-7994, boo#1035534, CVE-2017-8054, boo#1035596, + CVE-2017-8787, boo#1037739, CVE-2018-5295, boo#1075026, + CVE-2018-5296, boo#1075021, CVE-2018-5308, boo#1075772, + CVE-2018-5309, boo#1075322, CVE-2018-8001, boo#1084894) + + * 0001-fix-a-crash-when-passing-a-PDF-file-with-an-encryption-dictionary-ref.patch + * 0002-fix-stack-overflow-crash-when-XRef-record-references-itself.patch + * 0003-Fix-for-CVE-2017-5852-with-added-error-code.patch + * 0004-Fix-for-CVE-2017-5854.patch + * 0005-Fix-for-CVE-2017-5886.patch + * 0006-Extend-fix-for-CVE-2017-5852.patch + * 0007-Fix-CVE-2017-5853-signed-integer-overflow-and-CVE-2017-6844-buffer-overflow.patch + * 0008-Fix-infinite-loop-in-GetPageNumber-if-Parent-chain-contains-a-loop.patch + * 0009-Fix-CVE-2017-7379-encoding-array-too-short-to-encode-decode-code-point-0xffff.patch + * 0010-Fix-CVE-2017-5855-CVE-2018-5296-NULL-pointer-dereference-in-PoDoFo-PdfParser-ReadXRefSubsection.patch + * 0011-Fix-CVE-2017-6840-Out-of-bounds-read-in-ColorChanger-GetColorFromStack.patch + * 0012-Correct-fix-for-CVE-2017-6840-Too-strict-check-for-given-arguments.patch + * 0013-Fix-CVE-2017-6847-NULL-pointer-dereference-when-reading-XObject-without-BBox.patch + * 0014-Fix-CVE-2017-7378-Out-of-bounds-read-in-PdfPainter-ExpandTabs.patch + * 0015-Fix-CVE-2017-7380-NULL-dereference-in-PdfPage-GetFromResources.patch + * 0016-Fix-CVE-2017-7994-NULL-dereference-in-TextExtractor-ExtractText.patch + * 0017-Fix-a-memory-leak-on-document-load-exception-in-podofotxtextract.patch + * 0018-Fix-for-CVE-2017-8787-Read-out-of-buffer-size-in-PdfXRefStreamParserObject-ReadXRefStreamEntry.patch + * 0019-Changes-needed-to-compile-podofo.patch + * 0020-Fix-regression-from-0007.patch + * 0021-Fix-a-build-break-with-OpenSSL-1.1.0f-configured-with-disable-deprecated-option.patch + * 0022-Correct-boundary-comparison-in-PdfListField::GetItemDisplayText.patch + * 0023-Correct-in-parameter-test-in-PdfMemoryOutputStream-Write.patch + * 0024-Fix-CVE-2017-8054-Detect-cycles-in-PdfPagesTree.patch + * 0025-Related-to-CVE-2018-5308.patch + * 0026-Revert-part-of-0024.patch + * 0027-Correction-for-reverted-part-of-CVE-2017-8054-fix-in-0027.patch + * 0028-Fix-for-CVE-2018-5295-Integer-overflow-at-PdfXRefStreamParserObject-ParseStream.patch + * 0029-Try-to-address-an-eventual-use-after-free-in-PdfObject.patch + * 0030-Fix-CVE-2017-6845-Do-not-disable-PODOFO_RAISE_LOGIC_IF-for-Release-builds.patch + * 0031-Fix-clamping-avoiding-crashes-in-PdfPagesTree-InsertPage.patch + * 0032-Fix-wrong-use-of-memcpy-instead-of-wmemcpy.patch + * 0033-Fix-for-CVE-2018-5309-integer-overflow-in-the-PdfObjectStreamParserObject-ReadObjectsFromStream.patch + * 0034-Fix-for-CVE-2018-8001-heap-based-buffer-over-read-in-UnescapeName.patch + * fix-missing-include.patch + +------------------------------------------------------------------- New: ---- 0001-fix-a-crash-when-passing-a-PDF-file-with-an-encryption-dictionary-ref.patch 0002-fix-stack-overflow-crash-when-XRef-record-references-itself.patch 0003-Fix-for-CVE-2017-5852-with-added-error-code.patch 0004-Fix-for-CVE-2017-5854.patch 0005-Fix-for-CVE-2017-5886.patch 0006-Extend-fix-for-CVE-2017-5852.patch 0007-Fix-CVE-2017-5853-signed-integer-overflow-and-CVE-2017-6844-buffer-overflow.patch 0008-Fix-infinite-loop-in-GetPageNumber-if-Parent-chain-contains-a-loop.patch 0009-Fix-CVE-2017-7379-encoding-array-too-short-to-encode-decode-code-point-0xffff.patch 0010-Fix-CVE-2017-5855-CVE-2018-5296-NULL-pointer-dereference-in-PoDoFo-PdfParser-ReadXRefSubsection.patch 0011-Fix-CVE-2017-6840-Out-of-bounds-read-in-ColorChanger-GetColorFromStack.patch 0012-Correct-fix-for-CVE-2017-6840-Too-strict-check-for-given-arguments.patch 0013-Fix-CVE-2017-6847-NULL-pointer-dereference-when-reading-XObject-without-BBox.patch 0014-Fix-CVE-2017-7378-Out-of-bounds-read-in-PdfPainter-ExpandTabs.patch 0015-Fix-CVE-2017-7380-NULL-dereference-in-PdfPage-GetFromResources.patch 0016-Fix-CVE-2017-7994-NULL-dereference-in-TextExtractor-ExtractText.patch 0017-Fix-a-memory-leak-on-document-load-exception-in-podofotxtextract.patch 0018-Fix-for-CVE-2017-8787-Read-out-of-buffer-size-in-PdfXRefStreamParserObject-ReadXRefStreamEntry.patch 0019-Changes-needed-to-compile-podofo.patch 0020-Fix-regression-from-0007.patch 0021-Fix-a-build-break-with-OpenSSL-1.1.0f-configured-with-disable-deprecated-option.patch 0022-Correct-boundary-comparison-in-PdfListField::GetItemDisplayText.patch 0023-Correct-in-parameter-test-in-PdfMemoryOutputStream-Write.patch 0024-Fix-CVE-2017-8054-Detect-cycles-in-PdfPagesTree.patch 0025-Related-to-CVE-2018-5308.patch 0026-Revert-part-of-0024.patch 0027-Correction-for-reverted-part-of-CVE-2017-8054-fix-in-0027.patch 0028-Fix-for-CVE-2018-5295-Integer-overflow-at-PdfXRefStreamParserObject-ParseStream.patch 0029-Try-to-address-an-eventual-use-after-free-in-PdfObject.patch 0030-Fix-CVE-2017-6845-Do-not-disable-PODOFO_RAISE_LOGIC_IF-for-Release-builds.patch 0031-Fix-clamping-avoiding-crashes-in-PdfPagesTree-InsertPage.patch 0032-Fix-wrong-use-of-memcpy-instead-of-wmemcpy.patch 0033-Fix-for-CVE-2018-5309-integer-overflow-in-the-PdfObjectStreamParserObject-ReadObjectsFromStream.patch 0034-Fix-for-CVE-2018-8001-heap-based-buffer-over-read-in-UnescapeName.patch fix-missing-include.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ podofo.spec ++++++ --- /var/tmp/diff_new_pack.6TuYPe/_old 2018-03-22 12:10:42.909634335 +0100 +++ /var/tmp/diff_new_pack.6TuYPe/_new 2018-03-22 12:10:42.917634048 +0100 @@ -1,7 +1,7 @@ # # spec file for package podofo # -# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,11 +22,45 @@ Version: 0.9.5 Release: 0 Summary: Tools to work with PDF files -License: GPL-2.0+ +License: GPL-2.0-or-later Group: Productivity/Publishing/PDF Url: http://podofo.sourceforge.net/ Source0: http://downloads.sourceforge.net/podofo/%{name}-%{version}.tar.gz - +Patch0: 0001-fix-a-crash-when-passing-a-PDF-file-with-an-encryption-dictionary-ref.patch +Patch1: 0002-fix-stack-overflow-crash-when-XRef-record-references-itself.patch +Patch2: 0003-Fix-for-CVE-2017-5852-with-added-error-code.patch +Patch3: 0004-Fix-for-CVE-2017-5854.patch +Patch4: 0005-Fix-for-CVE-2017-5886.patch +Patch5: 0006-Extend-fix-for-CVE-2017-5852.patch +Patch6: 0007-Fix-CVE-2017-5853-signed-integer-overflow-and-CVE-2017-6844-buffer-overflow.patch +Patch7: 0008-Fix-infinite-loop-in-GetPageNumber-if-Parent-chain-contains-a-loop.patch +Patch8: 0009-Fix-CVE-2017-7379-encoding-array-too-short-to-encode-decode-code-point-0xffff.patch +Patch9: 0010-Fix-CVE-2017-5855-CVE-2018-5296-NULL-pointer-dereference-in-PoDoFo-PdfParser-ReadXRefSubsection.patch +Patch10: 0011-Fix-CVE-2017-6840-Out-of-bounds-read-in-ColorChanger-GetColorFromStack.patch +Patch11: 0012-Correct-fix-for-CVE-2017-6840-Too-strict-check-for-given-arguments.patch +Patch12: 0013-Fix-CVE-2017-6847-NULL-pointer-dereference-when-reading-XObject-without-BBox.patch +Patch13: 0014-Fix-CVE-2017-7378-Out-of-bounds-read-in-PdfPainter-ExpandTabs.patch +Patch14: 0015-Fix-CVE-2017-7380-NULL-dereference-in-PdfPage-GetFromResources.patch +Patch15: 0016-Fix-CVE-2017-7994-NULL-dereference-in-TextExtractor-ExtractText.patch +Patch16: 0017-Fix-a-memory-leak-on-document-load-exception-in-podofotxtextract.patch +Patch17: 0018-Fix-for-CVE-2017-8787-Read-out-of-buffer-size-in-PdfXRefStreamParserObject-ReadXRefStreamEntry.patch +Patch18: 0019-Changes-needed-to-compile-podofo.patch +Patch19: 0020-Fix-regression-from-0007.patch +Patch20: 0021-Fix-a-build-break-with-OpenSSL-1.1.0f-configured-with-disable-deprecated-option.patch +Patch21: 0022-Correct-boundary-comparison-in-PdfListField::GetItemDisplayText.patch +Patch22: 0023-Correct-in-parameter-test-in-PdfMemoryOutputStream-Write.patch +Patch23: 0024-Fix-CVE-2017-8054-Detect-cycles-in-PdfPagesTree.patch +Patch24: 0025-Related-to-CVE-2018-5308.patch +Patch25: 0026-Revert-part-of-0024.patch +Patch26: 0027-Correction-for-reverted-part-of-CVE-2017-8054-fix-in-0027.patch +Patch27: 0028-Fix-for-CVE-2018-5295-Integer-overflow-at-PdfXRefStreamParserObject-ParseStream.patch +Patch28: 0029-Try-to-address-an-eventual-use-after-free-in-PdfObject.patch +Patch29: 0030-Fix-CVE-2017-6845-Do-not-disable-PODOFO_RAISE_LOGIC_IF-for-Release-builds.patch +Patch30: 0031-Fix-clamping-avoiding-crashes-in-PdfPagesTree-InsertPage.patch +Patch31: 0032-Fix-wrong-use-of-memcpy-instead-of-wmemcpy.patch +Patch32: 0033-Fix-for-CVE-2018-5309-integer-overflow-in-the-PdfObjectStreamParserObject-ReadObjectsFromStream.patch +Patch33: 0034-Fix-for-CVE-2018-8001-heap-based-buffer-over-read-in-UnescapeName.patch +Patch1000: fix-missing-include.patch BuildRequires: cmake >= 2.5 BuildRequires: doxygen BuildRequires: fdupes @@ -40,8 +74,8 @@ BuildRequires: libtiff-devel BuildRequires: lua-devel BuildRequires: openssl-devel -BuildRequires: zlib-devel BuildRequires: pkgconfig +BuildRequires: zlib-devel BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -50,7 +84,7 @@ %package -n libpodofo%{libver} Summary: PDF parsing and creation library -License: LGPL-2.1+ +License: LGPL-2.1-or-later Group: System/Libraries %description -n libpodofo%{libver} @@ -58,7 +92,7 @@ %package -n libpodofo-devel Summary: Development files for podofo -License: LGPL-2.1+ +License: LGPL-2.1-or-later Group: Development/Libraries/Other Requires: libpodofo%{libver} = %{version} @@ -67,6 +101,7 @@ %prep %setup -q +%autopatch -p3 # Remove build time references so build-compare can do its work echo "HTML_TIMESTAMP = NO" >> Doxyfile ++++++ 0001-fix-a-crash-when-passing-a-PDF-file-with-an-encryption-dictionary-ref.patch ++++++ Subject: Fix a crash when passing a PDF file with an encryption dictionary reference to a nonexistent object Url: https://sourceforge.net/p/podofo/code/1833/ --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -948,6 +948,14 @@ if( pEncrypt->IsReference() ) { i = pEncrypt->GetReference().ObjectNumber(); + if( i <= 0 || static_cast<size_t>( i ) >= m_offsets.size () ) + { + std::ostringstream oss; + oss << "Encryption dictionary references a nonexistent object " << pEncrypt->GetReference().ObjectNumber() << " " + << pEncrypt->GetReference().GenerationNumber(); + PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEncryptionDict, oss.str().c_str() ); + } + pObject = new PdfParserObject( m_vecObjects, m_device, m_buffer, m_offsets[i].lOffset ); if( !pObject ) PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); ++++++ 0002-fix-stack-overflow-crash-when-XRef-record-references-itself.patch ++++++ Subject: Fix stack overflow crash when XRef record references itself Url: https://sourceforge.net/p/podofo/code/1834/ --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -855,7 +855,7 @@ xrefObject.ReadXRefTable(); // Check for a previous XRefStm or xref table - if(xrefObject.HasPrevious()) + if(xrefObject.HasPrevious() && xrefObject.GetPreviousOffset() != lOffset) { try { m_nIncrementalUpdates++; ++++++ 0003-Fix-for-CVE-2017-5852-with-added-error-code.patch ++++++ Subject: Fix for CVE-2017-5852 with added error code Url: https://sourceforge.net/p/podofo/code/1835/ --- a/podofo/trunk/src/base/PdfError.cpp +++ b/podofo/trunk/src/base/PdfError.cpp @@ -222,6 +222,9 @@ case ePdfError_InvalidEnumValue: pszMsg = "ePdfError_InvalidEnumValue"; break; + case ePdfError_BrokenFile: + pszMsg = "ePdfError_BrokenFile"; + break; case ePdfError_PageNotFound: pszMsg = "ePdfError_PageNotFound"; break; @@ -396,6 +399,9 @@ break; case ePdfError_InvalidEnumValue: pszMsg = "An invalid enum value was specified."; + break; + case ePdfError_BrokenFile: + pszMsg = "The file content is broken."; break; case ePdfError_PageNotFound: pszMsg = "The requested page could not be found in the PDF."; --- a/podofo/trunk/src/base/PdfError.h +++ b/podofo/trunk/src/base/PdfError.h @@ -73,6 +73,7 @@ ePdfError_ValueOutOfRange, /**< The specified memory is out of the allowed range. */ ePdfError_InternalLogic, /**< An internal sanity check or assertion failed. */ ePdfError_InvalidEnumValue, /**< An invalid enum value was specified. */ + ePdfError_BrokenFile, /**< The file content is broken. */ ePdfError_PageNotFound, /**< The requested page could not be found in the PDF. */ --- a/podofo/trunk/src/doc/PdfPage.cpp +++ b/podofo/trunk/src/doc/PdfPage.cpp @@ -228,6 +228,14 @@ if( inObject->GetDictionary().HasKey( "Parent" ) ) { pObj = inObject->GetIndirectKey( "Parent" ); + if( pObj == inObject ) + { + std::ostringstream oss; + oss << "Object " << inObject->Reference().ObjectNumber() << " " + << inObject->Reference().GenerationNumber() << " references itself as Parent"; + PODOFO_RAISE_ERROR_INFO( ePdfError_BrokenFile, oss.str().c_str() ); + } + if( pObj ) pObj = GetInheritedKeyFromObject( inKey, pObj ); } ++++++ 0004-Fix-for-CVE-2017-5854.patch ++++++ Subject: Fix for CVE-2017-5854 Url: https://sourceforge.net/p/podofo/code/1836/ --- a/podofo/trunk/tools/podofopdfinfo/pdfinfo.cpp +++ b/podofo/trunk/tools/podofopdfinfo/pdfinfo.cpp @@ -207,6 +207,10 @@ for ( int pg=0; pg<pgCount; pg++ ) { curPage = mDoc->GetPage( pg ); + if( !curPage ) + { + PODOFO_RAISE_ERROR( PoDoFo::ePdfError_PageNotFound ); + } rect = curPage->GetMediaBox(); Format s( rect.GetWidth() - rect.GetLeft(), rect.GetHeight() - rect.GetBottom()); sIt = sizes.find(s); ++++++ 0005-Fix-for-CVE-2017-5886.patch ++++++ Subject: Fix for CVE-2017-5886 Url: https://sourceforge.net/p/podofo/code/1837/ --- a/podofo/trunk/src/base/PdfTokenizer.cpp +++ b/podofo/trunk/src/base/PdfTokenizer.cpp @@ -239,7 +239,7 @@ *peType = ePdfTokenType_Token; while( (c = m_device.Device()->Look()) != EOF - && counter < static_cast<pdf_int64>(m_buffer.GetSize()) ) + && counter + 1 < static_cast<pdf_int64>(m_buffer.GetSize()) ) { // ignore leading whitespaces if( !counter && IsWhitespace( c ) ) @@ -317,7 +317,6 @@ } m_buffer.GetBuffer()[counter] = '\0'; - if( c == EOF && !counter ) { ++++++ 0006-Extend-fix-for-CVE-2017-5852.patch ++++++ Subject: Patch by Mark Rogers: Extend fix for CVE-2017-5852 Url: https://sourceforge.net/p/podofo/code/1838/ --- a/podofo/trunk/src/doc/PdfPage.cpp +++ b/podofo/trunk/src/doc/PdfPage.cpp @@ -212,7 +212,7 @@ return rect; } -const PdfObject* PdfPage::GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject ) const +const PdfObject* PdfPage::GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject, int depth ) const { const PdfObject* pObj = NULL; @@ -227,6 +227,18 @@ // if we get here, we need to go check the parent - if there is one! if( inObject->GetDictionary().HasKey( "Parent" ) ) { + // CVE-2017-5852 - prevent stack overflow if Parent chain contains a loop, or is very long + // e.g. pObj->GetParent() == pObj or pObj->GetParent()->GetParent() == pObj + // default stack sizes + // Windows: 1 MB + // Linux: 2 MB + // macOS: 8 MB for main thread, 0.5 MB for secondary threads + // 0.5 MB is enough space for 1000 512 byte stack frames and 2000 256 byte stack frames + const int maxRecursionDepth = 1000; + + if ( depth > maxRecursionDepth ) + PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); + pObj = inObject->GetIndirectKey( "Parent" ); if( pObj == inObject ) { @@ -237,7 +249,7 @@ } if( pObj ) - pObj = GetInheritedKeyFromObject( inKey, pObj ); + pObj = GetInheritedKeyFromObject( inKey, pObj, depth + 1 ); } return pObj; --- a/podofo/trunk/src/doc/PdfPage.h +++ b/podofo/trunk/src/doc/PdfPage.h @@ -291,7 +291,7 @@ /** Method for getting a key value that could be inherited (such as the boxes, resources, etc.) * \returns PdfObject - the result of the key fetching or NULL */ - const PdfObject* GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject ) const; + const PdfObject* GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject, int depth = 0 ) const; /** Get the annotations array. * \param bCreate if true the annotations array is created ++++++ 0007-Fix-CVE-2017-5853-signed-integer-overflow-and-CVE-2017-6844-buffer-overflow.patch ++++++ Subject: Patch by Matthias Brinke: Fix CVE-2017-5853 (signed integer overflow) and CVE-2017-6844 (buffer overflow) Url: https://sourceforge.net/p/podofo/code/1840/ --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -745,21 +745,39 @@ void PdfParser::ReadXRefSubsection( pdf_int64 & nFirstObject, pdf_int64 & nNumObjects ) { - int count = 0; + pdf_int64 count = 0; #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Reading XRef Section: %" PDF_FORMAT_INT64 " with %" PDF_FORMAT_INT64 " Objects.\n", nFirstObject, nNumObjects ); #endif // PODOFO_VERBOSE_DEBUG - if ( nFirstObject + nNumObjects > m_nNumObjects ) - { - // Total number of xref entries to read is greater than the /Size - // specified in the trailer if any. That's an error unless we're trying - // to recover from a missing /Size entry. - PdfError::LogMessage( eLogSeverity_Warning, - "There are more objects (%" PDF_FORMAT_INT64 ") in this XRef table than " - "specified in the size key of the trailer directory (%" PDF_FORMAT_INT64 ")!\n", - nFirstObject + nNumObjects, m_nNumObjects ); + if ( nFirstObject < 0 ) + PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "ReadXRefSubsection: nFirstObject is negative" ); + if ( nNumObjects < 0 ) + PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "ReadXRefSubsection: nNumObjects is negative" ); + + const pdf_int64 maxNum + = static_cast<pdf_int64>(PdfParser::s_nMaxObjects); + + // overflow guard, fixes CVE-2017-5853 (signed integer overflow) + // also fixes CVE-2017-6844 (buffer overflow) together with below size check + if( (maxNum >= nNumObjects) && (nFirstObject <= maxNum - nNumObjects) ) + { + if( nFirstObject + nNumObjects > m_nNumObjects ) + { + // Total number of xref entries to read is greater than the /Size + // specified in the trailer if any. That's an error unless we're + // trying to recover from a missing /Size entry. + PdfError::LogMessage( eLogSeverity_Warning, + "There are more objects (%" PDF_FORMAT_INT64 ") in this XRef " + "table than specified in the size key of the trailer directory " + "(%" PDF_FORMAT_INT64 ")!\n", nFirstObject + nNumObjects, + static_cast<pdf_int64>( m_nNumObjects )); + } + + if ( static_cast<pdf_uint64>( nFirstObject ) + static_cast<pdf_uint64>( nNumObjects ) > static_cast<pdf_uint64>( std::numeric_limits<size_t>::max() ) ) + PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, + "xref subsection's given entry numbers together too large" ); #ifdef _WIN32 m_nNumObjects = static_cast<long>(nFirstObject + nNumObjects); @@ -768,7 +786,16 @@ m_nNumObjects = nFirstObject + nNumObjects; m_offsets.resize(nFirstObject+nNumObjects); #endif // _WIN32 - } + + } + else + { + PdfError::LogMessage( eLogSeverity_Error, "There are more objects (%" PDF_FORMAT_INT64 + " + %" PDF_FORMAT_INT64 " seemingly) in this XRef" + " table than supported by standard PDF, or it's inconsistent.\n", + nFirstObject, nNumObjects); + PODOFO_RAISE_ERROR( ePdfError_InvalidXRef ); + } // consume all whitespaces int charcode; ++++++ 0008-Fix-infinite-loop-in-GetPageNumber-if-Parent-chain-contains-a-loop.patch ++++++ Subject: Patch by Mark Rogers: Fix infinite loop in GetPageNumber() if Parent chain contains a loop Url: https://sourceforge.net/p/podofo/code/1841/ --- a/podofo/trunk/src/doc/PdfPage.cpp +++ b/podofo/trunk/src/doc/PdfPage.cpp @@ -543,6 +543,11 @@ PdfObject* pParent = this->GetObject()->GetIndirectKey( "Parent" ); PdfReference ref = this->GetObject()->Reference(); + // CVE-2017-5852 - prevent infinite loop if Parent chain contains a loop + // e.g. pParent->GetIndirectKey( "Parent" ) == pParent or pParent->GetIndirectKey( "Parent" )->GetIndirectKey( "Parent" ) == pParent + const int maxRecursionDepth = 1000; + int depth = 0; + while( pParent ) { PdfObject* pKids = pParent->GetIndirectKey( "Kids" ); @@ -574,6 +579,12 @@ ref = pParent->Reference(); pParent = pParent->GetIndirectKey( "Parent" ); + ++depth; + + if ( depth > maxRecursionDepth ) + { + PODOFO_RAISE_ERROR_INFO( ePdfError_BrokenFile, "Loop in Parent chain" ); + } } return ++nPageNumber; ++++++ 0009-Fix-CVE-2017-7379-encoding-array-too-short-to-encode-decode-code-point-0xffff.patch ++++++ Subject: Patch by Mark Rogers: Fix CVE-2017-7379: encoding array too short to encode/decode code point 0xffff Url: https://sourceforge.net/p/podofo/code/1842/ --- a/podofo/trunk/src/base/PdfEncoding.cpp +++ b/podofo/trunk/src/base/PdfEncoding.cpp @@ -45,6 +45,7 @@ #include <stack> #include <stdlib.h> #include <string.h> +#include <limits> #include <sstream> #include "PdfArray.h" #include "doc/PdfDifferenceEncoding.h" @@ -362,7 +363,9 @@ void PdfSimpleEncoding::InitEncodingTable() { Util::PdfMutexWrapper wrapper( *m_mutex ); - const long lTableLength = 0xffff; + // CVE-2017-7379 - previously lTableLength was 0xffff, but pdf_utf16be characters can be in range 0..0xffff so this + // caused out-by-one heap overflow when character 0xffff was encoded + const long lTableLength = std::numeric_limits<pdf_utf16be>::max() + 1; const pdf_utf16be* cpUnicodeTable = this->GetToUnicodeTable(); if( !m_pEncodingTable ) // double check ++++++ 0010-Fix-CVE-2017-5855-CVE-2018-5296-NULL-pointer-dereference-in-PoDoFo-PdfParser-ReadXRefSubsection.patch ++++++ Subject: Fix CVE-2017-5855: NULL pointer dereference in PoDoFo::PdfParser::ReadXRefSubsection Url: https://sourceforge.net/p/podofo/code/1843/ Throw PoDoFo's Out of memory exception when resize of std::vector fails when reading XRef content. Fixes: CVE-2017-5855, CVE-2018-5296 --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -779,6 +779,7 @@ PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "xref subsection's given entry numbers together too large" ); + try { #ifdef _WIN32 m_nNumObjects = static_cast<long>(nFirstObject + nNumObjects); m_offsets.resize(static_cast<long>(nFirstObject+nNumObjects)); @@ -786,7 +787,9 @@ m_nNumObjects = nFirstObject + nNumObjects; m_offsets.resize(nFirstObject+nNumObjects); #endif // _WIN32 - + } catch (std::bad_alloc &ex) { + PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); + } } else { ++++++ 0011-Fix-CVE-2017-6840-Out-of-bounds-read-in-ColorChanger-GetColorFromStack.patch ++++++ Subject: Fix CVE-2017-6840: Out of bounds read in ColorChanger::GetColorFromStack() Url: https://sourceforge.net/p/podofo/code/1844/ --- a/podofo/trunk/tools/podofocolor/colorchanger.cpp +++ b/podofo/trunk/tools/podofocolor/colorchanger.cpp @@ -181,6 +181,13 @@ int nNumArgs = pInfo->nNumArguments; EPdfColorSpace eColorSpace; + if( args.size() != static_cast<size_t>( pInfo->nNumArguments ) ) + { + std::ostringstream oss; + oss << "Expected " << pInfo->nNumArguments << " argument(s) for keyword '" << pszKeyword << "', but " << args.size() << " given instead."; + PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidContentStream, oss.str().c_str() ); + } + switch( pInfo->eKeywordType ) { case eKeyword_GraphicsStack_Push: ++++++ 0012-Correct-fix-for-CVE-2017-6840-Too-strict-check-for-given-arguments.patch ++++++ Subject: Correct fix for CVE-2017-6840: Too strict check for given arguments. Url: https://sourceforge.net/p/podofo/code/1845/ --- a/podofo/trunk/tools/podofocolor/colorchanger.cpp +++ b/podofo/trunk/tools/podofocolor/colorchanger.cpp @@ -181,7 +181,7 @@ int nNumArgs = pInfo->nNumArguments; EPdfColorSpace eColorSpace; - if( args.size() != static_cast<size_t>( pInfo->nNumArguments ) ) + if( pInfo->nNumArguments > 0 && args.size() != static_cast<size_t>( pInfo->nNumArguments ) ) { std::ostringstream oss; oss << "Expected " << pInfo->nNumArguments << " argument(s) for keyword '" << pszKeyword << "', but " << args.size() << " given instead."; ++++++ 0013-Fix-CVE-2017-6847-NULL-pointer-dereference-when-reading-XObject-without-BBox.patch ++++++ Subject: Fix CVE-2017-6847: NULL pointer dereference when reading XObject without BBox Url: https://sourceforge.net/p/podofo/code/1846/ --- a/podofo/trunk/src/doc/PdfXObject.cpp +++ b/podofo/trunk/src/doc/PdfXObject.cpp @@ -261,8 +261,10 @@ m_pResources = pObject->GetIndirectKey( "Resources" ); m_Identifier = PdfName( out.str().c_str() ); - m_rRect = PdfRect( this->GetObject()->GetIndirectKey( "BBox" )->GetArray() ); - m_Reference = this->GetObject()->Reference(); + m_Reference = this->GetObject()->Reference(); + + if( this->GetObject()->GetIndirectKey( "BBox" ) ) + m_rRect = PdfRect( this->GetObject()->GetIndirectKey( "BBox" )->GetArray() ); } void PdfXObject::InitXObject( const PdfRect & rRect, const char* pszPrefix ) ++++++ 0014-Fix-CVE-2017-7378-Out-of-bounds-read-in-PdfPainter-ExpandTabs.patch ++++++ Subject: Fix CVE-2017-7378: Out of bounds read in PdfPainter::ExpandTabs Url: https://sourceforge.net/p/podofo/code/1847/ --- a/podofo/trunk/src/doc/PdfPainter.cpp +++ b/podofo/trunk/src/doc/PdfPainter.cpp @@ -1938,16 +1938,27 @@ const pdf_utf16be cTab = 0x0900; const pdf_utf16be cSpace = 0x2000; + if( lStringLen == -1 ) + lStringLen = rsString.GetCharacterLength(); + + if (lStringLen > rsString.GetCharacterLength()) + { + PdfError::DebugMessage( "Requested to expand tabs in string of %" PDF_FORMAT_INT64 " chars, while it has only %" PDF_FORMAT_INT64 "; correcting the value\n", + static_cast<pdf_int64>( lStringLen ), static_cast<pdf_int64>( rsString.GetCharacterLength() ) ); + + lStringLen = rsString.GetCharacterLength(); + } + // count the number of tabs in the string if( bUnicode ) { - for( i=0;i<=lStringLen;i++ ) + for( i=0;i<lStringLen;i++ ) if( rsString.GetUnicode()[i] == cTab ) ++nTabCnt; } else { - for( i=0;i<=lStringLen;i++ ) + for( i=0;i<lStringLen;i++ ) if( rsString.GetString()[i] == '\t' ) ++nTabCnt; } ++++++ 0015-Fix-CVE-2017-7380-NULL-dereference-in-PdfPage-GetFromResources.patch ++++++ Subject: Fix CVE-2017-7380: NULL dereference in PdfPage::GetFromResources() Url: https://sourceforge.net/p/podofo/code/1848/ --- a/podofo/trunk/src/doc/PdfPage.cpp +++ b/podofo/trunk/src/doc/PdfPage.cpp @@ -642,7 +642,7 @@ // OC 15.08.2010 BugFix: Ghostscript creates here sometimes an indirect reference to a directory // PdfObject* pType = m_pResources->GetDictionary().GetKey( rType ); PdfObject* pType = m_pResources->GetIndirectKey( rType ); - if( pType->IsDictionary() && pType->GetDictionary().HasKey( rKey ) ) + if( pType && pType->IsDictionary() && pType->GetDictionary().HasKey( rKey ) ) { const PdfReference & ref = pType->GetDictionary().GetKey( rKey )->GetReference(); return this->GetObject()->GetOwner()->GetObject( ref ); ++++++ 0016-Fix-CVE-2017-7994-NULL-dereference-in-TextExtractor-ExtractText.patch ++++++ Subject: Fix CVE-2017-7994: NULL dereference in TextExtractor::ExtractText Url: https://sourceforge.net/p/podofo/code/1849/ --- a/podofo/trunk/tools/podofotxtextract/TextExtractor.cpp +++ b/podofo/trunk/tools/podofotxtextract/TextExtractor.cpp @@ -72,10 +72,21 @@ if( strcmp( pszToken, "l" ) == 0 || strcmp( pszToken, "m" ) == 0 ) { - dCurPosX = stack.top().GetReal(); - stack.pop(); - dCurPosY = stack.top().GetReal(); - stack.pop(); + if( stack.size() == 2 ) + { + dCurPosX = stack.top().GetReal(); + stack.pop(); + dCurPosY = stack.top().GetReal(); + stack.pop(); + } + else + { + fprintf( stderr, "WARNING: Token '%s' expects two arguments, but %" PDF_FORMAT_INT64 " given; ignoring\n", + pszToken, static_cast<pdf_int64>( stack.size() ) ); + + while( !stack.empty() ) + stack.pop(); + } } else if( strcmp( pszToken, "BT" ) == 0 ) { @@ -93,6 +104,13 @@ { if( strcmp( pszToken, "Tf" ) == 0 ) { + if( stack.size() < 2 ) + { + fprintf( stderr, "WARNING: Expects two arguments for 'Tf', ignoring\n" ); + pCurFont = NULL; + continue; + } + stack.pop(); PdfName fontName = stack.top().GetName(); PdfObject* pFont = pPage->GetFromResources( PdfName("Font"), fontName ); @@ -102,21 +120,37 @@ } pCurFont = pDocument->GetFont( pFont ); - if( !pCurFont ) - { - fprintf( stderr, "WARNING: Unable to create font for object %i %i R\n", - pFont->Reference().ObjectNumber(), - pFont->Reference().GenerationNumber() ); + if( !pCurFont ) + { + fprintf( stderr, "WARNING: Unable to create font for object %" PDF_FORMAT_INT64 " %" PDF_FORMAT_INT64 " R\n", + static_cast<pdf_int64>( pFont->Reference().ObjectNumber() ), + static_cast<pdf_int64>( pFont->Reference().GenerationNumber() ) ); } } else if( strcmp( pszToken, "Tj" ) == 0 || strcmp( pszToken, "'" ) == 0 ) { + if( stack.size() < 1 ) + { + fprintf( stderr, "WARNING: Expects one argument for '%s', ignoring\n", pszToken ); + continue; + } + AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); } else if( strcmp( pszToken, "\"" ) == 0 ) { + if( stack.size() < 3 ) + { + fprintf( stderr, "WARNING: Expects three arguments for '%s', ignoring\n", pszToken ); + + while( !stack.empty() ) + stack.pop(); + + continue; + } + AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); stack.pop(); // remove char spacing from stack @@ -124,6 +158,12 @@ } else if( strcmp( pszToken, "TJ" ) == 0 ) { + if( stack.size() < 3 ) + { + fprintf( stderr, "WARNING: Expects one argument for '%s', ignoring\n", pszToken ); + continue; + } + PdfArray array = stack.top().GetArray(); stack.pop(); ++++++ 0017-Fix-a-memory-leak-on-document-load-exception-in-podofotxtextract.patch ++++++ Subject: Fix a memory leak on document load exception in podofotxtextract Url: https://sourceforge.net/p/podofo/code/1850/ --- a/podofo/trunk/tools/podofotxtextract/TextExtractor.cpp +++ b/podofo/trunk/tools/podofotxtextract/TextExtractor.cpp @@ -38,7 +38,9 @@ PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } - PdfMemDocument document( pszInput ); + PdfMemDocument document; + + document.Load( pszInput ); int nCount = document.GetPageCount(); for( int i=0; i<nCount; i++ ) ++++++ 0018-Fix-for-CVE-2017-8787-Read-out-of-buffer-size-in-PdfXRefStreamParserObject-ReadXRefStreamEntry.patch ++++++ Subject: Fix for CVE-2017-8787 - Read out of buffer size in PdfXRefStreamParserObject::ReadXRefStreamEntry( Url: https://sourceforge.net/p/podofo/code/1851/ --- a/podofo/trunk/src/base/PdfXRefStreamParserObject.cpp +++ b/podofo/trunk/src/base/PdfXRefStreamParserObject.cpp @@ -123,6 +123,11 @@ char* pBuffer; pdf_long lBufferLen; const size_t entryLen = static_cast<size_t>(nW[0] + nW[1] + nW[2]); + + if( nW[0] + nW[1] + nW[2] < 0 ) + { + PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Invalid entry length in XRef stream" ); + } this->GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); ++++++ 0019-Changes-needed-to-compile-podofo.patch ++++++ Subject: Changes needed to compile podofo 0.9.5 on CentOS 7, but are probably useful for other distributions too Url: https://sourceforge.net/p/podofo/code/1854/ Patch by Jan-Erik S The following diff contains changes needed to compile podofo 0.9.5 on CentOS 7, but are probably useful for other distributions too. The first of them can be explained by the description here: https://cmake.org/cmake/help/v3.0/manual/cmake-policies.7.html The other can be explained by running this command: cpp -dM < /dev/null | grep -E 'PTRDIFF_MAX|INT_MAX' --- a/podofo/trunk/CMakeLists.txt +++ b/podofo/trunk/CMakeLists.txt @@ -32,7 +32,9 @@ # Prefer files in CMAKE_MODULE_PATH over shipped ones in module directory CMAKE_POLICY(SET CMP0017 NEW) # https://cmake.org/cmake/help/v3.0/policy/CMP0017.html # Do not use export_library_dependencies() anymore +if(POLICY CMP0033) CMAKE_POLICY(SET CMP0033 NEW) # https://cmake.org/cmake/help/v3.0/policy/CMP0033.html +endif() # Load modules from our source tree too SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -63,6 +63,8 @@ #if defined( PTRDIFF_MAX ) #define PDF_LONG_MAX PTRDIFF_MAX +#elif defined( __PTRDIFF_MAX__ ) +#define PDF_LONG_MAX __PTRDIFF_MAX__ #else // only old compilers don't define PTRDIFF_MAX (all 32-bit only?) #define PDF_LONG_MAX INT_MAX ++++++ 0020-Fix-regression-from-0007.patch ++++++ Subject: Fix regression from r1840: Make PdfParser::m_offsets resize only to grow Url: https://sourceforge.net/p/podofo/code/1859/ --- a/podofo/trunk/src/base/PdfParser.cpp +++ b/podofo/trunk/src/base/PdfParser.cpp @@ -781,16 +781,19 @@ PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "xref subsection's given entry numbers together too large" ); - try { + if( nFirstObject + nNumObjects > m_nNumObjects ) + { + try { #ifdef _WIN32 - m_nNumObjects = static_cast<long>(nFirstObject + nNumObjects); - m_offsets.resize(static_cast<long>(nFirstObject+nNumObjects)); + m_nNumObjects = static_cast<long>(nFirstObject + nNumObjects); + m_offsets.resize(static_cast<long>(nFirstObject+nNumObjects)); #else - m_nNumObjects = nFirstObject + nNumObjects; - m_offsets.resize(nFirstObject+nNumObjects); + m_nNumObjects = nFirstObject + nNumObjects; + m_offsets.resize(nFirstObject+nNumObjects); #endif // _WIN32 - } catch (std::bad_alloc &ex) { - PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); + } catch (std::bad_alloc &) { + PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); + } } } else ++++++ 0021-Fix-a-build-break-with-OpenSSL-1.1.0f-configured-with-disable-deprecated-option.patch ++++++ Subject: Fix a build break with OpenSSL 1.1.0f configured with disable-deprecated option Url: https://sourceforge.net/p/podofo/code/1860/ --- a/podofo/trunk/CMakeLists.txt +++ b/podofo/trunk/CMakeLists.txt @@ -498,6 +498,7 @@ ${LIBIDN_LIBRARIES} ${LIBCRYPTO_LDFLAGS} ${LIBCRYPTO_LIBRARIES} + ${OPENSSL_LIBRARIES} ${LIBJPEG_LIBRARIES} ${PLATFORM_SYSTEM_LIBRARIES} ${stlport_libraries_if_use_stlport} --- a/podofo/trunk/tools/podofosign/podofosign.cpp +++ b/podofo/trunk/tools/podofosign/podofosign.cpp @@ -27,6 +27,7 @@ #include <openssl/evp.h> #include <openssl/err.h> #include <openssl/pem.h> +#include <openssl/ssl.h> #include <openssl/x509.h> using namespace PoDoFo; @@ -874,11 +875,15 @@ outputfile = NULL; } +#ifdef PODOFO_HAVE_OPENSSL_1_1 + OPENSSL_init_ssl(0, NULL); +#else OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ERR_load_PEM_strings(); ERR_load_ASN1_strings(); ERR_load_EVP_strings(); +#endif X509* cert = NULL; EVP_PKEY* pkey = NULL; @@ -1082,7 +1087,9 @@ result = e.GetError(); } +#ifndef PODOFO_HAVE_OPENSSL_1_1 ERR_free_strings(); +#endif if( pSignField ) delete pSignField; ++++++ 0022-Correct-boundary-comparison-in-PdfListField::GetItemDisplayText.patch ++++++ Subject: Fix by Michal Sudolsky: Correct boundary comparison in PdfListField::GetItemDisplayText() Url: https://sourceforge.net/p/podofo/code/1863/ --- a/podofo/trunk/src/doc/PdfField.cpp +++ b/podofo/trunk/src/doc/PdfField.cpp @@ -891,7 +891,7 @@ if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); - if( nIndex < 0 || nIndex > static_cast<int>(opt.size()) ) + if( nIndex < 0 || nIndex >= static_cast<int>(opt.size()) ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } ++++++ 0023-Correct-in-parameter-test-in-PdfMemoryOutputStream-Write.patch ++++++ Subject: Correct in-parameter test in PdfMemoryOutputStream::Write Url: https://sourceforge.net/p/podofo/code/1870/ This could eventually cause NULL pointer being passed into memcpy() function. --- a/podofo/trunk/src/base/PdfOutputStream.cpp +++ b/podofo/trunk/src/base/PdfOutputStream.cpp @@ -98,7 +98,7 @@ pdf_long PdfMemoryOutputStream::Write( const char* pBuffer, pdf_long lLen ) { - if( !m_pBuffer ) + if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } ++++++ 0024-Fix-CVE-2017-8054-Detect-cycles-in-PdfPagesTree.patch ++++++ Subject: Fix by Matthias Brinke: CVE-2017-8054 - Detect cycles in PdfPagesTree Url: https://sourceforge.net/p/podofo/code/1872/ --- a/podofo/trunk/src/base/PdfError.cpp +++ b/podofo/trunk/src/base/PdfError.cpp @@ -60,6 +60,12 @@ { } +PdfErrorInfo::PdfErrorInfo( int line, const char* pszFile, std::string sInfo ) + : m_nLine( line ), m_sFile( pszFile ? pszFile : "" ), m_sInfo( sInfo ) +{ + +} + PdfErrorInfo::PdfErrorInfo( int line, const char* pszFile, const char* pszInfo ) : m_nLine( line ), m_sFile( pszFile ? pszFile : "" ), m_sInfo( pszInfo ? pszInfo : "" ) { @@ -93,6 +99,12 @@ PdfError::PdfError() { m_error = ePdfError_ErrOk; +} + +PdfError::PdfError( const EPdfError & eCode, const char* pszFile, int line, + std::string sInformation ) +{ + this->SetError( eCode, pszFile, line, sInformation ); } PdfError::PdfError( const EPdfError & eCode, const char* pszFile, int line, --- a/podofo/trunk/src/base/PdfError.h +++ b/podofo/trunk/src/base/PdfError.h @@ -158,8 +158,8 @@ /** \def PODOFO_RAISE_ERROR_INFO( x, y ) * * Set the value of the variable eCode (which has to exist in the current function) to x - * and return the eCode. Additionally additional information on the error y is set. y has - * to be an c-string. + * and return the eCode. Additionally additional information on the error y is set. + * y can be a C string, but can also be a C++ std::string. */ #define PODOFO_RAISE_ERROR_INFO( x, y ) throw ::PoDoFo::PdfError( x, __FILE__, __LINE__, y ); @@ -184,6 +184,7 @@ public: PdfErrorInfo(); PdfErrorInfo( int line, const char* pszFile, const char* pszInfo ); + PdfErrorInfo( int line, const char* pszFile, std::string pszInfo ); PdfErrorInfo( int line, const char* pszFile, const wchar_t* pszInfo ); PdfErrorInfo( const PdfErrorInfo & rhs ); @@ -195,6 +196,7 @@ inline const std::wstring & GetInformationW() const { return m_swInfo; } inline void SetInformation( const char* pszInfo ) { m_sInfo = pszInfo ? pszInfo : ""; } + inline void SetInformation( std::string pszInfo ) { m_sInfo = pszInfo; } inline void SetInformation( const wchar_t* pszInfo ) { m_swInfo = pszInfo ? pszInfo : L""; } private: @@ -252,11 +254,21 @@ * Use the compiler macro __FILE__ to initialize the field. * \param line the line in which the error has occured. * Use the compiler macro __LINE__ to initialize the field. - * \param pszInformation additional information on this error which mayy - * be formatted like printf + * \param pszInformation additional information on this error */ PdfError( const EPdfError & eCode, const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL ); + + /** Create a PdfError object with a given error code. + * \param eCode the error code of this object + * \param pszFile the file in which the error has occured. + * Use the compiler macro __FILE__ to initialize the field. + * \param line the line in which the error has occured. + * Use the compiler macro __LINE__ to initialize the field. + * \param sInformation additional information on this error + */ + explicit PdfError( const EPdfError & eCode, const char* pszFile, int line, + std::string sInformation ); /** Copy constructor * \param rhs copy the contents of rhs into this object @@ -310,6 +322,21 @@ * \return the callstack */ inline const TDequeErrorInfo & GetCallstack() const; + + /** Set the error code of this object. + * \param eCode the error code of this object + * \param pszFile the filename of the source file causing + * the error or NULL. Typically you will use + * the gcc macro __FILE__ here. + * \param line the line of source causing the error + * or 0. Typically you will use the gcc + * macro __LINE__ here. + * \param sInformation additional information on the error. + * e.g. how to fix the error. This string is intended to + * be shown to the user. + */ + inline void SetError( const EPdfError & eCode, const char* pszFile, int line, + std::string sInformation ); /** Set the error code of this object. * \param eCode the error code of this object @@ -354,6 +381,21 @@ */ inline void AddToCallstack( const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL ); + /** Add callstack information to an error object. Always call this function + * if you get an error object but do not handle the error but throw it again. + * + * \param pszFile the filename of the source file causing + * the error or NULL. Typically you will use + * the gcc macro __FILE__ here. + * \param line the line of source causing the error + * or 0. Typically you will use the gcc + * macro __LINE__ here. + * \param sInformation additional information on the error. + * e.g. how to fix the error. This string is intended to + * be shown to the user. + */ + inline void AddToCallstack( const char* pszFile, int line, std::string sInformation ); + /** \returns true if an error code was set * and false if the error code is ePdfError_ErrOk */ @@ -488,6 +530,22 @@ // ----------------------------------------------------- // // ----------------------------------------------------- +void PdfError::SetError( const EPdfError & eCode, const char* pszFile, int line, std::string sInformation ) +{ + m_error = eCode; + this->AddToCallstack( pszFile, line, sInformation ); +} + +// ----------------------------------------------------- +// +// ----------------------------------------------------- +void PdfError::AddToCallstack( const char* pszFile, int line, std::string sInformation ) +{ + m_callStack.push_front( PdfErrorInfo( line, pszFile, sInformation ) ); +} +// ----------------------------------------------------- +// +// ----------------------------------------------------- void PdfError::SetErrorInformation( const char* pszInformation ) { if( m_callStack.size() ) --- a/podofo/trunk/src/doc/PdfPagesTree.cpp +++ b/podofo/trunk/src/doc/PdfPagesTree.cpp @@ -34,6 +34,7 @@ #include "PdfPagesTree.h" #include "base/PdfDefinesPrivate.h" +#include <algorithm> #include "base/PdfArray.h" #include "base/PdfDictionary.h" @@ -478,7 +479,17 @@ if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays - return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); + // Recursive call removed to prevent stack overflow, replaced by: + // all the following inside this conditional, plus restart looping + const PdfArray & rVarArray = rVar.GetArray(); + if (rVarArray.GetSize() == 0) + { + PdfError::LogMessage( eLogSeverity_Critical, "Trying to access" + " first page index of empty array" ); + return NULL; + } + rVar = rVarArray[0]; + continue; } else if( !rVar.IsReference() ) { @@ -502,6 +513,18 @@ if( !pgObject->GetDictionary().HasKey( "Kids" ) ) return NULL; + if ( std::find( rLstParents.begin(), rLstParents.end(), pgObject ) + != rLstParents.end() ) // cycle in parent list detected, fend + { // off security vulnerability CVE-2017-8054 (infinite recursion) + std::ostringstream oss; + oss << "Cycle in page tree: child in /Kids array of object " + << ( *(rLstParents.rbegin()) )->Reference().ToString() + << " back-references to object " << pgObject->Reference() + .ToString() << " one of whose descendants the former is."; + + PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, oss.str() ); + } + rLstParents.push_back( pgObject ); rVar = *(pgObject->GetDictionary().GetKey( "Kids" )); } else { ++++++ 0025-Related-to-CVE-2018-5308.patch ++++++ Subject: Related to CVE-2018-5308: Add in-parameter validity check Url: https://sourceforge.net/p/podofo/code/1876/ --- a/podofo/trunk/src/base/PdfOutputStream.cpp +++ b/podofo/trunk/src/base/PdfOutputStream.cpp @@ -85,6 +85,11 @@ PdfMemoryOutputStream::PdfMemoryOutputStream( char* pBuffer, pdf_long lLen ) : m_lLen( 0 ), m_bOwnBuffer( false ) { + if( !pBuffer ) + { + PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); + } + m_lSize = lLen; m_pBuffer = pBuffer; } ++++++ 0026-Revert-part-of-0024.patch ++++++ Subject: Revert part of r1872 (Fix for CVE-2017-8054 - Detect cycles in PdfPagesTree) Url: https://sourceforge.net/p/podofo/code/1881/ This part had been causing use-after-free in test/unit/podofo-test. --- a/podofo/trunk/src/doc/PdfPagesTree.cpp +++ b/podofo/trunk/src/doc/PdfPagesTree.cpp @@ -479,17 +479,7 @@ if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays - // Recursive call removed to prevent stack overflow, replaced by: - // all the following inside this conditional, plus restart looping - const PdfArray & rVarArray = rVar.GetArray(); - if (rVarArray.GetSize() == 0) - { - PdfError::LogMessage( eLogSeverity_Critical, "Trying to access" - " first page index of empty array" ); - return NULL; - } - rVar = rVarArray[0]; - continue; + return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); } else if( !rVar.IsReference() ) { ++++++ 0027-Correction-for-reverted-part-of-CVE-2017-8054-fix-in-0027.patch ++++++ Subject: Patch by Matthias Brinke: Correction for reverted part of his CVE-2017-5084 fix Url: https://sourceforge.net/p/podofo/code/1882/ The first entry of the array held by rVar is now used for copy-initializing another (stack-allocated, so it'll be freed when no longer needed) PdfVariant whose array is copied in the next line via the PdfVariant assignment operator. This avoids use-after-free in the latter: trying to copy the first array entry after it was freed by PdfVariant::Clear() called in there, found by zyx, thanks. --- a/podofo/trunk/src/doc/PdfPagesTree.cpp +++ b/podofo/trunk/src/doc/PdfPagesTree.cpp @@ -479,7 +479,18 @@ if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays - return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); + // Recursive call removed to prevent stack overflow, replaced by: + // all the following inside this conditional, plus restart looping + const PdfArray & rVarArray = rVar.GetArray(); + if (rVarArray.GetSize() == 0) + { + PdfError::LogMessage( eLogSeverity_Critical, "Trying to access" + " first page index of empty array" ); + return NULL; + } + PdfVariant rVarFirstEntry = rVarArray[0]; // avoids use-after-free + rVar = rVarFirstEntry; // in this line (rVar-ref'd array is freed) + continue; } else if( !rVar.IsReference() ) { ++++++ 0028-Fix-for-CVE-2018-5295-Integer-overflow-at-PdfXRefStreamParserObject-ParseStream.patch ++++++ Subject: Patch by Matthias Brinke: Fix for CVE-2018-5295 - Integer overflow at PdfXRefStreamParserObject::ParseStream() Url: https://sourceforge.net/p/podofo/code/1889/ --- a/podofo/trunk/src/base/PdfXRefStreamParserObject.cpp +++ b/podofo/trunk/src/base/PdfXRefStreamParserObject.cpp @@ -38,7 +38,7 @@ #include "PdfStream.h" #include "PdfVariant.h" -#include <stdio.h> +#include <limits> namespace PoDoFo { @@ -122,12 +122,26 @@ { char* pBuffer; pdf_long lBufferLen; + + for(pdf_int64 nLengthSum = 0, i = 0; i < W_ARRAY_SIZE; i++ ) + { + if ( nW[i] < 0 ) + { + PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, + "Negative field length in XRef stream" ); + } + if ( std::numeric_limits<pdf_int64>::max() - nLengthSum < nW[i] ) + { + PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, + "Invalid entry length in XRef stream" ); + } + else + { + nLengthSum += nW[i]; + } + } + const size_t entryLen = static_cast<size_t>(nW[0] + nW[1] + nW[2]); - - if( nW[0] + nW[1] + nW[2] < 0 ) - { - PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Invalid entry length in XRef stream" ); - } this->GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); ++++++ 0029-Try-to-address-an-eventual-use-after-free-in-PdfObject.patch ++++++ Subject: Try to address an eventual use-after-free in PdfObject::operator=() Url: https://sourceforge.net/p/podofo/code/1890/ Reported by clang: .../src/base/PdfObject.cpp:321:21: warning: Use of memory after it is freed m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) ); ^ ~~~~~~~~~~~~~~~~ .../src/base/PdfObject.cpp:303:30: note: Assuming rhs == *this const PdfObject & PdfObject::operator=( const PdfObject & rhs ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .../src/base/PdfObject.cpp:309:5: note: Memory is released delete m_pStream; ^~~~~~~~~~~~~~~~ .../src/base/PdfObject.cpp:320:5: note: Taking true branch if( rhs.m_pStream ) ^ .../src/base/PdfObject.cpp:321:21: note: Use of memory after it is freed m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) ); ^ ~~~~~~~~~~~~~~~~ 319| 320| if( rhs.m_pStream ) 321|-> m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) ); 322| 323| #if defined(PODOFO_EXTRA_CHECKS) --- a/podofo/trunk/src/base/PdfObject.cpp +++ b/podofo/trunk/src/base/PdfObject.cpp @@ -302,11 +302,15 @@ const PdfObject & PdfObject::operator=( const PdfObject & rhs ) { + if( &rhs == this) + return *this; + // DS: If you change this code, also change the copy constructor. // As the copy constructor is called very often, // it contains a copy of parts of this code to be faster. delete m_pStream; + m_pStream = NULL; const_cast<PdfObject*>(&rhs)->DelayedStreamLoad(); ++++++ 0030-Fix-CVE-2017-6845-Do-not-disable-PODOFO_RAISE_LOGIC_IF-for-Release-builds.patch ++++++ Subject: Do not disable PODOFO_RAISE_LOGIC_IF for Release builds (also fixes CVE-2017-6845) Url: https://sourceforge.net/p/podofo/code/1892/ --- a/podofo/trunk/src/base/PdfError.h +++ b/podofo/trunk/src/base/PdfError.h @@ -169,18 +169,8 @@ * * Evaluate `x' as a binary predicate and if it is true, raise a logic error with the * info string `y' . - * - * This macro will be undefined when NDEBUG is set, so it's compiled out for release - * builds. Use it for expensive or extremely frequent sanity checking. - * - * We define it then UNDEF it to help out doxygen. - */ -#ifndef NDEBUG - // Woo for double-negatives. We define PODOFO_RAISE_LOGIC_IF unless we've been told not to by NDEBUG. - #define PODOFO_RAISE_LOGIC_IF( x, y ) { if (x) throw ::PoDoFo::PdfError( ePdfError_InternalLogic, __FILE__, __LINE__, y ); }; -#else - #define PODOFO_RAISE_LOGIC_IF( x, y ) {}; -#endif + */ +#define PODOFO_RAISE_LOGIC_IF( x, y ) { if (x) throw ::PoDoFo::PdfError( ePdfError_InternalLogic, __FILE__, __LINE__, y ); }; class PODOFO_API PdfErrorInfo { public: ++++++ 0031-Fix-clamping-avoiding-crashes-in-PdfPagesTree-InsertPage.patch ++++++ Subject: Patch by Francesco Pretto: Fix clamping (avoiding crashes) in PdfPagesTree::InsertPage(const PdfRect&, int) Url: https://sourceforge.net/p/podofo/code/1898/ This patch is from the podofo-users mailing list post specified below and fixes a crash when called with int index 0, in PdfPagesTreeCache::AddPageObject(), by array out-of-bounds access. The new clamping allows an index equal to number of pages but will clamp negative input indices to 0 instead of the page count - 1, positive input indices to the page count (meaning "insert after the last page") which avoids the call to the latter method with a negative index (crash cause). Metadata of the patch-source mailing list post: Date: Fri, 23 Feb 2018 19:27:40 +0100 Message-ID: <CALas-igwWbEOr7dW1=t0c6n20y4hnud13sespgavb_0kuj+...@mail.gmail.com> Subject prefix: [PATCH 05/13], further Subject: PdfPagesTree::InsertPage: Fix "atIndex" is really a 0-based index --- a/podofo/trunk/src/doc/PdfPagesTree.cpp +++ b/podofo/trunk/src/doc/PdfPagesTree.cpp @@ -247,11 +247,13 @@ { PdfPage* pPage = new PdfPage( rSize, GetRoot()->GetOwner() ); - if (atIndex < 0 || atIndex >= this->GetTotalNumberOfPages()) { - atIndex = this->GetTotalNumberOfPages() - 1; - } - - InsertPage( atIndex - 1, pPage ); + int pageCount; + if ( atIndex < 0 ) + atIndex = 0; + else if ( atIndex > ( pageCount = this->GetTotalNumberOfPages() ) ) + atIndex = pageCount; + + InsertPage( atIndex - 1, pPage ); m_cache.AddPageObject( atIndex, pPage ); return pPage; ++++++ 0032-Fix-wrong-use-of-memcpy-instead-of-wmemcpy.patch ++++++ Subject: Patch by Francesco Pretto: PdfMemDocument::Load: Fix wrong use of memcpy instead of wmemcpy Url: https://sourceforge.net/p/podofo/code/1903/ --- a/podofo/trunk/src/doc/PdfMemDocument.cpp +++ b/podofo/trunk/src/doc/PdfMemDocument.cpp @@ -271,7 +271,7 @@ { int lLen = wcslen( pszFilename ); m_wchar_pszUpdatingFilename = static_cast<wchar_t *>( podofo_malloc( sizeof( wchar_t ) * ( lLen + 1 ) ) ); - memcpy( m_wchar_pszUpdatingFilename, pszFilename, lLen ); + wmemcpy( m_wchar_pszUpdatingFilename, pszFilename, lLen ); m_wchar_pszUpdatingFilename[lLen] = L'\0'; } ++++++ 0033-Fix-for-CVE-2018-5309-integer-overflow-in-the-PdfObjectStreamParserObject-ReadObjectsFromStream.patch ++++++ Subject: Fix for CVE-2018-5309 - integer overflow in the PdfObjectStreamParserObject::ReadObjectsFromStream Url: https://sourceforge.net/p/podofo/code/1907/ --- a/podofo/trunk/src/base/PdfObjectStreamParserObject.cpp +++ b/podofo/trunk/src/base/PdfObjectStreamParserObject.cpp @@ -95,6 +95,12 @@ const pdf_int64 lOff = tokenizer.GetNextNumber(); const std::streamoff pos = device.Device()->Tell(); + if( lFirst >= std::numeric_limits<pdf_int64>::max() - lOff ) + { + PODOFO_RAISE_ERROR_INFO( ePdfError_BrokenFile, + "Object position out of max limit" ); + } + // move to the position of the object in the stream device.Device()->Seek( static_cast<std::streamoff>(lFirst + lOff) ); ++++++ 0034-Fix-for-CVE-2018-8001-heap-based-buffer-over-read-in-UnescapeName.patch ++++++ Subject: Fix for CVE-2018-8001 - heap-based buffer over-read in UnescapeName() Url: https://sourceforge.net/p/podofo/code/1909/ --- a/podofo/trunk/src/base/PdfName.cpp +++ b/podofo/trunk/src/base/PdfName.cpp @@ -134,7 +134,7 @@ unsigned int incount = 0, outcount = 0; while (incount++ < length) { - if (*it == '#') + if (*it == '#' && incount + 1 < length) { unsigned char hi = static_cast<unsigned char>(*(++it)); ++incount; unsigned char low = static_cast<unsigned char>(*(++it)); ++incount; ++++++ fix-missing-include.patch ++++++ Subject: Add missing #include <limits> to fix build From: Antonio Larrosa <alarr...@suse.com> Index: a/podofo/trunk/src/base/PdfObjectStreamParserObject.cpp =================================================================== --- a/podofo/trunk/src/base/PdfObjectStreamParserObject.cpp +++ b/podofo/trunk/src/base/PdfObjectStreamParserObject.cpp @@ -41,6 +41,7 @@ #include "PdfVecObjects.h" #include <algorithm> +#include <limits> #if defined(PODOFO_VERBOSE_DEBUG) #include <iostream>