From 10f72dd232849d0142a0688bcc9aa71025f120a3 Mon Sep 17 00:00:00 2001
From: erouault <erouault>
Date: Fri, 2 Dec 2016 23:05:51 +0000
Subject: [PATCH 2/4] * libtiff/tif_pixarlog.c, libtiff/tif_luv.c: fix
 heap-based buffer overflow on generation of PixarLog / LUV compressed files,
 with ColorMap, TransferFunction attached and nasty plays with bitspersample.
 The fix for LUV has not been tested, but suffers from the same kind of issue
 of PixarLog. Reported by Agostino Sarubbo. Fixes
 http://bugzilla.maptools.org/show_bug.cgi?id=2604

Upstream-Status: Backport

CVE: CVE-2016-10269
Signed-off-by: Rajkumar Veer <rveer@mvista.com>
---
 ChangeLog              | 10 ++++++++++
 libtiff/tif_luv.c      | 18 ++++++++++++++----
 libtiff/tif_pixarlog.c | 17 +++++++++++++++--
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2e913b6..0a2c2a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,14 @@
 2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+	* libtiff/tif_pixarlog.c, libtiff/tif_luv.c: fix heap-based buffer
+	overflow on generation of PixarLog / LUV compressed files, with
+	ColorMap, TransferFunction attached and nasty plays with bitspersample.
+	The fix for LUV has not been tested, but suffers from the same kind
+	of issue of PixarLog.
+	Reported by Agostino Sarubbo.
+	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2604
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
  
 	* libtiff/tif_ojpeg.c: make OJPEGDecode() early exit in case of failure in
 	OJPEGPreDecode(). This will avoid a divide by zero, and potential other issues.
diff --git a/libtiff/tif_luv.c b/libtiff/tif_luv.c
index f68a9b1..e6783db 100644
--- a/libtiff/tif_luv.c
+++ b/libtiff/tif_luv.c
@@ -158,6 +158,7 @@
 typedef struct logLuvState LogLuvState;
 
 struct logLuvState {
+        int                     encoder_state;  /* 1 if encoder correctly initialized */
 	int                     user_datafmt;   /* user data format */
 	int                     encode_meth;    /* encoding method */
 	int                     pixel_size;     /* bytes per pixel */
@@ -1552,6 +1553,7 @@ LogLuvSetupEncode(TIFF* tif)
 		    td->td_photometric, "must be either LogLUV or LogL");
 		break;
 	}
+	sp->encoder_state = 1;
 	return (1);
 notsupported:
 	TIFFErrorExt(tif->tif_clientdata, module,
@@ -1563,19 +1565,27 @@ notsupported:
 static void
 LogLuvClose(TIFF* tif)
 {
+        LogLuvState* sp = (LogLuvState*) tif->tif_data;
 	TIFFDirectory *td = &tif->tif_dir;
 
+	assert(sp != 0);
 	/*
 	 * For consistency, we always want to write out the same
 	 * bitspersample and sampleformat for our TIFF file,
 	 * regardless of the data format being used by the application.
 	 * Since this routine is called after tags have been set but
 	 * before they have been recorded in the file, we reset them here.
+         * Note: this is really a nasty approach. See PixarLogClose
 	 */
-	td->td_samplesperpixel =
-	    (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
-	td->td_bitspersample = 16;
-	td->td_sampleformat = SAMPLEFORMAT_INT;
+        if( sp->encoder_state )
+        {
+            /* See PixarLogClose. Might avoid issues with tags whose size depends
+             * on those below, but not completely sure this is enough. */
+            td->td_samplesperpixel =
+                (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
+            td->td_bitspersample = 16;
+            td->td_sampleformat = SAMPLEFORMAT_INT;
+        }
 }
 
 static void
diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c
index d1246c3..aa99bc9 100644
--- a/libtiff/tif_pixarlog.c
+++ b/libtiff/tif_pixarlog.c
@@ -1233,8 +1233,10 @@ PixarLogPostEncode(TIFF* tif)
 static void
 PixarLogClose(TIFF* tif)
 {
+        PixarLogState* sp = (PixarLogState*) tif->tif_data;
 	TIFFDirectory *td = &tif->tif_dir;
 
+	assert(sp != 0);
 	/* In a really sneaky (and really incorrect, and untruthful, and
 	 * troublesome, and error-prone) maneuver that completely goes against
 	 * the spirit of TIFF, and breaks TIFF, on close, we covertly
@@ -1243,8 +1245,19 @@ PixarLogClose(TIFF* tif)
 	 * readers that don't know about PixarLog, or how to set
 	 * the PIXARLOGDATFMT pseudo-tag.
 	 */
-	td->td_bitspersample = 8;
-	td->td_sampleformat = SAMPLEFORMAT_UINT;
+
+        if (sp->state&PLSTATE_INIT) {
+            /* We test the state to avoid an issue such as in
+             * http://bugzilla.maptools.org/show_bug.cgi?id=2604
+             * What appends in that case is that the bitspersample is 1 and
+             * a TransferFunction is set. The size of the TransferFunction
+             * depends on 1<<bitspersample. So if we increase it, an access
+             * out of the buffer will happen at directory flushing.
+             * Another option would be to clear those targs. 
+             */
+            td->td_bitspersample = 8;
+            td->td_sampleformat = SAMPLEFORMAT_UINT;
+        }
 }
 
 static void
-- 
1.9.1

