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-8054.patch

207 lines
8.7 KiB

Description: CVE-2017-8054
Acked-By: Mattia Rizzolo <mattia@debian.org>
Bug-Debian: https://bugs.debian.org/860995
Origin: https://sourceforge.net/p/podofo/code/1872
Origin: https://sourceforge.net/p/podofo/code/1881
Origin: https://sourceforge.net/p/podofo/code/1882
Origin: https://sourceforge.net/p/podofo/code/1883
--- a/src/base/PdfError.cpp
+++ b/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 : "" )
{
@@ -96,6 +102,12 @@
}
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 );
--- a/src/base/PdfError.h
+++ b/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 );
@@ -174,6 +174,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 );
@@ -185,6 +186,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:
@@ -242,12 +244,22 @@
* 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
*/
@@ -309,6 +321,21 @@
* \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.
@@ -344,6 +371,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
*/
@@ -478,6 +520,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/src/doc/PdfPagesTree.cpp
+++ b/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,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 (CVE-2017-8054)
+ // replaced by the following inside this conditional incl. continue
+ 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() )
{
@@ -502,6 +514,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 {