CVE-2018-18557: Out-of-bounds Write (CWE-787)
value: LibTIFF 3.9.3, 3.9.4, 3.9.5, 3.9.6, 3.9.7, 4.0.0alpha4, 4.0.0alpha5, 4.0.0alpha6, 4.0.0beta7, 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.0.4beta, 4.0.5, 4.0.6, 4.0.7, 4.0.8 and 4.0.9 (with JBIG enabled) decodes arbitrarily-sized JBIG into a buffer, ignoring the buffer size, which leads to a tif_jbig.c JBIGDecode out-of-bounds write.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2018-10-22T16:29Z
Repository: https://gitlab.com/libtiff/libtiff
Language: C
Files changed: libtiff/tif_jbig.c, libtiff/tif_read.c
Commit date: 2018-10-14 16:45:14 +0200
Commit message: 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()

Diff: diff --git a/libtiff/tif_jbig.c b/libtiff/tif_jbig.c
index 0befdf32..7ffe8851 100644
--- a/libtiff/tif_jbig.c
+++ b/libtiff/tif_jbig.c
@@ -49,21 +49,22 @@ static int JBIGSetupDecode(TIFF* tif)
 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
 	 * will fail.  It is generally only needed for received fax images
 	 * that do not contain the actual length of the image in the BIE
@@ -72,12 +73,12 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s)
 	 * PostScript.  As long as the actual image length is contained in the
 	 * BIE header jbg_dec_in should succeed.
 	 */
 #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)
 	{
 		/*
 		 * XXX: JBG_EN constant was defined in pre-2.0 releases of the
 		 * JBIG-KIT. Since the 2.0 the error reporting functions were
@@ -94,13 +95,32 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s)
 			     );
 		jbg_dec_free(&decoder);
 		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;
 }
 
 static int JBIGSetupEncode(TIFF* tif)
 {
diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c
index 518363bb..e63810cc 100644
--- a/libtiff/tif_read.c
+++ b/libtiff/tif_read.c
@@ -344,11 +344,12 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
 #if defined(CHUNKY_STRIP_READ_SUPPORT)
         if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
             return 0;
         whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
                 || isMapped(tif);
-        if( td->td_compression == COMPRESSION_LERC )
+        if( td->td_compression == COMPRESSION_LERC ||
+            td->td_compression == COMPRESSION_JBIG )
         {
             /* Ideally plugins should have a way to declare they don't support
              * chunk strip */
             whole_strip = 1;
         }

Vulnerable code: 	(void) size, (void) s;
		TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize);
	jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize);
	decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata,
				  (size_t)tif->tif_rawdatasize, NULL);
	_TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder));
        if( td->td_compression == COMPRESSION_LERC )
Fixed code: 	unsigned long decodedSize;
	(void) s;
		TIFFReverseBits(tif->tif_rawcp, tif->tif_rawcc);
	jbg_newlen(tif->tif_rawcp, (size_t)tif->tif_rawcc);
	decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawcp,
				  (size_t)tif->tif_rawcc, NULL);
	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;
	}
	_TIFFmemcpy(buffer, pImage, decodedSize);

        tif->tif_rawcp += tif->tif_rawcc;
        tif->tif_rawcc = 0;

        if( td->td_compression == COMPRESSION_LERC ||
            td->td_compression == COMPRESSION_JBIG )