Hello community,
here is the log from the commit of package podofo for openSUSE:Factory checked in at 2019-02-25 18:01:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/podofo (Old)
and /work/SRC/openSUSE:Factory/.podofo.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "podofo"
Mon Feb 25 18:01:00 2019 rev:29 rq:678906 version:0.9.6
Changes:
--------
--- /work/SRC/openSUSE:Factory/podofo/podofo.changes 2018-10-17 08:42:49.505783305 +0200
+++ /work/SRC/openSUSE:Factory/.podofo.new.28833/podofo.changes 2019-02-25 18:01:00.594099460 +0100
@@ -1,0 +2,53 @@
+Wed Feb 20 16:47:32 UTC 2019 - Antonio Larrosa
+
+- Add patches from upstream to fix several CVEs:
+
+ * r1933-Really-fix-CVE-2017-7381.patch
+ to fix a null pointer dereference (bsc#1032020, CVE-2017-7381)
+
+ * r1936-Really-fix-CVE-2017-7382.patch
+ to fix a null pointer dereference (bsc#1032021, CVE-2017-7382)
+
+ * r1937-Really-fix-CVE-2017-7383.patch
+ to fix a null pointer dereference (bsc#1032022, CVE-2017-7383)
+
+ * r1938-Fix-CVE-2018-11256-PdfError-info-gives-not-found-page-0-based.patch
+ to fix a null pointer dereference Denial of Service
+ (bsc#1096889, CVE-2018-11256)
+
+ * r1941-Fix-CVE-2017-8054-and-other-issues-keeping-binary-compat.patch
+ This patch was rebased from the one upstream so that it applies correctly
+ and modified so it doesn't break binary compatibility.
+ (CVE-2017-8054, boo#1035596)
+
+ * r1945-Fix-possible-incompatibility-of-PdfAESStream-with-OpenSSL-1.1.0g.patch
+
+ * r1948-Fix-CVE-2018-12982-implementing-inline-PdfDictionary-MustGetKey.patch
+ This patch was rebased from the one upstream so that it applies correctly.
+ (CVE-2018-12982, boo#1099720)
+
+ * r1949-Fix-CVE-2018-5783-by-introducing-singleton-limit-for-indirect-objects-keeping-binary-compat.patch
+ This patch was rebased from the one upstream so that it applies correctly
+ and modified so it doesn't break binary compatibility.
+ (CVE-2018-5783, boo#1076962)
+
+ * r1950-Fix-null-pointer-dereference-in-PdfTranslator-setTarget.patch
+
+ * r1952-Fix-CVE-2018-11255-Null-pointer-dereference-in-PdfPage-GetPageNumber.patch
+ (CVE-2018-11255, boo#1096890)
+
+ * r1953-Fix-CVE-2018-14320-Possible-undefined-behaviour-in-PdfEncoding-ParseToUnicode.patch
+ (CVE-2018-14320, boo#1108764)
+
+ * r1954-Fix-CVE-2018-20751-null-pointer-dereference-in-crop_page-of-tools-podofocrop.patch
+ (CVE-2018-20751, boo#1124357)
+
+ * r1961-EncryptTest-Fix-buffer-overflow-in-decrypted-out-buffer-in-TestEncrypt.patch
+ This patch was rebased from the one upstream so that it applies correctly.
+
+ * r1963-Fix-heap-based-buffer-overflow-vulnerability-in-PoDoFo-PdfVariant-DelayedLoad.patch
+
+- Renamed fix-build.patch to r1942-Fix-build-with-cmake-ge-3.12.patch to
+ keep its name consistent with the other upstream patches.
+
+-------------------------------------------------------------------
Old:
----
fix-build.patch
New:
----
r1933-Really-fix-CVE-2017-7381.patch
r1936-Really-fix-CVE-2017-7382.patch
r1937-Really-fix-CVE-2017-7383.patch
r1938-Fix-CVE-2018-11256-PdfError-info-gives-not-found-page-0-based.patch
r1941-Fix-CVE-2017-8054-and-other-issues-keeping-binary-compat.patch
r1942-Fix-build-with-cmake-ge-3.12.patch
r1945-Fix-possible-incompatibility-of-PdfAESStream-with-OpenSSL-1.1.0g.patch
r1948-Fix-CVE-2018-12982-implementing-inline-PdfDictionary-MustGetKey.patch
r1949-Fix-CVE-2018-5783-by-introducing-singleton-limit-for-indirect-objects-keeping-binary-compat.patch
r1950-Fix-null-pointer-dereference-in-PdfTranslator-setTarget.patch
r1952-Fix-CVE-2018-11255-Null-pointer-dereference-in-PdfPage-GetPageNumber.patch
r1953-Fix-CVE-2018-14320-Possible-undefined-behaviour-in-PdfEncoding-ParseToUnicode.patch
r1954-Fix-CVE-2018-20751-null-pointer-dereference-in-crop_page-of-tools-podofocrop.patch
r1961-EncryptTest-Fix-buffer-overflow-in-decrypted-out-buffer-in-TestEncrypt.patch
r1963-Fix-heap-based-buffer-overflow-vulnerability-in-PoDoFo-PdfVariant-DelayedLoad.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ podofo.spec ++++++
--- /var/tmp/diff_new_pack.90j4vE/_old 2019-02-25 18:01:02.042098335 +0100
+++ /var/tmp/diff_new_pack.90j4vE/_new 2019-02-25 18:01:02.046098331 +0100
@@ -1,7 +1,7 @@
#
# spec file for package podofo
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 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
@@ -25,8 +25,36 @@
Group: Productivity/Publishing/PDF
URL: http://podofo.sourceforge.net/
Source0: http://downloads.sourceforge.net/podofo/%{name}-%{version}.tar.gz
-# PATCH-FIX-UPSTREAM fix-build.patch
-Patch0: fix-build.patch
+# PATCH-FIX-UPSTREAM
+Patch0: r1933-Really-fix-CVE-2017-7381.patch
+# PATCH-FIX-UPSTREAM
+Patch1: r1936-Really-fix-CVE-2017-7382.patch
+# PATCH-FIX-UPSTREAM
+Patch2: r1937-Really-fix-CVE-2017-7383.patch
+# PATCH-FIX-UPSTREAM
+Patch3: r1938-Fix-CVE-2018-11256-PdfError-info-gives-not-found-page-0-based.patch
+# PATCH-FIX-UPSTREAM
+Patch4: r1941-Fix-CVE-2017-8054-and-other-issues-keeping-binary-compat.patch
+# PATCH-FIX-UPSTREAM
+Patch5: r1942-Fix-build-with-cmake-ge-3.12.patch
+# PATCH-FIX-UPSTREAM
+Patch6: r1945-Fix-possible-incompatibility-of-PdfAESStream-with-OpenSSL-1.1.0g.patch
+# PATCH-FIX-UPSTREAM
+Patch7: r1948-Fix-CVE-2018-12982-implementing-inline-PdfDictionary-MustGetKey.patch
+# PATCH-FIX-UPSTREAM
+Patch8: r1949-Fix-CVE-2018-5783-by-introducing-singleton-limit-for-indirect-objects-keeping-binary-compat.patch
+# PATCH-FIX-UPSTREAM
+Patch9: r1950-Fix-null-pointer-dereference-in-PdfTranslator-setTarget.patch
+# PATCH-FIX-UPSTREAM
+Patch10: r1952-Fix-CVE-2018-11255-Null-pointer-dereference-in-PdfPage-GetPageNumber.patch
+# PATCH-FIX-UPSTREAM
+Patch11: r1953-Fix-CVE-2018-14320-Possible-undefined-behaviour-in-PdfEncoding-ParseToUnicode.patch
+# PATCH-FIX-UPSTREAM
+Patch12: r1954-Fix-CVE-2018-20751-null-pointer-dereference-in-crop_page-of-tools-podofocrop.patch
+# PATCH-FIX-UPSTREAM
+Patch13: r1961-EncryptTest-Fix-buffer-overflow-in-decrypted-out-buffer-in-TestEncrypt.patch
+# PATCH-FIX-UPSTREAM
+Patch14: r1963-Fix-heap-based-buffer-overflow-vulnerability-in-PoDoFo-PdfVariant-DelayedLoad.patch
BuildRequires: cmake >= 2.5
BuildRequires: doxygen
BuildRequires: fdupes
@@ -65,7 +93,7 @@
%prep
%setup -q
-%patch0 -p0
+%autopatch -p0
# Remove build time references so build-compare can do its work
echo "HTML_TIMESTAMP = NO" >> Doxyfile
++++++ r1933-Really-fix-CVE-2017-7381.patch ++++++
------------------------------------------------------------------------
r1933 | mabri | 2018-07-16 02:34:38 +0200 (lun 16 de jul de 2018) | 2 líneas
Really fix CVE-2017-7381
Index: src/doc/PdfPage.cpp
===================================================================
--- src/doc/PdfPage.cpp (revisión: 1932)
+++ src/doc/PdfPage.cpp (revisión: 1933)
@@ -673,6 +673,10 @@
PdfObject* PdfPage::GetFromResources( const PdfName & rType, const PdfName & rKey )
{
+ if( m_pResources == NULL ) // Fix CVE-2017-7381
+ {
+ PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "No Resources" );
+ }
if( m_pResources->GetDictionary().HasKey( rType ) )
{
// OC 15.08.2010 BugFix: Ghostscript creates here sometimes an indirect reference to a directory
------------------------------------------------------------------------
++++++ r1936-Really-fix-CVE-2017-7382.patch ++++++
------------------------------------------------------------------------
r1936 | mabri | 2018-08-24 23:40:46 +0200 (vie 24 de ago de 2018) | 1 línea
Really fix CVE-2017-7382
Index: src/doc/PdfFontFactory.cpp
===================================================================
--- src/doc/PdfFontFactory.cpp (revisión: 1935)
+++ src/doc/PdfFontFactory.cpp (revisión: 1936)
@@ -197,7 +197,13 @@
PODOFO_RAISE_ERROR( ePdfError_InvalidDataType );
}
- const PdfName & rSubType = pObject->GetDictionary().GetKey( PdfName::KeySubtype )->GetName();
+ PdfVariant* pSubTypeKey = pObject->GetDictionary()
+ .GetKey( PdfName::KeySubtype );
+ if ( NULL == pSubTypeKey )
+ {
+ PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Font: No SubType" );
+ }
+ const PdfName & rSubType = pSubTypeKey->GetName();
if( rSubType == PdfName("Type0") )
{
// The PDF reference states that DescendantFonts must be an array,
------------------------------------------------------------------------
++++++ r1937-Really-fix-CVE-2017-7383.patch ++++++
------------------------------------------------------------------------
r1937 | mabri | 2018-08-25 00:07:55 +0200 (sáb 25 de ago de 2018) | 1 línea
Really fix CVE-2017-7383
Index: src/doc/PdfFontFactory.cpp
===================================================================
--- src/doc/PdfFontFactory.cpp (revisión: 1936)
+++ src/doc/PdfFontFactory.cpp (revisión: 1937)
@@ -192,8 +192,14 @@
PdfObject* pDescriptor = NULL;
PdfObject* pEncoding = NULL;
- if( pObject->GetDictionary().GetKey( PdfName::KeyType )->GetName() != PdfName("Font") )
+ PdfVariant* pTypeKey = pObject->GetDictionary().GetKey( PdfName::KeyType );
+ if ( NULL == pTypeKey )
{
+ PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Font: No Type" );
+ }
+
+ if( pTypeKey->GetName() != PdfName("Font") )
+ {
PODOFO_RAISE_ERROR( ePdfError_InvalidDataType );
}
------------------------------------------------------------------------
++++++ r1938-Fix-CVE-2018-11256-PdfError-info-gives-not-found-page-0-based.patch ++++++
------------------------------------------------------------------------
r1938 | mabri | 2018-08-28 22:36:23 +0200 (mar 28 de ago de 2018) | 1 línea
Fix CVE-2018-11256: PdfError info gives not-found page 0-based (and says that)
Index: src/doc/PdfDocument.cpp
===================================================================
--- src/doc/PdfDocument.cpp (revisión: 1937)
+++ src/doc/PdfDocument.cpp (revisión: 1938)
@@ -325,6 +325,12 @@
for(int i=0;iGetObject()->Reference().ObjectNumber() + difference, pPage->GetObject()->Reference().GenerationNumber() ) );
if( pObj->IsDictionary() && pObj->GetDictionary().HasKey( "Parent" ) )
pObj->GetDictionary().RemoveKey( "Parent" );
------------------------------------------------------------------------
++++++ r1941-Fix-CVE-2017-8054-and-other-issues-keeping-binary-compat.patch ++++++
------------------------------------------------------------------------
r1941 | mc-zyx | 2018-09-30 16:56:19 +0200 (dom 30 de sep de 2018) | 10 líneas
Patch by Amin Massad: Fix bugs in PdfPagesTree::GetPageNode() / PdfPagesTree::GetPageNodeFromArray()
The patch includes:
1) A real fix of CVE-2017-8054 (not really fixed upto r1937!) for handling
of cyclic trees, see testCyclicTree()
2) A fix for handling of subtrees with „/Kids []“ and „/Count 0“ which is
completely valid according to the PDF spec, see testEmptyKidsTree()
3) A changed behavior for trees with nested kids array which are not valid
according to the PDF spec and now yield an NULL ptr, see testNestedArrayTree()
Modified by Antonio Larrosa so the patch
doesn't break binary compatibility
Index: src/doc/PdfPagesTree.cpp
===================================================================
--- src/doc/PdfPagesTree.cpp (revisión: 1940)
+++ src/doc/PdfPagesTree.cpp (revisión: 1941)
@@ -335,7 +335,6 @@
const PdfArray & rKidsArray = pObj->GetArray();
PdfArray::const_iterator it = rKidsArray.begin();
- const size_t numDirectKids = rKidsArray.size();
const size_t numKids = GetChildCount(pParent);
// use <= since nPageNum is 0-based
@@ -347,62 +346,25 @@
return NULL;
}
- //printf("Fetching: %i %i %i\n", numDirectKids, numKids, nPageNum );
- if( numDirectKids == numKids && static_cast(nPageNum) < numDirectKids )
+ //printf("Fetching: %i %i\n", numKids, nPageNum );
+
+ // We have to traverse the tree
+ //
+ // BEWARE: There is no valid shortcut for tree traversal.
+ // Even if eKidsArray.size()==numKids, this does not imply that
+ // eKidsArray can be accessed with the index of the page directly.
+ // The tree could have an arbitrary complex structure because
+ // internal nodes with no leaves (page objects) are not forbidden
+ // by the PDF spec.
+ while( it != rKidsArray.end() )
{
- // This node has only page nodes as kids,
- // so we can access the array directly
- rLstParents.push_back( pParent );
- return GetPageNodeFromArray( nPageNum, rKidsArray, rLstParents );
- }
- else
- {
- // We have to traverse the tree
- while( it != rKidsArray.end() )
+ if(!(*it).IsReference() )
{
- if( (*it).IsArray() )
- { // Fixes PDFs broken by having trees with arrays nested once
-
- rLstParents.push_back( pParent );
+ PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Invalid datatype in kids array: %s\n",
+ nPageNum, (*it).GetDataTypeString());
+ return NULL;
+ }
- // the following code is to find the reference to log this with
- const PdfReference & rIterArrayRef = (*it).Reference();
- PdfReference refToLog;
- bool isDirectObject // don't worry about 0-num. indirect ones
- = ( !(rIterArrayRef.ObjectNumber() ) );
- if ( isDirectObject )
- {
- if ( !(pObj->Reference().ObjectNumber() ) ) // rKidsArray's
- {
- refToLog = pParent->Reference();
- }
- else
- {
- refToLog = pObj->Reference();
- }
- }
- else
- {
- refToLog = rIterArrayRef;
- }
- PdfError::LogMessage( eLogSeverity_Error,
- "Entry in Kids array is itself an array"
- "%s reference: %s\n", isDirectObject ? " (direct object)"
- ", in object with" : ",", refToLog.ToString().c_str() );
-
- const PdfArray & rIterArray = (*it).GetArray();
-
- // is the array large enough to potentially have the page?
- if( static_cast(nPageNum) < rIterArray.GetSize() )
- {
- PdfObject* pPageNode = GetPageNodeFromArray( nPageNum,
- rIterArray, rLstParents );
- if ( pPageNode ) // and if not, search further
- return pPageNode;
- }
- }
- else if( (*it).IsReference() )
- {
PdfObject* pChild = GetRoot()->GetOwner()->GetObject( (*it).GetReference() );
if (!pChild)
{
@@ -416,13 +378,28 @@
int childCount = GetChildCount( pChild );
if( childCount < nPageNum + 1 ) // Pages are 0 based, but count is not
{
- // skip this page node
- // and go to the next one
+ // skip this page tree node
+ // and go to the next child in rKidsArray
nPageNum -= childCount;
}
else
{
+ // page is in the subtree of pChild
+ // => call GetPageNode() recursively
+
rLstParents.push_back( pParent );
+
+ if ( std::find( rLstParents.begin(), rLstParents.end(), pChild )
+ != rLstParents.end() ) // cycle in parent list detected, fend
+ { // off security vulnerability similar to 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 " << pChild->Reference()
+ .ToString() << " one of whose descendants the former is.";
+ PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, oss.str() );
+ }
+
return this->GetPageNode( nPageNum, pChild, rLstParents );
}
}
@@ -430,6 +407,7 @@
{
if( 0 == nPageNum )
{
+ // page found
rLstParents.push_back( pParent );
return pChild;
}
@@ -448,24 +426,18 @@
"Invalid datatype referenced in kids array: %s\n"
"Reference to invalid object: %i %i R\n", nPageNum,
pChild->GetDataTypeString(), nLogObjNum, nLogGenNum);
+ return NULL;
}
- }
- else
- {
- PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Invalid datatype in kids array: %s\n",
- nPageNum, (*it).GetDataTypeString());
- return NULL;
- }
++it;
}
- }
return NULL;
}
PdfObject* PdfPagesTree::GetPageNodeFromArray( int nPageNum, const PdfArray & rKidsArray, PdfObjectList & rLstParents )
{
+ PdfError::LogMessage( eLogSeverity_Warning, "PdfPagesTree::GetPageNodeFromArray is deprecated and will be removed soon");
if( static_cast(nPageNum) >= rKidsArray.GetSize() )
{
PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i from array of size %i\n",
Index: test/unit/PagesTreeTest.cpp
===================================================================
--- test/unit/PagesTreeTest.cpp (revisión: 1940)
+++ test/unit/PagesTreeTest.cpp (revisión: 1941)
@@ -22,6 +22,8 @@
#include
+#include <sstream>
+
#define PODOFO_TEST_PAGE_KEY "PoDoFoTestPageNumber"
#define PODOFO_TEST_NUM_PAGES 100
@@ -70,6 +72,58 @@
CPPUNIT_ASSERT_THROW( writer.GetPage( 1 ), PdfError );
}
+void PagesTreeTest::testCyclicTree()
+{
+ for (int pass=0; pass < 2; pass++)
+ {
+ PdfMemDocument doc;
+ CreateCyclicTree( doc, pass==1);
+ //doc.Write(pass==0?"tree_valid.pdf":"tree_cyclic.pdf");
+ for (int pagenum=0; pagenum < doc.GetPageCount(); pagenum++)
+ {
+ if (pass==0)
+ {
+ // pass 0:
+ // valid tree without cycles should yield all pages
+ PdfPage* pPage = doc.GetPage( pagenum );
+ CPPUNIT_ASSERT_EQUAL( pPage != NULL, true );
+ CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, pagenum ), true );
+ }
+ else
+ {
+ // pass 1:
+ // cyclic tree must throw exception to prevent infinite recursion
+ CPPUNIT_ASSERT_THROW( doc.GetPage( pagenum ), PdfError );
+ }
+ }
+ }
+}
+
+void PagesTreeTest::testEmptyKidsTree()
+{
+ PdfMemDocument doc;
+ CreateEmptyKidsTree(doc);
+ //doc.Write("tree_zerokids.pdf");
+ for (int pagenum=0; pagenum < doc.GetPageCount(); pagenum++)
+ {
+ PdfPage* pPage = doc.GetPage( pagenum );
+ CPPUNIT_ASSERT_EQUAL( pPage != NULL, true );
+ CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, pagenum ), true );
+ }
+}
+
+void PagesTreeTest::testNestedArrayTree()
+{
+ PdfMemDocument doc;
+ CreateNestedArrayTree(doc);
+ //doc.Write("tree_nested_array.pdf");
+ for (int pagenum=0; pagenum < doc.GetPageCount(); pagenum++)
+ {
+ PdfPage* pPage = doc.GetPage( pagenum );
+ CPPUNIT_ASSERT_EQUAL( pPage == NULL, true );
+ }
+}
+
void PagesTreeTest::testCreateDelete()
{
PdfMemDocument writer;
@@ -354,7 +408,153 @@
pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast(PODOFO_TEST_NUM_PAGES) );
}
+std::vector PagesTreeTest::CreateSamplePages( PdfMemDocument & rDoc,
+ int nPageCount)
+{
+ PdfFont* pFont;
+ // create font
+ pFont = rDoc.CreateFont( "Arial" );
+ if( !pFont )
+ {
+ PODOFO_RAISE_ERROR( ePdfError_InvalidHandle );
+ }
+ pFont->SetFontSize( 16.0 );
+
+ std::vector pPage(nPageCount);
+ for (int i = 0; i < nPageCount; ++i)
+ {
+ pPage[i] = new PdfPage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ),
+ &(rDoc.GetObjects()) );
+ pPage[i]->GetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY,
+ static_cast(i) );
+
+ PdfPainter painter;
+ painter.SetPage( pPage[i] );
+ painter.SetFont( pFont );
+ std::ostringstream os;
+ os << "Page " << i+1;
+ painter.DrawText( 200, 200, os.str() );
+ painter.FinishPage();
+ }
+
+ return pPage;
+}
+
+std::vector PagesTreeTest::CreateNodes( PdfMemDocument & rDoc,
+ int nNodeCount)
+{
+ std::vector pNode(nNodeCount);
+
+ for (int i = 0; i < nNodeCount; ++i)
+ {
+ pNode[i]=rDoc.GetObjects().CreateObject("Pages");
+ // init required keys
+ pNode[i]->GetDictionary().AddKey( "Kids", PdfArray());
+ pNode[i]->GetDictionary().AddKey( "Count", PdfVariant(static_cast(0L)));
+ }
+
+ return pNode;
+}
+
+void PagesTreeTest::CreateCyclicTree( PoDoFo::PdfMemDocument & rDoc,
+ bool bCreateCycle )
+{
+ const int COUNT = 3;
+
+ std::vector pPage=CreateSamplePages( rDoc, COUNT );
+ std::vector pNode=CreateNodes( rDoc, 2 );
+
+ // manually insert pages into pagetree
+ PdfObject* pRoot = rDoc.GetPagesTree()->GetObject();
+
+ // tree layout (for !bCreateCycle):
+ //
+ // root
+ // +-- node0
+ // +-- node1
+ // | +-- page0
+ // | +-- page1
+ // \-- page2
+
+ // root node
+ AppendChildNode(pRoot, pNode[0]);
+
+ // tree node 0
+ AppendChildNode(pNode[0], pNode[1]);
+ AppendChildNode(pNode[0], pPage[2]->GetObject());
+
+ // tree node 1
+ AppendChildNode(pNode[1], pPage[0]->GetObject());
+ AppendChildNode(pNode[1], pPage[1]->GetObject());
+
+ if (bCreateCycle)
+ {
+ // invalid tree: Cycle!!!
+ // was not detected in PdfPagesTree::GetPageNode() rev. 1937
+ pNode[0]->GetIndirectKey("Kids")->GetArray()[0]=pRoot->Reference();
+ }
+}
+
+void PagesTreeTest::CreateEmptyKidsTree( PoDoFo::PdfMemDocument & rDoc )
+{
+ const int COUNT = 3;
+
+ std::vector pPage=CreateSamplePages( rDoc, COUNT );
+ std::vector pNode=CreateNodes( rDoc, 3 );
+
+ // manually insert pages into pagetree
+ PdfObject* pRoot = rDoc.GetPagesTree()->GetObject();
+
+ // tree layout:
+ //
+ // root
+ // +-- node0
+ // | +-- page0
+ // | +-- page1
+ // | +-- page2
+ // +-- node1
+ // \-- node2
+
+ // root node
+ AppendChildNode(pRoot, pNode[0]);
+ AppendChildNode(pRoot, pNode[1]);
+ AppendChildNode(pRoot, pNode[2]);
+
+ // tree node 0
+ AppendChildNode(pNode[0], pPage[0]->GetObject());
+ AppendChildNode(pNode[0], pPage[1]->GetObject());
+ AppendChildNode(pNode[0], pPage[2]->GetObject());
+
+ // tree node 1 and node 2 are left empty: this is completely valid
+ // according to the PDF spec, i.e. the required keys may have the
+ // values "/Kids [ ]" and "/Count 0"
+}
+
+void PagesTreeTest::CreateNestedArrayTree( PoDoFo::PdfMemDocument & rDoc )
+{
+ const int COUNT = 3;
+
+ std::vector pPage=CreateSamplePages( rDoc, COUNT );
+ PdfObject* pRoot = rDoc.GetPagesTree()->GetObject();
+
+ // create kids array
+ PdfArray kids;
+ for (int i=0; i < COUNT; i++)
+ {
+ kids.push_back( pPage[i]->GetObject()->Reference() );
+ pPage[i]->GetObject()->GetDictionary().AddKey( PdfName("Parent"), pRoot->Reference());
+ }
+
+ // create nested kids array
+ PdfArray nested;
+ nested.push_back(kids);
+
+ // manually insert pages into pagetree
+ pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast(COUNT) );
+ pRoot->GetDictionary().AddKey( PdfName("Kids"), nested);
+}
+
bool PagesTreeTest::IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber )
{
pdf_int64 lPageNumber = pPage->GetObject()->GetDictionary().GetKeyAsLong( PODOFO_TEST_PAGE_KEY, -1 );
@@ -367,3 +567,33 @@
else
return true;
}
+
+void PagesTreeTest::AppendChildNode(PdfObject* pParent, PdfObject* pChild)
+{
+ // 1. Add the reference of the new child to the kids array of pParent
+ PdfArray kids;
+ PdfObject* oldKids=pParent->GetIndirectKey("Kids");
+ if (oldKids && oldKids->IsArray()) kids=oldKids->GetArray();
+ kids.push_back(pChild->Reference());
+ pParent->GetDictionary().AddKey( PdfName("Kids"), kids);
+
+ // 2. If the child is a page (leaf node), increase count of every parent
+ // (which also includes pParent)
+ if( pChild->GetDictionary().GetKeyAsName( PdfName( "Type" ) )
+ == PdfName( "Page" ) )
+ {
+ PdfObject* node=pParent;
+ while (node)
+ {
+ pdf_int64 count=0;
+ if (node->GetIndirectKey("Count")) count=node->GetIndirectKey("Count")->GetNumber();
+ count++;
+ node->GetDictionary().AddKey( PdfName("Count"), count);
+
+ node=node->GetIndirectKey("Parent");
+ }
+ }
+
+ // 3. Add Parent key to the child
+ pChild->GetDictionary().AddKey( PdfName("Parent"), pParent->Reference());
+}
Index: test/unit/PagesTreeTest.h
===================================================================
--- test/unit/PagesTreeTest.h (revisión: 1940)
+++ test/unit/PagesTreeTest.h (revisión: 1941)
@@ -21,11 +21,14 @@
#ifndef _PAGES_TREE_TEST_H_
#define _PAGES_TREE_TEST_H_
+#include <vector>
+
#include
namespace PoDoFo {
class PdfMemDocument;
class PdfPage;
+class PdfObject;
};
/** This test tests the class PdfPagesTree
@@ -35,6 +38,9 @@
CPPUNIT_TEST_SUITE( PagesTreeTest );
CPPUNIT_TEST( testEmptyTree );
CPPUNIT_TEST( testEmptyDoc );
+ CPPUNIT_TEST( testCyclicTree );
+ CPPUNIT_TEST( testEmptyKidsTree );
+ CPPUNIT_TEST( testNestedArrayTree );
CPPUNIT_TEST( testCreateDelete );
CPPUNIT_TEST( testGetPagesCustom );
CPPUNIT_TEST( testGetPagesPoDoFo );
@@ -52,6 +58,9 @@
void testEmptyTree();
void testEmptyDoc();
+ void testCyclicTree();
+ void testEmptyKidsTree();
+ void testNestedArrayTree();
void testCreateDelete();
void testGetPagesCustom();
void testGetPagesPoDoFo();
@@ -98,7 +107,58 @@
*/
void CreateTestTreeCustom( PoDoFo::PdfMemDocument & rDoc );
+ /**
+ * Create a pages tree with cycles to test prevention of endless
+ * recursion as mentioned in different CVE reports.
+ *
+ * \param bCreateCycle if true a cyclic tree is created, otherwise a
+ * valid tree without cycles
+ */
+ void CreateCyclicTree( PoDoFo::PdfMemDocument & rDoc,
+ bool bCreateCycle );
+
+ /**
+ * Create a pages tree with nodes containing empty kids.
+ *
+ * This is completely valid according to the PDF spec, i.e. the
+ * required keys may have the values "/Kids [ ]" and "/Count 0"
+ * Such a tree must still be parsable by a conforming reader:
+ *
+ * <BLOCKQUOTE>The tree contains nodes of two types—intermediate
+ * nodes, called page tree nodes, and leaf nodes, called page
+ * objects—whose form is described in the subsequent subclauses.
+ * Conforming products shall be prepared to handle any form
+ * of tree structure built of such nodes.</BLOCKQUOTE>
+ */
+ void CreateEmptyKidsTree( PoDoFo::PdfMemDocument & rDoc );
+
+ /**
+ * Ceate a pages tree with a nested kids array.
+ *
+ * Such a tree is not valid to the PDF spec, which requires they key
+ * "Kids" to be an array of indirect references. And the children shall
+ * only be page objects or other page tree nodes.
+ */
+ void CreateNestedArrayTree( PoDoFo::PdfMemDocument & rDoc );
+
+ /**
+ * Create page object nodes (leaf nodes),
+ * where every page object has an additional
+ * key PoDoFoTestPageNumber with the original
+ * page number of the page.
+ */
+ std::vectorPoDoFo::PdfPage* CreateSamplePages( PoDoFo::PdfMemDocument & rDoc,
+ int nPageCount);
+
+ /**
+ * Create page tree nodes (internal nodes)
+ */
+ std::vectorPoDoFo::PdfObject* CreateNodes( PoDoFo::PdfMemDocument & rDoc,
+ int nNodeCount);
+
bool IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber );
+
+ void AppendChildNode(PoDoFo::PdfObject* pParent, PoDoFo::PdfObject* pChild);
};
#endif // _PAGES_TREE_TEST_H_
------------------------------------------------------------------------
++++++ r1942-Fix-build-with-cmake-ge-3.12.patch ++++++
------------------------------------------------------------------------
r1942 | mc-zyx | 2018-09-30 18:16:47 +0200 (dim., 30 sept. 2018) | 4 lines
Patch by heirecka: Fix build with cmake >= 3.12
Closes https://sourceforge.net/p/podofo/tickets/24/
Index: test/TokenizerTest/CMakeLists.txt
===================================================================
--- test/TokenizerTest/CMakeLists.txt (revision 1941)
+++ test/TokenizerTest/CMakeLists.txt (revision 1942)
@@ -2,10 +2,3 @@
TARGET_LINK_LIBRARIES(TokenizerTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS})
SET_TARGET_PROPERTIES(TokenizerTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}")
ADD_DEPENDENCIES(TokenizerTest ${PODOFO_DEPEND_TARGET})
-
-# Copy the test samples over to the build tree
-ADD_CUSTOM_COMMAND(
- TARGET TokenizerTest
- POST_BUILD
- COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/objects" "${CMAKE_CURRENT_BINARY_DIR}/objects"
- )
------------------------------------------------------------------------
++++++ r1945-Fix-possible-incompatibility-of-PdfAESStream-with-OpenSSL-1.1.0g.patch ++++++
------------------------------------------------------------------------
r1945 | mc-zyx | 2018-10-27 15:46:04 +0200 (sáb 27 de oct de 2018) | 2 líneas
Patch by Francesco Pretto: Fix possible incompatibility of PdfAESStream with OpenSSL 1.1.0g
Index: src/base/PdfEncrypt.cpp
===================================================================
--- src/base/PdfEncrypt.cpp (revisión: 1944)
+++ src/base/PdfEncrypt.cpp (revisión: 1945)
@@ -32,6 +32,7 @@
#include
#include
#include <sstream>
+#include <vector>
#ifdef PODOFO_HAVE_OPENSSL
// SHA-256
@@ -384,8 +385,8 @@
EVP_CIPHER_CTX* aes = m_aes->getEngine();
int lOutLen = 0, lStepOutLen;
int status = 1;
+ int bufferOffset = 0;
if( bFirstRead ) {
- bFirstRead = false;
if( keyLen == PdfEncrypt::ePdfKeyLength_128/8 ) {
status = EVP_DecryptInit_ex( aes, EVP_aes_128_cbc(), NULL, key, pBuffer );
#ifdef PODOFO_HAVE_LIBIDN
@@ -397,15 +398,18 @@
}
if(status != 1)
PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" );
- status = EVP_DecryptUpdate( aes, pBuffer, &lOutLen, pBuffer + AES_IV_LENGTH, lLen - AES_IV_LENGTH );
- } else if( !bOnlyFinalLeft ) {
+
+ bufferOffset = AES_IV_LENGTH;
+ bFirstRead = false;
+ }
+
+ if( !bOnlyFinalLeft ) {
// Quote openssl.org: "the decrypted data buffer out passed to EVP_DecryptUpdate() should have sufficient room
// for (inl + cipher_block_size) bytes unless the cipher block size is 1 in which case inl bytes is sufficient."
// So we need to create a buffer that is bigger than lLen.
- unsigned char* tempBuffer = new unsigned char[lLen + 16];
- status = EVP_DecryptUpdate( aes, tempBuffer, &lOutLen, pBuffer, lLen );
- memcpy( pBuffer, tempBuffer, lOutLen );
- delete[] tempBuffer;
+ tempBuffer.resize( lLen + 16 );
+ status = EVP_DecryptUpdate( aes, &tempBuffer[0], &lOutLen, pBuffer + bufferOffset, lLen - bufferOffset );
+ memcpy( pBuffer, &tempBuffer[0], lOutLen );
}
if( status != 1 )
PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data" );
@@ -427,6 +431,7 @@
}
private:
+ std::vector<unsigned char> tempBuffer;
unsigned char key[32];
const size_t keyLen;
bool bFirstRead;
------------------------------------------------------------------------
++++++ r1948-Fix-CVE-2018-12982-implementing-inline-PdfDictionary-MustGetKey.patch ++++++
------------------------------------------------------------------------
r1948 | mabri | 2018-11-10 23:44:43 +0100 (sáb 10 de nov de 2018) | 9 líneas
Fix CVE-2018-12982 implementing inline PdfDictionary::MustGetKey()
That new method throws, therefore it makes NULL checks in the
calling places unnecessary. That it's inline means that it doesn't
change the ABI or API (AFAIK). It's called from the library itself
therefore no recompile of applications is necessary. Please also
cf. issue #22 in the issue tracker.
Index: src/base/PdfDictionary.h
===================================================================
--- src/base/PdfDictionary.h (revisión: 1947)
+++ src/base/PdfDictionary.h (revisión: 1948)
@@ -180,6 +180,21 @@
*/
PdfObject* GetKey( const PdfName & key );
+ /** Get the key's value out of the dictionary.
+ *
+ * The returned value is a reference to the internal object in the dictionary
+ * so it MUST not be deleted. If the key is not found, this throws a PdfError
+ * exception with error code ePdfError_NoObject, instead of returning.
+ * This is intended to make code more readable by sparing (especially multiple)
+ * NULL checks.
+ *
+ * \param key look for the key named key in the dictionary
+ *
+ * \returns reference to the found value (never 0).
+ * \throws PdfError(ePdfError_NoObject).
+ */
+ inline const PdfObject& MustGetKey( const PdfName & key ) const;
+
pdf_int64 GetKeyAsLong( const PdfName & key, pdf_int64 lDefault = 0 ) const;
double GetKeyAsReal( const PdfName & key, double dDefault = 0.0 ) const;
@@ -305,6 +320,17 @@
// -----------------------------------------------------
//
// -----------------------------------------------------
+const PdfObject& PdfDictionary::MustGetKey( const PdfName & key ) const
+{
+ const PdfObject* obj = GetKey( key );
+ if (!obj)
+ PODOFO_RAISE_ERROR( ePdfError_NoObject );
+ return *obj;
+}
+
+// -----------------------------------------------------
+//
+// -----------------------------------------------------
void PdfDictionary::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const
{
this->Write( pDevice, eWriteMode, pEncrypt, PdfName::KeyNull );
Index: src/base/PdfEncrypt.cpp
===================================================================
--- src/base/PdfEncrypt.cpp (revisión: 1947)
+++ src/base/PdfEncrypt.cpp (revisión: 1948)
@@ -564,16 +564,14 @@
bool encryptMetadata = true;
try {
- PdfString sTmp;
+ lV = static_cast<long>(pObject->GetDictionary().MustGetKey( PdfName("V") ).GetNumber());
+ rValue = static_cast<int>( pObject->GetDictionary().MustGetKey( PdfName("R") ).GetNumber());
- lV = static_cast<long>(pObject->GetDictionary().GetKey( PdfName("V") )->GetNumber());
- rValue = static_cast<int>(pObject->GetDictionary().GetKey( PdfName("R") )->GetNumber());
+ pValue = static_cast<int>( pObject->GetDictionary().MustGetKey( PdfName("P") ).GetNumber());
- pValue = static_cast<int>(pObject->GetDictionary().GetKey( PdfName("P") )->GetNumber());
+ oValue = pObject->GetDictionary().MustGetKey( PdfName("O") ).GetString();
+ uValue = pObject->GetDictionary().MustGetKey( PdfName("U") ).GetString();
- oValue = pObject->GetDictionary().GetKey( PdfName("O") )->GetString();
- uValue = pObject->GetDictionary().GetKey( PdfName("U") )->GetString();
-
if( pObject->GetDictionary().HasKey( PdfName("Length") ) )
{
lLength = pObject->GetDictionary().GetKey( PdfName("Length") )->GetNumber();
@@ -598,7 +596,7 @@
}
}
} catch( PdfError & e ) {
- e.AddToCallstack( __FILE__, __LINE__, "Invalid key in encryption dictionary" );
+ e.AddToCallstack( __FILE__, __LINE__, "Invalid or missing key in encryption dictionary" );
throw e;
}
------------------------------------------------------------------------
++++++ r1949-Fix-CVE-2018-5783-by-introducing-singleton-limit-for-indirect-objects-keeping-binary-compat.patch ++++++
------------------------------------------------------------------------
r1949 | mabri | 2018-11-13 23:53:01 +0100 (mar 13 de nov de 2018) | 8 líneas
Fix CVE-2018-5783 by introducing singleton limit for indirect objects
The limit is the standard one of 8,388,607 but can be changed by
a newly introduced inline method (also a getter is provided).
This also introduced a new define PODOFO_SIZE_FORMAT for formatting
size_t values portably in printf()-like methods of PdfError etc.
Please also cf. issue #4 in the issue tracker.
Modified by Antonio Larrosa so the patch
doesn't break binary compatibility
Index: src/base/PdfCompilerCompat.h
===================================================================
--- src/base/PdfCompilerCompat.h (revisión: 1948)
+++ src/base/PdfCompilerCompat.h (revisión: 1949)
@@ -184,12 +184,15 @@
#if defined(_MSC_VER)
# define PDF_FORMAT_INT64 "I64d"
# define PDF_FORMAT_UINT64 "I64u"
+# define PDF_SIZE_FORMAT "Iu"
#elif defined(SZ_INT64) && defined(SZ_LONG) && SZ_INT64 == SZ_LONG
# define PDF_FORMAT_INT64 "ld"
# define PDF_FORMAT_UINT64 "lu"
+# define PDF_SIZE_FORMAT "zu"
#else
# define PDF_FORMAT_INT64 "lld"
# define PDF_FORMAT_UINT64 "llu"
+# define PDF_SIZE_FORMAT "zu"
#endif
Index: src/base/PdfVecObjects.h
===================================================================
--- src/base/PdfVecObjects.h (revisión: 1948)
+++ src/base/PdfVecObjects.h (revisión: 1949)
@@ -496,7 +496,16 @@
// -----------------------------------------------------
inline void PdfVecObjects::Reserve( size_t size )
{
- m_vector.reserve( size );
+ if( size <= static_cast(8388607) ) // Fix CVE-2018-5783
+ {
+ m_vector.reserve( size );
+ }
+ else
+ {
+ PdfError::DebugMessage( "Call to PdfVecObjects::Reserve with %"
+ PDF_SIZE_FORMAT" is over allowed limit of %"
+ PDF_SIZE_FORMAT".\n", size, static_cast(8388607));
+ }
}
// -----------------------------------------------------
------------------------------------------------------------------------
++++++ r1950-Fix-null-pointer-dereference-in-PdfTranslator-setTarget.patch ++++++
------------------------------------------------------------------------
r1950 | mabri | 2018-11-17 00:05:15 +0100 (sáb 17 de nov de 2018) | 4 líneas
Fix issue #32: null pointer dereference in PdfTranslator::setTarget()
This is in podofoimpose and fixed there (pdftranslator.cpp) directly.
Index: tools/podofoimpose/pdftranslator.cpp
===================================================================
--- tools/podofoimpose/pdftranslator.cpp (revisión: 1949)
+++ tools/podofoimpose/pdftranslator.cpp (revisión: 1950)
@@ -256,7 +256,13 @@
PdfPage * page = sourceDoc->GetPage ( i );
PdfMemoryOutputStream outMemStream ( 1 );
- PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc );
+ if (!page) // Fix issue #32
+ {
+ std::ostringstream oss;
+ oss << "Page " << i << " (0-based) of " << pcount << " in source doc not found!";
+ PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, oss.str() );
+ }
+ PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc );
if ( page->GetContents()->HasStream() )
{
page->GetContents()->GetStream()->GetFilteredCopy ( &outMemStream );
------------------------------------------------------------------------
++++++ r1952-Fix-CVE-2018-11255-Null-pointer-dereference-in-PdfPage-GetPageNumber.patch ++++++
------------------------------------------------------------------------
r1952 | mabri | 2018-11-17 00:48:14 +0100 (sáb 17 de nov de 2018) | 4 líneas
Fix CVE-2018-11255: Null pointer dereference in PdfPage::GetPageNumber()
Please cf. issue #20.
Index: src/doc/PdfPage.cpp
===================================================================
--- src/doc/PdfPage.cpp (revisión: 1951)
+++ src/doc/PdfPage.cpp (revisión: 1952)
@@ -595,6 +595,13 @@
while( it != kids.end() && (*it).GetReference() != ref )
{
PdfObject* pNode = this->GetObject()->GetOwner()->GetObject( (*it).GetReference() );
+ if (!pNode)
+ {
+ std::ostringstream oss;
+ oss << "Object " << (*it).GetReference().ToString() << " not found from Kids array "
+ << pKids->Reference().ToString();
+ PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, oss.str() );
+ }
if( pNode->GetDictionary().GetKey( PdfName::KeyType ) != NULL
&& pNode->GetDictionary().GetKey( PdfName::KeyType )->GetName() == PdfName( "Pages" ) )
------------------------------------------------------------------------
++++++ r1953-Fix-CVE-2018-14320-Possible-undefined-behaviour-in-PdfEncoding-ParseToUnicode.patch ++++++
------------------------------------------------------------------------
r1953 | mc-zyx | 2018-11-22 10:04:02 +0100 (jue 22 de nov de 2018) | 7 líneas
Patch by Mark Rogers: CVE-2018-14320 - Possible undefined behaviour in PdfEncoding::ParseToUnicode()
There is undefined behaviour in PdfEncoding::ParseToUnicode() if the first
token in the parsed stream is 'beginbfrange' or 'beginbfchar'. In both
cases stkToken.top() is called when stkToken.size() == 0, which results
in the undefined behaviour.
Index: src/base/PdfEncoding.cpp
===================================================================
--- src/base/PdfEncoding.cpp (revisión: 1952)
+++ src/base/PdfEncoding.cpp (revisión: 1953)
@@ -285,6 +285,12 @@
if (strcmp (streamToken, "beginbfrange") == 0)
{
+ // need 2 entries - one to pop() and one for top()
+ if ( stkToken.size() < 2 )
+ {
+ PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidStream, "CMap missing object number before beginbfrange");
+ }
+
i = loop = 0;
in_beginbfrange = 1;
stkToken.pop ();
@@ -301,6 +307,12 @@
if (strcmp (streamToken, "beginbfchar") == 0)
{
+ // need 2 entries - one to pop() and one for top()
+ if ( stkToken.size() < 2 )
+ {
+ PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidStream, "CMap missing object number before beginbfchar");
+ }
+
i = loop = 0;
in_beginbfchar = 1;
stkToken.pop ();
Index: test/unit/EncodingTest.cpp
===================================================================
--- test/unit/EncodingTest.cpp (revisión: 1952)
+++ test/unit/EncodingTest.cpp (revisión: 1953)
@@ -359,6 +359,57 @@
#endif
CPPUNIT_ASSERT_EQUAL( expects, unicodeStr[ii] );
}
+
+ const char* toUnicodeInvalidTests[] =
+ {
+ // missing object numbers
+ "beginbfrange\n",
+ "beginbfchar\n",
+
+ // invalid hex digits
+ "2 beginbfrange <WXYZ> endbfrange\n",
+ "2 beginbfrange <-123> endbfrange\n",
+ "2 beginbfrange <<00>> endbfrange\n",
+
+ // missing hex digits
+ "2 beginbfrange <> endbfrange\n",
+
+ // empty array
+ "2 beginbfrange [] endbfrange\n",
+
+ nullptr
+ };
+
+ for ( size_t i = 0 ; toUnicodeInvalidTests[i] != nullptr ; ++i )
+ {
+ try
+ {
+ PdfVecObjects vecInvalid;
+ PdfObject *strmInvalidObject;
+
+ vec.SetAutoDelete( true );
+
+ strmInvalidObject = vecInvalid.CreateObject( PdfVariant( PdfDictionary() ) );
+ strmInvalidObject->GetStream()->Set( toUnicodeInvalidTests[i], strlen( toUnicodeInvalidTests[i] ) );
+
+ PdfIdentityEncoding encodingTestInvalid(0x0001, 0x000F, true, strmInvalidObject);
+
+ PdfString unicodeStringTestInvalid = encoding.ConvertToUnicode( PdfString( encodedStr ), NULL );
+
+ // exception not thrown - should never get here
+ // TODO not all invalid input throws an exception (e.g. no hex digits in <WXYZ>)
+ //CPPUNIT_ASSERT( false );
+ }
+ catch ( PoDoFo::PdfError& error )
+ {
+ // parsing every invalid test string should throw an exception
+ CPPUNIT_ASSERT( true );
+ }
+ catch( std::exception& ex )
+ {
+ CPPUNIT_FAIL( "Unexpected exception type" );
+ }
+ }
}
bool EncodingTest::outofRangeHelper( PdfEncoding* pEncoding, std::string & rMsg, const char* pszName )
------------------------------------------------------------------------
++++++ r1954-Fix-CVE-2018-20751-null-pointer-dereference-in-crop_page-of-tools-podofocrop.patch ++++++
------------------------------------------------------------------------
r1954 | mabri | 2018-11-26 23:16:19 +0100 (lun 26 de nov de 2018) | 2 líneas
Fix issue #33 (null-pointer dereference in crop_page() of tools/podofocrop/podofocrop.cpp)
Index: tools/podofocrop/podofocrop.cpp
===================================================================
--- tools/podofocrop/podofocrop.cpp (revisión: 1953)
+++ tools/podofocrop/podofocrop.cpp (revisión: 1954)
@@ -61,6 +61,11 @@
rCropBox.GetHeight());
*/
rCropBox.ToVariant( var );
+ if (!pPage)
+ {
+ PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle,
+ "crop_page: No page pointer given" );
+ }
pPage->GetObject()->GetDictionary().AddKey( PdfName("MediaBox"), var );
}
------------------------------------------------------------------------
++++++ r1961-EncryptTest-Fix-buffer-overflow-in-decrypted-out-buffer-in-TestEncrypt.patch ++++++
------------------------------------------------------------------------
r1961 | mabri | 2019-02-03 00:14:11 +0100 (dom 03 de feb de 2019) | 17 líneas
Patch by Francesco Pretto: EncryptTest: Fix buffer overflow in decrypted out buffer in TestEncrypt()
According to OpenSSL 1.1.0 documentation[1], "the decrypted data buffer out passed
to the EVP_DecryptUpdate() should have sufficient room for (inl + cipher_block_size)
bytes". In TestEncrypt(), pDecryptedBuffer has the exactly the size of the known clear
text, which sounds correct but it's currently violating the contract of EVP_DecryptUpdate()
used in PdfEncryptAESBase::BaseDecrypt() and causing a buffer overflow detected by
MSVC when running the the test in a Debug build. Fix TestEncrypt() so the out data buffer
will end up having exactly inl + cipher_block_size bytes.
[1] https://www.openssl.org/docs/man1.1.0/crypto/EVP_DecryptUpdate.html
The foregoing patch description except for the patch attribution is content-wise by the patch author.
Patch-Date: Tue Dec 25 20:59:16 2018 +0100
Post-Archive-Date: 2018-12-25 20:04:26 +0000
Post-Archive-URL: https://sourceforge.net/p/podofo/mailman/message/36501805/
Index: test/unit/EncryptTest.cpp
===================================================================
--- test/unit/EncryptTest.cpp (revisión: 1960)
+++ test/unit/EncryptTest.cpp (revisión: 1961)
@@ -199,7 +199,7 @@
pdf_long nOutputLen = pEncrypt->CalculateStreamLength(m_lLen);
unsigned char *pEncryptedBuffer = new unsigned char[nOutputLen];
- unsigned char *pDecryptedBuffer = new unsigned char[m_lLen];
+ unsigned char *pDecryptedBuffer = new unsigned char[nOutputLen];
// Encrypt buffer
try {
------------------------------------------------------------------------
++++++ r1963-Fix-heap-based-buffer-overflow-vulnerability-in-PoDoFo-PdfVariant-DelayedLoad.patch ++++++
------------------------------------------------------------------------
r1963 | mabri | 2019-02-03 01:00:23 +0100 (dom 03 de feb de 2019) | 1 línea
Fix (security) issue #39
Index: src/doc/PdfNamesTree.cpp
===================================================================
--- src/doc/PdfNamesTree.cpp (revisión: 1962)
+++ src/doc/PdfNamesTree.cpp (revisión: 1963)
@@ -504,7 +504,17 @@
// convert all strings into names
PdfName name( (*it).GetString().GetString() );
++it;
- rDict.AddKey( name, *(it) );
+ // fixes (security) issue #39 in PoDoFo's tracker (sourceforge.net)
+ if ( it == names.end() )
+ {
+ PdfError::LogMessage( eLogSeverity_Warning,
+ "No reference in /Names array last element in "
+ "object %lu %lu, possible\nexploit attempt!\n",
+ pObj->Reference().ObjectNumber(),
+ pObj->Reference().GenerationNumber() );
+ break;
+ }
+ rDict.AddKey( name, (*it) );
++it;
}
------------------------------------------------------------------------