You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
podofo/CVE-2017-5852.patch

128 lines
5.2 KiB

Description: CVE-2017-5852
The part coming from the email is not (yet?) merged, it's there only to
prevent an ABI breakage and can be safely dropped at the next SONAME bump.
Acked-By: Mattia Rizzolo <mattia@debian.org>
Bug-Debian: https://bugs.debian.org/854600
Origin: https://sourceforge.net/p/podofo/code/1838
Origin: https://sourceforge.net/p/podofo/code/1835
Origin: https://sourceforge.net/p/podofo/code/1841
Origin: https://sourceforge.net/p/podofo/mailman/message/36084628/
Last-Update: 2017-11-12
--- a/src/base/PdfError.cpp
+++ b/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;
@@ -397,6 +400,9 @@
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.";
break;
--- a/src/base/PdfError.h
+++ b/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/src/doc/PdfPage.cpp
+++ b/src/doc/PdfPage.cpp
@@ -214,6 +214,11 @@
const PdfObject* PdfPage::GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject ) const
{
+ return GetInheritedKeyFromObject( inKey, inObject, 0);
+}
+
+const PdfObject* PdfPage::GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject, int depth ) const
+{
const PdfObject* pObj = NULL;
// check for it in the object itself
@@ -227,9 +232,29 @@
// 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 )
+ {
+ 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 );
+ pObj = GetInheritedKeyFromObject( inKey, pObj, depth + 1 );
}
return pObj;
@@ -523,6 +548,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" );
@@ -554,6 +584,12 @@
ref = pParent->Reference();
pParent = pParent->GetIndirectKey( "Parent" );
+ ++depth;
+
+ if ( depth > maxRecursionDepth )
+ {
+ PODOFO_RAISE_ERROR_INFO( ePdfError_BrokenFile, "Loop in Parent chain" );
+ }
}
return ++nPageNumber;
--- a/src/doc/PdfPage.h
+++ b/src/doc/PdfPage.h
@@ -291,7 +291,10 @@
/** 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 ) const; // wraps the next one
+
+ // this is introduced by the fix for CVE-2017-5852, the depth param counts recursion depth, is checked against a max
+ const PdfObject* GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject, int depth ) const PODOFO_LOCAL;
/** Get the annotations array.
* \param bCreate if true the annotations array is created