From 8f393acc1e110101c071cb9e49c0599edadeedbd Mon Sep 17 00:00:00 2001
From: Mark Rogers <mark.rogers@powermapper.com>
Date: Wed, 2 Feb 2022 17:35:54 +0000
Subject: [PATCH] fix(podofo): check that /DecodeParams values are in range
 (CVE-2018-20797)

---
 .../podofo/src/podofo/base/PdfFiltersPrivate.cpp   | 20 +++++++++++
 .../podofo/src/podofo/base/PdfMemoryManagement.cpp | 40 ++++++++++++++--------
 .../podofo/src/podofo/base/PdfMemoryManagement.h   |  5 +++
 3 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfFiltersPrivate.cpp b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfFiltersPrivate.cpp
index d41444b9c..09b3ee691 100644
--- a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfFiltersPrivate.cpp
+++ b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfFiltersPrivate.cpp
@@ -93,6 +93,14 @@ public:
         m_nBPC         = static_cast<int>(pDecodeParms->GetKeyAsLong( "BitsPerComponent", 8L ));
         m_nColumns     = static_cast<int>(pDecodeParms->GetKeyAsLong( "Columns", 1L ));
         m_nEarlyChange = static_cast<int>(pDecodeParms->GetKeyAsLong( "EarlyChange", 1L ));
+        
+        // check that input values are in range (CVE-2018-20797)
+        // ISO 32000-2008 specifies these values as all 1 or greater
+        // negative values for m_nColumns / m_nColors / m_nBPC result in huge podofo_calloc
+        if ( m_nColumns < 1 || m_nColors < 1 || m_nBPC < 1 )
+        {
+            PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
+        }
 
         if( m_nPredictor >= 10)
         {
@@ -109,6 +117,18 @@ public:
         m_nBpp  = (m_nBPC * m_nColors) >> 3;
         m_nRows = (m_nColumns * m_nColors * m_nBPC) >> 3;
 
+        // check for multiplication overflow on buffer sizes (e.g. if m_nBPC=2 and m_nColors=SIZE_MAX/2+1)
+        if ( podofo_multiplication_overflow( m_nBPC, m_nColors ) || podofo_multiplication_overflow( m_nColumns, m_nBPC * m_nColors ) )
+        {
+            PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
+        }
+
+        // check that computed allocation sizes are > 0 (CVE-2018-20797)
+        if ( m_nRows < 1 || m_nBpp < 1 )
+        {
+            PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
+        }
+
         m_pPrev = static_cast<char*>(podofo_calloc( m_nRows, sizeof(char) ));
         if( !m_pPrev )
         {
diff --git a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.cpp b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.cpp
index b35698b10..9d6ae5623 100644
--- a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.cpp
+++ b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.cpp
@@ -113,21 +113,7 @@ void* podofo_calloc(size_t nmemb, size_t size)
 	if (nmemb == 0)
 		nmemb = 1;
 
-	/*
-		This overflow check is from OpenBSD reallocarray.c, and is also used in GifLib 5.1.2 onwards.
-		
-        Very old versions of calloc() in NetBSD and OS X 10.4 just multiplied size*nmemb which can
-        overflow size_t and allocate much less memory than expected e.g. 2*(SIZE_MAX/2+1) = 2 bytes. 
-        The calloc() overflow is also present in GCC 3.1.1, GNU Libc 2.2.5 and Visual C++ 6.
-        http://cert.uni-stuttgart.de/ticker/advisories/calloc.html
-
-		MUL_NO_OVERFLOW is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
-		if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
-	*/
-	#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
-    
-	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
-		nmemb > 0 && SIZE_MAX / nmemb < size) 
+	if ( podofo_multiplication_overflow( nmemb, size ) )
 	{
 		errno = ENOMEM;
 		return NULL;
@@ -167,6 +153,30 @@ void podofo_free( void* buffer )
     free( buffer );
 }
 
+bool podofo_multiplication_overflow(size_t nmemb, size_t size)
+{
+	/*
+		This overflow check is from OpenBSD reallocarray.c, and is also used in GifLib 5.1.2 onwards.
+		
+        Very old versions of calloc() in NetBSD and OS X 10.4 just multiplied size*nmemb which can
+        overflow size_t and allocate much less memory than expected e.g. 2*(SIZE_MAX/2+1) = 2 bytes. 
+        The calloc() overflow is also present in GCC 3.1.1, GNU Libc 2.2.5 and Visual C++ 6.
+        http://cert.uni-stuttgart.de/ticker/advisories/calloc.html
+
+		MUL_NO_OVERFLOW is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+		if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+	*/
+	#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
+    
+	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+		nmemb > 0 && SIZE_MAX / nmemb < size) 
+	{
+		return true;
+	}
+
+	return false;
+}
+
 };
 
 // OC 17.08.2010: Activate showing the correct source for Memory Leak Detection in Visual Studio:
diff --git a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.h b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.h
index d42c9e19c..9de3c313d 100644
--- a/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.h
+++ b/Electrum/Mapper/Libs/podofo/src/podofo/base/PdfMemoryManagement.h
@@ -75,6 +75,11 @@ PODOFO_API void podofo_free( void* buffer );
  */
 PODOFO_API bool podofo_is_little_endian();
 
+/**
+ * Check if multiplying two numbers will overflow. This is crucial when calculating buffer sizes that are the product of two numbers/
+ * \returns true if multiplication will overflow
+ */
+PODOFO_API bool podofo_multiplication_overflow( size_t nmemb, size_t size );
 
 };
 
-- 
2.14.1.windows.1

