From dfd5030637f8643990161311eb6b47f3292ab076 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 14 Oct 2018 16:38:29 +0200 Subject: [PATCH] (CVE-2018-18557) JBIG: fix potential out-of-bounds write in JBIGDecode() JBIGDecode doesn't check if the user provided buffer is large enough to store the JBIG decoded image, which can potentially cause out-of-bounds write in the buffer. This issue was reported and analyzed by Thomas Dullien. Also fixes a (harmless) potential use of uninitialized memory when tif->tif_rawsize > tif->tif_rawcc And in case libtiff is compiled with CHUNKY_STRIP_READ_SUPPORT, make sure that whole strip data is provided to JBIGDecode() (cherry picked from commit 681748ec2f5ce88da5f9fa6831e1653e46af8a66) --- libtiff/tif_jbig.c | 32 ++++++++++++++++++++++++++------ libtiff/tif_read.c | 6 ++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/libtiff/tif_jbig.c b/libtiff/tif_jbig.c index 7a14dd9a..8136c77b 100644 --- a/libtiff/tif_jbig.c +++ b/libtiff/tif_jbig.c @@ -53,17 +53,18 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) struct jbg_dec_state decoder; int decodeStatus = 0; unsigned char* pImage = NULL; - (void) size, (void) s; + unsigned long decodedSize; + (void) s; if (isFillOrder(tif, tif->tif_dir.td_fillorder)) { - TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); + TIFFReverseBits(tif->tif_rawcp, tif->tif_rawcc); } jbg_dec_init(&decoder); #if defined(HAVE_JBG_NEWLEN) - jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize); + jbg_newlen(tif->tif_rawcp, (size_t)tif->tif_rawcc); /* * I do not check the return status of jbg_newlen because even if this * function fails it does not necessarily mean that decoding the image @@ -76,8 +77,8 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) */ #endif /* HAVE_JBG_NEWLEN */ - decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata, - (size_t)tif->tif_rawdatasize, NULL); + decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawcp, + (size_t)tif->tif_rawcc, NULL); if (JBG_EOK != decodeStatus) { /* @@ -98,9 +99,28 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) return 0; } + decodedSize = jbg_dec_getsize(&decoder); + if( (tmsize_t)decodedSize < size ) + { + TIFFWarningExt(tif->tif_clientdata, "JBIG", + "Only decoded %lu bytes, whereas %lu requested", + decodedSize, (unsigned long)size); + } + else if( (tmsize_t)decodedSize > size ) + { + TIFFErrorExt(tif->tif_clientdata, "JBIG", + "Decoded %lu bytes, whereas %lu were requested", + decodedSize, (unsigned long)size); + jbg_dec_free(&decoder); + return 0; + } pImage = jbg_dec_getimage(&decoder, 0); - _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); + _TIFFmemcpy(buffer, pImage, decodedSize); jbg_dec_free(&decoder); + + tif->tif_rawcp += tif->tif_rawcc; + tif->tif_rawcc = 0; + return 1; } diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c index 2ba985a7..04100f4d 100644 --- a/libtiff/tif_read.c +++ b/libtiff/tif_read.c @@ -348,6 +348,12 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) return 0; whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10 || isMapped(tif); + if( td->td_compression == COMPRESSION_JBIG ) + { + /* Ideally plugins should have a way to declare they don't support + * chunk strip */ + whole_strip = 1; + } #else whole_strip = 1; #endif