From dcdbb4d76bdf4ce69bd18454d02eb30cedb9a941 Mon Sep 17 00:00:00 2001
From: Mark Rogers <mark.rogers@powermapper.com>
Date: Sat, 28 May 2016 08:36:56 +0100
Subject: [PATCH] PoDoFo: Re-created PdfString fix with improved comments

---
 Electrum/Mapper/Libs/podofo/src/base/PdfString.cpp | 46 ++++++++++++++++++++--
 Electrum/Mapper/Libs/podofo/src/base/PdfString.h   | 39 +++++++++++++++---
 2 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/Electrum/Mapper/Libs/podofo/src/base/PdfString.cpp b/Electrum/Mapper/Libs/podofo/src/base/PdfString.cpp
index 13759b0..e83c916 100644
--- a/Electrum/Mapper/Libs/podofo/src/base/PdfString.cpp
+++ b/Electrum/Mapper/Libs/podofo/src/base/PdfString.cpp
@@ -354,7 +354,7 @@ void PdfString::Write ( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, cons
     // Peter Petrov: 17 May 2008
     // Added check - m_buffer.GetSize()
     // Now we are not encrypting the empty strings (was access violation)!
-    if( pEncrypt && m_buffer.GetSize())
+    if( pEncrypt && m_buffer.GetSize() && IsValid() )
     {
         pdf_long nInputBufferLen = m_buffer.GetSize() - 2; // Cut off the trailing pair of zeros
         pdf_long nUnicodeMarkerOffet = sizeof( PdfString::s_pszUnicodeMarker );
@@ -387,7 +387,7 @@ void PdfString::Write ( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, cons
     }
 
     pDevice->Print( m_bHex ? "<" : "(" );
-    if( m_buffer.GetSize() )
+    if( m_buffer.GetSize() && IsValid() )
     {
         char* pBuf = m_buffer.GetBuffer();
         pdf_long  lLen = m_buffer.GetSize() - 2; // Cut off the trailing pair of zeros
@@ -452,6 +452,12 @@ const PdfString & PdfString::operator=( const PdfString & rhs )
 
 bool PdfString::operator>( const PdfString & rhs ) const
 {
+    if ( !this->IsValid() || !rhs.IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::operator> LHS or RHS was invalid PdfString" );
+        return false;
+    }
+    
     const PdfString & str1 = *this;
     const PdfString & str2 = rhs;
 
@@ -475,6 +481,12 @@ bool PdfString::operator>( const PdfString & rhs ) const
 
 bool PdfString::operator<( const PdfString & rhs ) const
 {
+    if ( !this->IsValid() || !rhs.IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::operator< LHS or RHS was invalid PdfString" );
+        return false;
+    }
+    
     const PdfString & str1 = *this;
     const PdfString & str2 = rhs;
 
@@ -498,6 +510,17 @@ bool PdfString::operator<( const PdfString & rhs ) const
 
 bool PdfString::operator==( const PdfString & rhs ) const
 {
+    if ( !this->IsValid() && !rhs.IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::operator== LHS and RHS both invalid PdfStrings" );
+        return true;
+    }
+    else if ( !this->IsValid() || !rhs.IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::operator== LHS or RHS was invalid PdfString" );
+        return false;
+    }
+
     PdfString str1 = *this;
     PdfString str2 = rhs;
 
@@ -615,6 +638,12 @@ void PdfString::InitUtf8()
 #ifdef _WIN32
 const std::wstring PdfString::GetStringW() const
 {
+    if ( !IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::GetStringW invalid PdfString" );
+        return std::wstring();
+    }
+    
     if( !this->IsUnicode() )
     {
         return this->ToUnicode().GetStringW();
@@ -693,14 +722,25 @@ PdfString PdfString::HexDecode() const
 PdfString PdfString::ToUnicode() const
 {
     if( this->IsUnicode() )
+    {
         return *this;
-    else
+    }
+    else if ( this->IsValid() )
     {
         const PdfEncoding* const pEncoding = (m_pEncoding ? 
                                               m_pEncoding : 
                                               PdfEncodingFactory::GlobalPdfDocEncodingInstance());
         return pEncoding->ConvertToUnicode( *this, NULL );
     }
+    else
+    {
+        // can't convert because PdfString is invalid and has no buffer, so return *this
+        // which means trying to convert an invalid string returns another invalid string
+        // and in the special case where *this is PdfString::StringNull then ToUnicode()
+        // returns PdfString::StringNull
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::ToUnicode invalid PdfString" );
+        return *this;
+    }
 }
 
 void PdfString::SwapBytes( char* pBuf, pdf_long lLen ) 
diff --git a/Electrum/Mapper/Libs/podofo/src/base/PdfString.h b/Electrum/Mapper/Libs/podofo/src/base/PdfString.h
index 3eac3a3..d70cf6e 100644
--- a/Electrum/Mapper/Libs/podofo/src/base/PdfString.h
+++ b/Electrum/Mapper/Libs/podofo/src/base/PdfString.h
@@ -177,6 +177,9 @@ class PODOFO_API PdfString : public PdfDataType{
     void SetHexData( const char* pszHex, pdf_long lLen = -1, PdfEncrypt* pEncrypt = NULL );
 
     /** The string is valid if no error in the constructor has occurred.
+     *  The default constructor PdfString() creates an invalid string, as do
+     *  other constructors when passed a NULL char* or NULL wchar_t*.
+     *  PdfString::StringNull uses the default constructor so is also invalid.
      *  If it is valid it is safe to call all the other member functions.
      *  \returns true if this is a valid initialized PdfString
      */
@@ -229,7 +232,8 @@ class PODOFO_API PdfString : public PdfDataType{
      *  characters. Better use GetUnicode() in this case.
      * 
      *  \returns the strings contents which is guaranteed to be zero terminated
-     *           but might also contain 0 bytes in the string.
+     *           but might also contain 0 bytes in the string,
+     *           returns NULL if PdfString::IsValid() returns false
      *
      *  \see IsHex
      *  \see IsUnicode
@@ -245,7 +249,8 @@ class PODOFO_API PdfString : public PdfDataType{
      *
      *  This is the prefered way to access the strings contents.
      *
-     *  \returns the string contents always as UTF8.
+     *  \returns the string contents always as UTF8,
+     *           returns NULL if PdfString::IsValid() returns false
      */
     inline const std::string & GetStringUtf8() const;
 
@@ -253,6 +258,7 @@ class PODOFO_API PdfString : public PdfDataType{
     /** The contents of the string as wide character string.
      *
      *  \returns the string contents as wide character string.
+     *           returns an empty string if PdfString::IsValid() returns false
      */
     const std::wstring GetStringW() const;
 #endif // _WIN32
@@ -260,7 +266,8 @@ class PODOFO_API PdfString : public PdfDataType{
     /** The length of the string data returned by GetString() 
      *  in bytes not including terminating zeros.
      *
-     *  \returns the length of the string. 
+     *  \returns the length of the string,
+     *           returns zero if PdfString::IsValid() returns false
      *
      *  \see GetCharacterLength to determine the number of characters in the string
      */
@@ -269,7 +276,8 @@ class PODOFO_API PdfString : public PdfDataType{
     /** The length of the string data returned by GetUnicode() 
      *  in characters not including the terminating zero 
      *
-     *  \returns the length of the string. 
+     *  \returns the length of the string,
+     *           returns zero if PdfString::IsValid() returns false
      *
      *  \see GetCharacterLength to determine the number of characters in the string
      */
@@ -283,7 +291,8 @@ class PODOFO_API PdfString : public PdfDataType{
      *  as GetLength() will returns the number of bytes used for unicode strings!
      *
      * 
-     *  \returns the number of characters in the string
+     *  \returns the number of characters in the string,
+     *           returns zero if PdfString::IsValid() returns false
      */
     inline pdf_long GetCharacterLength() const;
 
@@ -362,13 +371,15 @@ class PODOFO_API PdfString : public PdfDataType{
      *  If IsUnicode() returns true a copy of this string is returned
      *  otherwise the string data is converted to UTF-16be and returned.
      *
-     *  \returns a unicode version of this string
+     *  \returns a unicode version of this string,
+     *           returns *this if if PdfString::IsValid() returns false
      */
     PdfString ToUnicode() const;
 
 	 /** Returns internal buffer; do not free it, it's owned by the PdfString
 	  *
 	  * \returns internal buffer; do not free it, it's owned by the PdfString
+      *          returns a NULL zero size buffer if PdfString::IsValid() returns false
 	  */
 	 PdfRefCountedBuffer &GetBuffer(void);
 
@@ -503,6 +514,14 @@ const std::string & PdfString::GetStringUtf8() const
 // -----------------------------------------------------
 pdf_long PdfString::GetLength() const
 {
+    if ( !IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::GetLength invalid PdfString" );
+        return 0;
+    }
+    
+    PODOFO_ASSERT( m_buffer.GetSize() >= 2 );
+    
     return m_buffer.GetSize() - 2;
 }
 
@@ -519,6 +538,14 @@ pdf_long PdfString::GetCharacterLength() const
 // -----------------------------------------------------
 pdf_long PdfString::GetUnicodeLength() const
 {
+    if ( !IsValid() )
+    {
+        PdfError::LogMessage( eLogSeverity_Error, "PdfString::GetUnicodeLength invalid PdfString" );
+        return 0;
+    }
+    
+    PODOFO_ASSERT( (m_buffer.GetSize() / sizeof(pdf_utf16be)) >= 1 );
+    
     return (m_buffer.GetSize() / sizeof(pdf_utf16be)) - 1;
 }
 
-- 
2.2.1

