[Ubuntu note: Backport of the following patch from upstream, with a few changes to match the current version of the file in the present Ubuntu release: . using TIFFWarningExt instead of TIFFWarningExtR (the latter did not exist yet); . using uint64 instead of uint64_t to preserve the current code usage; -- Rodrigo Figueiredo Zaiden] Backport of: From 0b025324711213a75e38b52f7e7ba60235f108aa Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 31 Oct 2023 19:47:22 +0100 Subject: [PATCH] tif_dirread.c: only issue TIFFGetFileSize() for large enough RAM requests Ammends 5320c9d89c054fa805d037d84c57da874470b01a This fixes a performance regression caught by the GDAL regression test suite. Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/tiff/tree/debian/patches/CVE-2023-6277-2.patch?h=ubuntu/focal-security Upstream commit https://gitlab.com/libtiff/libtiff/-/commit/0b025324711213a75e38b52f7e7ba60235f108aa] CVE: CVE-2023-6277 Signed-off-by: Vijay Anusuri --- libtiff/tif_dirread.c | 83 +++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 35 deletions(-) --- tiff-4.1.0+git191117.orig/libtiff/tif_dirread.c +++ tiff-4.1.0+git191117/libtiff/tif_dirread.c @@ -864,19 +864,22 @@ static enum TIFFReadDirEntryErr TIFFRead datasize=(*count)*typesize; assert((tmsize_t)datasize>0); - /* Before allocating a huge amount of memory for corrupted files, check if - * size of requested memory is not greater than file size. - */ - uint64 filesize = TIFFGetFileSize(tif); - if (datasize > filesize) + if (datasize > 100 * 1024 * 1024) { - TIFFWarningExt(tif->tif_clientdata, "ReadDirEntryArray", - "Requested memory size for tag %d (0x%x) %" PRIu32 - " is greather than filesize %" PRIu64 - ". Memory not allocated, tag not read", - direntry->tdir_tag, direntry->tdir_tag, datasize, - filesize); - return (TIFFReadDirEntryErrAlloc); + /* Before allocating a huge amount of memory for corrupted files, check + * if size of requested memory is not greater than file size. + */ + const uint64 filesize = TIFFGetFileSize(tif); + if (datasize > filesize) + { + TIFFWarningExt(tif->tif_clientdata, "ReadDirEntryArray", + "Requested memory size for tag %d (0x%x) %" PRIu32 + " is greater than filesize %" PRIu64 + ". Memory not allocated, tag not read", + direntry->tdir_tag, direntry->tdir_tag, datasize, + filesize); + return (TIFFReadDirEntryErrAlloc); + } } if( isMapped(tif) && datasize > (uint32)tif->tif_size ) @@ -4550,18 +4553,22 @@ EstimateStripByteCounts(TIFF* tif, TIFFD if( !_TIFFFillStrilesInternal( tif, 0 ) ) return -1; - /* Before allocating a huge amount of memory for corrupted files, check if - * size of requested memory is not greater than file size. */ - uint64 filesize = TIFFGetFileSize(tif); - uint64 allocsize = (uint64)td->td_nstrips * sizeof(uint64); - if (allocsize > filesize) + const uint64 allocsize = (uint64)td->td_nstrips * sizeof(uint64); + uint64 filesize = 0; + if (allocsize > 100 * 1024 * 1024) { - TIFFWarningExt(tif->tif_clientdata, module, - "Requested memory size for StripByteCounts of %" PRIu64 - " is greather than filesize %" PRIu64 - ". Memory not allocated", - allocsize, filesize); - return -1; + /* Before allocating a huge amount of memory for corrupted files, check + * if size of requested memory is not greater than file size. */ + filesize = TIFFGetFileSize(tif); + if (allocsize > filesize) + { + TIFFWarningExt( + tif->tif_clientdata, module, + "Requested memory size for StripByteCounts of %" PRIu64 + " is greater than filesize %" PRIu64 ". Memory not allocated", + allocsize, filesize); + return -1; + } } if (td->td_stripbytecount_p) @@ -4608,11 +4615,13 @@ EstimateStripByteCounts(TIFF* tif, TIFFD return -1; space+=datasize; } + if (filesize == 0) + filesize = TIFFGetFileSize(tif); if( filesize < space ) - /* we should perhaps return in error ? */ - space = filesize; - else - space = filesize - space; + /* we should perhaps return in error ? */ + space = filesize; + else + space = filesize - space; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) space /= td->td_samplesperpixel; for (strip = 0; strip < td->td_nstrips; strip++) @@ -4882,19 +4891,23 @@ TIFFFetchDirectory(TIFF* tif, uint64 dir dircount16 = (uint16)dircount64; dirsize = 20; } - /* Before allocating a huge amount of memory for corrupted files, check - * if size of requested memory is not greater than file size. */ - uint64 filesize = TIFFGetFileSize(tif); - uint64 allocsize = (uint64)dircount16 * dirsize; - if (allocsize > filesize) + const uint64 allocsize = (uint64)dircount16 * dirsize; + if (allocsize > 100 * 1024 * 1024) { - TIFFWarningExt( - tif->tif_clientdata, module, - "Requested memory size for TIFF directory of %" PRIu64 - " is greather than filesize %" PRIu64 - ". Memory not allocated, TIFF directory not read", - allocsize, filesize); - return 0; + /* Before allocating a huge amount of memory for corrupted files, + * check if size of requested memory is not greater than file size. + */ + const uint64 filesize = TIFFGetFileSize(tif); + if (allocsize > filesize) + { + TIFFWarningExt( + tif->tif_clientdata, module, + "Requested memory size for TIFF directory of %" PRIu64 + " is greater than filesize %" PRIu64 + ". Memory not allocated, TIFF directory not read", + allocsize, filesize); + return 0; + } } origdir = _TIFFCheckMalloc(tif, dircount16, dirsize, "to read TIFF directory");