File r1924-Add-PdfRecursionGuard-to-detect-recursions-in-XRef-tables.patch of Package podofo.23799
------------------------------------------------------------------------
r1924 | domseichter | 2018-04-30 20:28:12 +0200 (lun, 30 abr 2018) | 1 line
ADDED: #7 Patch by Mark Rogers to add PdfRecursionGuard to detect recursions in XRef tables
Index: src/base/PdfParser.cpp
===================================================================
--- src/base/PdfParser.cpp (revision 1923)
+++ src/base/PdfParser.cpp (revision 1924)
@@ -74,6 +74,44 @@
long PdfParser::s_nMaxObjects = std::numeric_limits<long>::max();
+class PdfRecursionGuard
+{
+ // RAII recursion guard ensures m_nRecursionDepth is always decremented
+ // because the destructor is always called when control leaves a method
+ // via return or an exception.
+ // see http://en.cppreference.com/w/cpp/language/raii
+
+ // It's used like this in PdfParser methods
+ // PdfRecursionGuard guard(m_nRecursionDepth);
+
+ public:
+ PdfRecursionGuard( int& nRecursionDepth )
+ : m_nRecursionDepth(nRecursionDepth)
+ {
+ // be careful changing this limit - overflow limits depend on the OS, linker settings, and how much stack space compiler allocates
+ // 500 limit prevents overflow on Win7 with VC++ 2005 with default linker stack size (1000 caused overflow with same compiler/OS)
+ const int maxRecursionDepth = 500;
+
+ ++m_nRecursionDepth;
+
+ if ( m_nRecursionDepth > maxRecursionDepth )
+ {
+ // avoid stack overflow on documents that have circular cross references in /Prev entries
+ // in trailer and XRef streams (possible via a chain of entries with a loop)
+ PODOFO_RAISE_ERROR( ePdfError_InvalidXRef );
+ }
+ }
+
+ ~PdfRecursionGuard()
+ {
+ --m_nRecursionDepth;
+ }
+
+ private:
+ // must be a reference so that we modify m_nRecursionDepth in parent class
+ int& m_nRecursionDepth;
+};
+
PdfParser::PdfParser( PdfVecObjects* pVecObjects )
: PdfTokenizer(), m_vecObjects( pVecObjects ), m_bStrictParsing( false )
@@ -147,7 +185,7 @@
m_bIgnoreBrokenObjects = false;
m_nIncrementalUpdates = 0;
- m_nReadNextTrailerLevel = 0;
+ m_nRecursionDepth = 0;
}
void PdfParser::ParseFile( const char* pszFilename, bool bLoadOnDemand )
@@ -514,17 +552,7 @@
void PdfParser::ReadNextTrailer()
{
- // be careful changing this limit - overflow limits depend on the OS, linker settings, and how much stack space compiler allocates
- // 500 limit prevents overflow on Win7 with VC++ 2005 with default linker stack size (1000 caused overflow with same compiler/OS)
- const int maxReadNextTrailerLevel = 500;
-
- ++m_nReadNextTrailerLevel;
-
- if ( m_nReadNextTrailerLevel > maxReadNextTrailerLevel )
- {
- // avoid stack overflow on documents that have circular cross references in trailer
- PODOFO_RAISE_ERROR( ePdfError_InvalidXRef );
- }
+ PdfRecursionGuard guard(m_nRecursionDepth);
// ReadXRefcontents has read the first 't' from "trailer" so just check for "railer"
if( this->IsNextToken( "trailer" ) )
@@ -575,8 +603,6 @@
{
PODOFO_RAISE_ERROR( ePdfError_NoTrailer );
}
-
- --m_nReadNextTrailerLevel;
}
void PdfParser::ReadTrailer()
@@ -642,6 +668,8 @@
void PdfParser::ReadXRefContents( pdf_long lOffset, bool bPositionAtEnd )
{
+ PdfRecursionGuard guard(m_nRecursionDepth);
+
long long nFirstObject = 0;
long long nNumObjects = 0;
@@ -894,6 +922,8 @@
void PdfParser::ReadXRefStreamContents( pdf_long lOffset, bool bReadOnlyTrailer )
{
+ PdfRecursionGuard guard(m_nRecursionDepth);
+
m_device.Device()->Seek( lOffset );
PdfXRefStreamParserObject xrefObject( m_vecObjects, m_device, m_buffer, &m_offsets );
Index: src/base/PdfParser.h
===================================================================
--- src/base/PdfParser.h (revision 1923)
+++ src/base/PdfParser.h (revision 1924)
@@ -591,7 +591,7 @@
bool m_bIgnoreBrokenObjects;
int m_nIncrementalUpdates;
- int m_nReadNextTrailerLevel;
+ int m_nRecursionDepth;
static long s_nMaxObjects;
------------------------------------------------------------------------