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.
207 lines
8.7 KiB
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 {
|