------------------------------------------------------------------------
r1948 | mabri | 2018-11-10 23:44:43 +0100 (sáb 10 de nov de 2018) | 9 líneas

Fix CVE-2018-12982 implementing inline PdfDictionary::MustGetKey()

That new method throws, therefore it makes NULL checks in the
calling places unnecessary. That it's inline means that it doesn't
change the ABI or API (AFAIK). It's called from the library itself
therefore no recompile of applications is necessary. Please also
cf. issue #22 in the issue tracker.
 


Index: src/base/PdfDictionary.h
===================================================================
--- src/base/PdfDictionary.h	(revisión: 1947)
+++ src/base/PdfDictionary.h	(revisión: 1948)
@@ -180,6 +180,21 @@
      */
     PdfObject* GetKey( const PdfName & key );
 
+    /** Get the key's value out of the dictionary.
+     *
+     * The returned value is a reference to the internal object in the dictionary
+     * so it MUST not be deleted. If the key is not found, this throws a PdfError
+     * exception with error code ePdfError_NoObject, instead of returning.
+     * This is intended to make code more readable by sparing (especially multiple)
+     * NULL checks.
+     *
+     *  \param key look for the key named key in the dictionary
+     * 
+     *  \returns reference to the found value (never 0).
+     *  \throws PdfError(ePdfError_NoObject).
+     */
+    inline const PdfObject& MustGetKey( const PdfName & key ) const;
+
#     pdf_int64 GetKeyAsLong( const PdfName & key, pdf_int64 lDefault = 0 ) const;
# 
#     double GetKeyAsReal( const PdfName & key, double dDefault = 0.0 ) const;
     long long GetKeyAsLong( const PdfName & key, long long lDefault = 0 ) const;
 
     double GetKeyAsReal( const PdfName & key, double dDefault = 0.0 ) const;
@@ -305,6 +320,17 @@
 // -----------------------------------------------------
 // 
 // -----------------------------------------------------
+const PdfObject& PdfDictionary::MustGetKey( const PdfName & key ) const
+{
+    const PdfObject* obj = GetKey( key );
+    if (!obj)
+        PODOFO_RAISE_ERROR( ePdfError_NoObject );
+    return *obj;
+}
+
+// -----------------------------------------------------
+// 
+// -----------------------------------------------------
 void PdfDictionary::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const 
 { 
     this->Write( pDevice, eWriteMode, pEncrypt, PdfName::KeyNull ); 
Index: src/base/PdfEncrypt.cpp
===================================================================
--- src/base/PdfEncrypt.cpp	(revisión: 1947)
+++ src/base/PdfEncrypt.cpp	(revisión: 1948)
@@ -564,16 +564,14 @@
# 	bool encryptMetadata = true;
     PdfString uValue;
     
     try {
-        PdfString sTmp;
+        lV     = static_cast<long>(pObject->GetDictionary().MustGetKey( PdfName("V") ).GetNumber());
+        rValue = static_cast<int>( pObject->GetDictionary().MustGetKey( PdfName("R") ).GetNumber());
         
-        lV           = static_cast<long>(pObject->GetDictionary().GetKey( PdfName("V") )->GetNumber());
-        rValue       = static_cast<int>(pObject->GetDictionary().GetKey( PdfName("R") )->GetNumber());
+        pValue = static_cast<int>( pObject->GetDictionary().MustGetKey( PdfName("P") ).GetNumber());
         
-        pValue       = static_cast<int>(pObject->GetDictionary().GetKey( PdfName("P") )->GetNumber());
+        oValue =                   pObject->GetDictionary().MustGetKey( PdfName("O") ).GetString();        
+        uValue =                   pObject->GetDictionary().MustGetKey( PdfName("U") ).GetString();
         
-        oValue       = pObject->GetDictionary().GetKey( PdfName("O") )->GetString();        
-        uValue       = pObject->GetDictionary().GetKey( PdfName("U") )->GetString();
-        
         if( pObject->GetDictionary().HasKey( PdfName("Length") ) )
         {
             lLength = pObject->GetDictionary().GetKey( PdfName("Length") )->GetNumber();
@@ -598,7 +596,7 @@
# 			}
# 		}
         }
         
     } catch( PdfError & e ) {
-        e.AddToCallstack( __FILE__, __LINE__, "Invalid key in encryption dictionary" );
+        e.AddToCallstack( __FILE__, __LINE__, "Invalid or missing key in encryption dictionary" );
         throw e;
     }
#
     
------------------------------------------------------------------------
