From 1b5e3b6a23827c33acf19ad50ce5ce78f12b3773 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 10 Aug 2019 18:25:03 +0200 Subject: Fix integer overflow in _TIFFCheckMalloc() and other implementation-defined behaviour (CVE-2019-14973) _TIFFCheckMalloc()/_TIFFCheckRealloc() used a unsafe way to detect overflow in the multiplication of nmemb and elem_size (which are of type tmsize_t, thus signed), which was especially easily triggered on 32-bit builds (with recent enough compilers that assume that signed multiplication cannot overflow, since this is undefined behaviour by the C standard). The original issue which lead to this fix was trigged from tif_fax3.c There were also unsafe (implementation defied), and broken in practice on 64bit builds, ways of checking that a uint64 fits of a (signed) tmsize_t by doing (uint64)(tmsize_t)uint64_var != uint64_var comparisons. Those have no known at that time exploits, but are better to fix in a more bullet-proof way. Or similarly use of (int64)uint64_var <= 0. --- libtiff/tif_read.c | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) (limited to 'libtiff/tif_read.c') diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c index 1f5362a7..c436b0d5 100644 --- a/libtiff/tif_read.c +++ b/libtiff/tif_read.c @@ -29,9 +29,6 @@ #include "tiffiop.h" #include -#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) -#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) - int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillTile(TIFF* tif, uint32 tile); static int TIFFStartStrip(TIFF* tif, uint32 strip); @@ -49,6 +46,8 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m #define THRESHOLD_MULTIPLIER 10 #define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) +#define TIFF_INT64_MAX ((((int64)0x7FFFFFFF) << 32) | 0xFFFFFFFF) + /* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' * Returns 1 in case of success, 0 otherwise. */ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, @@ -727,23 +726,8 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) return ((tmsize_t)(-1)); } bytecount = TIFFGetStrileByteCount(tif, strip); - if ((int64)bytecount <= 0) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "%I64u: Invalid strip byte count, strip %lu", - (unsigned __int64) bytecount, - (unsigned long) strip); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "%llu: Invalid strip byte count, strip %lu", - (unsigned long long) bytecount, - (unsigned long) strip); -#endif - return ((tmsize_t)(-1)); - } - bytecountm = (tmsize_t)bytecount; - if ((uint64)bytecountm!=bytecount) { - TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow"); + bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount, module); + if (bytecountm == 0) { return ((tmsize_t)(-1)); } if (size != (tmsize_t)(-1) && size < bytecountm) @@ -764,7 +748,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip) if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = TIFFGetStrileByteCount(tif, strip); - if ((int64)bytecount <= 0) { + if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %I64u, strip %lu", @@ -791,7 +775,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip) (bytecount - 4096) / 10 > (uint64)stripsize ) { uint64 newbytecount = (uint64)stripsize * 10 + 4096; - if( (int64)newbytecount >= 0 ) + if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFWarningExt(tif->tif_clientdata, module, @@ -1181,10 +1165,8 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) bytecount64 = TIFFGetStrileByteCount(tif, tile); if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) bytecount64 = (uint64)size; - bytecountm = (tmsize_t)bytecount64; - if ((uint64)bytecountm!=bytecount64) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module); + if( bytecountm == 0 ) { return ((tmsize_t)(-1)); } return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); @@ -1203,7 +1185,7 @@ TIFFFillTile(TIFF* tif, uint32 tile) if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = TIFFGetStrileByteCount(tif, tile); - if ((int64)bytecount <= 0) { + if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "%I64u: Invalid tile byte count, tile %lu", @@ -1230,7 +1212,7 @@ TIFFFillTile(TIFF* tif, uint32 tile) (bytecount - 4096) / 10 > (uint64)stripsize ) { uint64 newbytecount = (uint64)stripsize * 10 + 4096; - if( (int64)newbytecount >= 0 ) + if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFWarningExt(tif->tif_clientdata, module, -- cgit v1.2.1