CVE-2017-5225: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: LibTIFF version 4.0.7 is vulnerable to a heap buffer overflow in the tools/tiffcp resulting in DoS or code execution via a crafted BitsPerSample value.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 9.8
Published: 2017-01-12T11:59Z
Repository: https://github.com/vadz/libtiff
Language: Other
Files changed: ChangeLog, tools/tiffcp.c
Commit date: 2017-01-11 19:25:44 +0000
Commit message: * tools/tiffcp.c: error out cleanly in cpContig2SeparateByRow and
cpSeparate2ContigByRow if BitsPerSample != 8 to avoid heap based overflow.
Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2656 and
http://bugzilla.maptools.org/show_bug.cgi?id=2657

Diff: diff --git a/ChangeLog b/ChangeLog
index f78cad045..064f25b66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+	* tools/tiffcp.c: error out cleanly in cpContig2SeparateByRow and
+	cpSeparate2ContigByRow if BitsPerSample != 8 to avoid heap based overflow.
+	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2656 and
+	http://bugzilla.maptools.org/show_bug.cgi?id=2657
+
 2017-01-11 Even Rouault <even.rouault at spatialys.com>
 
 	* libtiff/tiffio.h, tif_unix.c, tif_win32.c, tif_vms.c: add _TIFFcalloc()
 
 	* libtiff/tif_read.c: TIFFReadBufferSetup(): use _TIFFcalloc() to zero
diff --git a/tools/tiffcp.c b/tools/tiffcp.c
index bdf754c30..8bbcd52fc 100644
--- a/tools/tiffcp.c
+++ b/tools/tiffcp.c
@@ -589,11 +589,11 @@ static	copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
 /* PODD */
 
 static int
 tiffcp(TIFF* in, TIFF* out)
 {
-	uint16 bitspersample, samplesperpixel = 1;
+	uint16 bitspersample = 1, samplesperpixel = 1;
 	uint16 input_compression, input_photometric = PHOTOMETRIC_MINISBLACK;
 	copyFunc cf;
 	uint32 width, length;
 	struct cpTag* p;
 
@@ -1065,10 +1065,20 @@ DECLAREcpFunc(cpContig2SeparateByRow)
 	tdata_t outbuf;
 	register uint8 *inp, *outp;
 	register uint32 n;
 	uint32 row;
 	tsample_t s;
+        uint16 bps = 0;
+
+        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
+        if( bps != 8 )
+        {
+            TIFFError(TIFFFileName(in),
+                      "Error, can only handle BitsPerSample=8 in %s",
+                      "cpContig2SeparateByRow");
+            return 0;
+        }
 
 	inbuf = _TIFFmalloc(scanlinesizein);
 	outbuf = _TIFFmalloc(scanlinesizeout);
 	if (!inbuf || !outbuf)
 		goto bad;
@@ -1118,10 +1128,20 @@ DECLAREcpFunc(cpSeparate2ContigByRow)
 	tdata_t outbuf;
 	register uint8 *inp, *outp;
 	register uint32 n;
 	uint32 row;
 	tsample_t s;
+        uint16 bps = 0;
+
+        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
+        if( bps != 8 )
+        {
+            TIFFError(TIFFFileName(in),
+                      "Error, can only handle BitsPerSample=8 in %s",
+                      "cpSeparate2ContigByRow");
+            return 0;
+        }
 
 	inbuf = _TIFFmalloc(scanlinesizein);
 	outbuf = _TIFFmalloc(scanlinesizeout);
 	if (!inbuf || !outbuf)
                 goto bad;
@@ -1782,11 +1802,11 @@ pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
 {
 	uint16 shortv;
 	uint32 w, l, tw, tl;
 	int bychunk;
 
-	(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
+	(void) TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &shortv);
 	if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
 		fprintf(stderr,
 		    "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
 		    TIFFFileName(in));
 		return (NULL);

Vulnerable code: 	uint16 bitspersample, samplesperpixel = 1;
	(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
Fixed code: 2017-01-11 Even Rouault <even.rouault at spatialys.com>

	* tools/tiffcp.c: error out cleanly in cpContig2SeparateByRow and
	cpSeparate2ContigByRow if BitsPerSample != 8 to avoid heap based overflow.
	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2656 and
	http://bugzilla.maptools.org/show_bug.cgi?id=2657

	uint16 bitspersample = 1, samplesperpixel = 1;
        uint16 bps = 0;

        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
        if( bps != 8 )
        {
            TIFFError(TIFFFileName(in),
                      "Error, can only handle BitsPerSample=8 in %s",
                      "cpContig2SeparateByRow");
            return 0;
        }
        uint16 bps = 0;

        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
        if( bps != 8 )
        {
            TIFFError(TIFFFileName(in),
                      "Error, can only handle BitsPerSample=8 in %s",
                      "cpSeparate2ContigByRow");
            return 0;
        }
	(void) TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &shortv);