From e596d4e27c5afb7960dc360fdd3afd90ba0fb8ba Mon Sep 17 00:00:00 2001
From: erouault <erouault>
Date: Mon, 15 Aug 2016 21:05:40 +0000
Subject: [PATCH 2/2] * tools/tiffcrop.c: Fix out-of-bounds write in
 loadImage(). From patch libtiff-CVE-2016-3991.patch from
 libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro (bugzilla #2543)

CVE: CVE-2016-3991
Upstream-Status: Backport
https://github.com/vadz/libtiff/commit/e596d4e27c5afb7960dc360fdd3afd90ba0fb8ba

Signed-off-by: Yi Zhao <yi.zhao@windirver.com>
---
 ChangeLog        |  6 ++++++
 tools/tiffcrop.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index db4ea18..5d60608 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2016-08-15 Even Rouault <even.rouault at spatialys.com>
 
+	* tools/tiffcrop.c: Fix out-of-bounds write in loadImage().
+	From patch libtiff-CVE-2016-3991.patch from
+	libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro (bugzilla #2543)
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
 	* libtiff/tif_pixarlog.c: Fix write buffer overflow in PixarLogEncode
 	if more input samples are provided than expected by PixarLogSetupEncode.
 	Idea based on libtiff-CVE-2016-3990.patch from
diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
index 27abc0b..ddba7b9 100644
--- a/tools/tiffcrop.c
+++ b/tools/tiffcrop.c
@@ -798,6 +798,11 @@ static int readContigTilesIntoBuffer (TIFF* in, uint8* buf,
     }
 
   tile_buffsize = tilesize;
+  if (tilesize == 0 || tile_rowsize == 0)
+  {
+     TIFFError("readContigTilesIntoBuffer", "Tile size or tile rowsize is zero");
+     exit(-1);
+  }
 
   if (tilesize < (tsize_t)(tl * tile_rowsize))
     {
@@ -807,7 +812,12 @@ static int readContigTilesIntoBuffer (TIFF* in, uint8* buf,
               tilesize, tl * tile_rowsize);
 #endif
     tile_buffsize = tl * tile_rowsize;
-    } 
+    if (tl != (tile_buffsize / tile_rowsize))
+    {
+    	TIFFError("readContigTilesIntoBuffer", "Integer overflow when calculating buffer size.");
+        exit(-1);
+    }
+    }
 
   tilebuf = _TIFFmalloc(tile_buffsize);
   if (tilebuf == 0)
@@ -1210,6 +1220,12 @@ static int writeBufferToContigTiles (TIFF* out, uint8* buf, uint32 imagelength,
       !TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps) )
       return 1;
 
+  if (tilesize == 0 || tile_rowsize == 0 || tl == 0 || tw == 0)
+  {
+    TIFFError("writeBufferToContigTiles", "Tile size, tile row size, tile width, or tile length is zero");
+    exit(-1);
+  }
+  
   tile_buffsize = tilesize;
   if (tilesize < (tsize_t)(tl * tile_rowsize))
     {
@@ -1219,6 +1235,11 @@ static int writeBufferToContigTiles (TIFF* out, uint8* buf, uint32 imagelength,
               tilesize, tl * tile_rowsize);
 #endif
     tile_buffsize = tl * tile_rowsize;
+    if (tl != tile_buffsize / tile_rowsize)
+    {
+	TIFFError("writeBufferToContigTiles", "Integer overflow when calculating buffer size");
+	exit(-1);
+    }
     }
 
   tilebuf = _TIFFmalloc(tile_buffsize);
@@ -5945,12 +5966,27 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
     TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 
     tile_rowsize  = TIFFTileRowSize(in);      
+    if (ntiles == 0 || tlsize == 0 || tile_rowsize == 0)
+    {
+	TIFFError("loadImage", "File appears to be tiled, but the number of tiles, tile size, or tile rowsize is zero.");
+	exit(-1);
+    }
     buffsize = tlsize * ntiles;
+    if (tlsize != (buffsize / ntiles))
+    {
+	TIFFError("loadImage", "Integer overflow when calculating buffer size");
+	exit(-1);
+    }
 
-        
     if (buffsize < (uint32)(ntiles * tl * tile_rowsize))
       {
       buffsize = ntiles * tl * tile_rowsize;
+      if (ntiles != (buffsize / tl / tile_rowsize))
+      {
+	TIFFError("loadImage", "Integer overflow when calculating buffer size");
+	exit(-1);
+      }
+      
 #ifdef DEBUG2
       TIFFError("loadImage",
 	        "Tilesize %u is too small, using ntiles * tilelength * tilerowsize %lu",
@@ -5969,8 +6005,25 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
     TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
     stsize = TIFFStripSize(in);
     nstrips = TIFFNumberOfStrips(in);
+    if (nstrips == 0 || stsize == 0)
+    {
+	TIFFError("loadImage", "File appears to be striped, but the number of stipes or stripe size is zero.");
+	exit(-1);
+    }
+
     buffsize = stsize * nstrips;
-    
+    if (stsize != (buffsize / nstrips))
+    {
+	TIFFError("loadImage", "Integer overflow when calculating buffer size");
+	exit(-1);
+    }
+    uint32 buffsize_check;
+    buffsize_check = ((length * width * spp * bps) + 7);
+    if (length != ((buffsize_check - 7) / width / spp / bps))
+    {
+	TIFFError("loadImage", "Integer overflow detected.");
+	exit(-1);
+    }
     if (buffsize < (uint32) (((length * width * spp * bps) + 7) / 8))
       {
       buffsize =  ((length * width * spp * bps) + 7) / 8;
-- 
2.7.4

