File podofo-CVE-2018-20797.patch of Package podofo.35911
--- src/base/PdfFiltersPrivate.cpp
+++ src/base/PdfFiltersPrivate.cpp
@@ -93,6 +93,14 @@
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)
{
@@ -108,6 +116,18 @@
m_nCurRowIndex = 0;
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 )
--- src/base/PdfMemoryManagement.cpp
+++ src/base/PdfMemoryManagement.cpp
@@ -113,6 +113,48 @@
if (nmemb == 0)
nmemb = 1;
+ if ( podofo_multiplication_overflow( nmemb, size ) )
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ return calloc(nmemb, size);
+}
+
+void* podofo_realloc( void* buffer, size_t size )
+{
+ /*
+ realloc behaviour with size==0 is platform specific (and dangerous in Visual C++)
+
+ Windows Visual C++
+ If size is zero, then the block pointed to by memblock is freed; the return value is NULL, and buffer is left pointing at a freed block.
+ NOTE: this is very dangerous, since NULL is also returned when there's not enough memory, but the block ISN'T freed
+
+ OpenBSD
+ If size is equal to 0, a unique pointer to an access protected, zero sized object is returned.
+ Access via this pointer will generate a SIGSEGV exception.
+
+ Linux
+ If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
+
+ OS X
+ If size is zero and buffer is not NULL, a new, minimum sized object is allocated and the original object is freed.
+ */
+
+ if (size == 0)
+ size = 1;
+
+ return realloc( buffer, size );
+}
+
+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.
@@ -129,42 +171,10 @@
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
{
- errno = ENOMEM;
- return NULL;
+ return true;
}
- return calloc(nmemb, size);
-}
-
-void* podofo_realloc( void* buffer, size_t size )
-{
- /*
- realloc behaviour with size==0 is platform specific (and dangerous in Visual C++)
-
- Windows Visual C++
- If size is zero, then the block pointed to by memblock is freed; the return value is NULL, and buffer is left pointing at a freed block.
- NOTE: this is very dangerous, since NULL is also returned when there's not enough memory, but the block ISN'T freed
-
- OpenBSD
- If size is equal to 0, a unique pointer to an access protected, zero sized object is returned.
- Access via this pointer will generate a SIGSEGV exception.
-
- Linux
- If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
-
- OS X
- If size is zero and buffer is not NULL, a new, minimum sized object is allocated and the original object is freed.
- */
-
- if (size == 0)
- size = 1;
-
- return realloc( buffer, size );
-}
-
-void podofo_free( void* buffer )
-{
- free( buffer );
+ return false;
}
};
--- src/base/PdfMemoryManagement.h
+++ src/base/PdfMemoryManagement.h
@@ -75,6 +75,11 @@
*/
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 );
};