Blame SOURCES/libtiff-CVE-2018-7456.patch

6456d8
From f1c2759436a0ee5181cae7176114f57e45f0eb16 Mon Sep 17 00:00:00 2001
6456d8
From: Hugo Lefeuvre <hle@debian.org>
6456d8
Date: Sun, 8 Apr 2018 14:07:08 -0400
6456d8
Subject: [PATCH] Fix NULL pointer dereference in TIFFPrintDirectory
6456d8
6456d8
The TIFFPrintDirectory function relies on the following assumptions,
6456d8
supposed to be guaranteed by the specification:
6456d8
6456d8
(a) A Transfer Function field is only present if the TIFF file has
6456d8
    photometric type < 3.
6456d8
6456d8
(b) If SamplesPerPixel > Color Channels, then the ExtraSamples field
6456d8
    has count SamplesPerPixel - (Color Channels) and contains
6456d8
    information about supplementary channels.
6456d8
6456d8
While respect of (a) and (b) are essential for the well functioning of
6456d8
TIFFPrintDirectory, no checks are realized neither by the callee nor
6456d8
by TIFFPrintDirectory itself. Hence, following scenarios might happen
6456d8
and trigger the NULL pointer dereference:
6456d8
6456d8
(1) TIFF File of photometric type 4 or more has illegal Transfer
6456d8
    Function field.
6456d8
6456d8
(2) TIFF File has photometric type 3 or less and defines a
6456d8
    SamplesPerPixel field such that SamplesPerPixel > Color Channels
6456d8
    without defining all extra samples in the ExtraSamples fields.
6456d8
6456d8
In this patch, we address both issues with respect of the following
6456d8
principles:
6456d8
6456d8
(A) In the case of (1), the defined transfer table should be printed
6456d8
    safely even if it isn't 'legal'. This allows us to avoid expensive
6456d8
    checks in TIFFPrintDirectory. Also, it is quite possible that
6456d8
    an alternative photometric type would be developed (not part of the
6456d8
    standard) and would allow definition of Transfer Table. We want
6456d8
    libtiff to be able to handle this scenario out of the box.
6456d8
6456d8
(B) In the case of (2), the transfer table should be printed at its
6456d8
    right size, that is if TIFF file has photometric type Palette
6456d8
    then the transfer table should have one row and not three, even
6456d8
    if two extra samples are declared.
6456d8
6456d8
In order to fulfill (A) we simply add a new 'i < 3' end condition to
6456d8
the broken TIFFPrintDirectory loop. This makes sure that in any case
6456d8
where (b) would be respected but not (a), everything stays fine.
6456d8
6456d8
(B) is fulfilled by the loop condition
6456d8
'i < td->td_samplesperpixel - td->td_extrasamples'. This is enough as
6456d8
long as (b) is respected.
6456d8
6456d8
Naturally, we also make sure (b) is respected. This is done in the
6456d8
TIFFReadDirectory function by making sure any non-color channel is
6456d8
counted in ExtraSamples.
6456d8
6456d8
This commit addresses CVE-2018-7456.
6456d8
---
6456d8
 libtiff/tif_dirread.c | 61 +++++++++++++++++++++++++++++++++++++++++++
6456d8
 libtiff/tif_print.c   |  2 +-
6456d8
 libtiff/tif_unix.c    |  9 +++++++
6456d8
 libtiff/tiffio.h      |  1 +
6456d8
 4 files changed, 72 insertions(+), 1 deletion(-)
6456d8
6456d8
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
6456d8
index 0a9484d..8dc40b5 100644
6456d8
--- a/libtiff/tif_dirread.c
6456d8
+++ b/libtiff/tif_dirread.c
6456d8
@@ -65,6 +65,35 @@ static	int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);
6456d8
 static	int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);
6456d8
 static	int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);
6456d8
 static	void ChopUpSingleUncompressedStrip(TIFF*);
6456d8
+static	int _TIFFGetMaxColorChannels(uint16 photometric);
6456d8
+
6456d8
+/*
6456d8
+ * Return the maximum number of color channels specified for a given photometric
6456d8
+ * type. 0 is returned if photometric type isn't supported or no default value
6456d8
+ * is defined by the specification.
6456d8
+ */
6456d8
+static int _TIFFGetMaxColorChannels( uint16 photometric )
6456d8
+{
6456d8
+    switch (photometric) {
6456d8
+	case PHOTOMETRIC_PALETTE:
6456d8
+	case PHOTOMETRIC_MINISWHITE:
6456d8
+	case PHOTOMETRIC_MINISBLACK:
6456d8
+            return 1;
6456d8
+	case PHOTOMETRIC_YCBCR:
6456d8
+	case PHOTOMETRIC_RGB:
6456d8
+	case PHOTOMETRIC_CIELAB:
6456d8
+            return 3;
6456d8
+	case PHOTOMETRIC_SEPARATED:
6456d8
+	case PHOTOMETRIC_MASK:
6456d8
+            return 4;
6456d8
+	case PHOTOMETRIC_LOGL:
6456d8
+	case PHOTOMETRIC_LOGLUV:
6456d8
+	case PHOTOMETRIC_ITULAB:
6456d8
+	case PHOTOMETRIC_ICCLAB:
6456d8
+	default:
6456d8
+            return 0;
6456d8
+    }
6456d8
+}
6456d8
 
6456d8
 /*
6456d8
  * Read the next TIFF directory from a file and convert it to the internal
6456d8
@@ -86,6 +115,7 @@ TIFFReadDirectory(TIFF* tif)
6456d8
 	uint16 previous_tag = 0;
6456d8
 	int diroutoforderwarning = 0, compressionknown = 0;
6456d8
 	int haveunknowntags = 0;
6456d8
+	int color_channels;
6456d8
 
6456d8
 	tif->tif_diroff = tif->tif_nextdiroff;
6456d8
 	/*
6456d8
@@ -617,6 +647,37 @@ TIFFReadDirectory(TIFF* tif)
6456d8
 			}
6456d8
 		}
6456d8
 	}
6456d8
+
6456d8
+	/*
6456d8
+	 * Make sure all non-color channels are extrasamples.
6456d8
+	 * If it's not the case, define them as such.
6456d8
+	 */
6456d8
+        color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric);
6456d8
+        if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) {
6456d8
+                uint16 old_extrasamples;
6456d8
+                uint16 *new_sampleinfo;
6456d8
+
6456d8
+                TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related "
6456d8
+                    "color channels and ExtraSamples doesn't match SamplesPerPixel. "
6456d8
+                    "Defining non-color channels as ExtraSamples.");
6456d8
+
6456d8
+                old_extrasamples = tif->tif_dir.td_extrasamples;
6456d8
+                tif->tif_dir.td_extrasamples = (tif->tif_dir.td_samplesperpixel - color_channels);
6456d8
+
6456d8
+                // sampleinfo should contain information relative to these new extra samples
6456d8
+                new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16));
6456d8
+                if (!new_sampleinfo) {
6456d8
+                    TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for "
6456d8
+                                "temporary new sampleinfo array (%d 16 bit elements)",
6456d8
+                                tif->tif_dir.td_extrasamples);
6456d8
+                    goto bad;
6456d8
+                }
6456d8
+
6456d8
+                memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16));
6456d8
+                _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples);
6456d8
+                _TIFFfree(new_sampleinfo);
6456d8
+        }
6456d8
+
6456d8
 	/*
6456d8
 	 * Verify Palette image has a Colormap.
6456d8
 	 */
6456d8
diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c
6456d8
index 0f6ea01..1ec4f26 100644
6456d8
--- a/libtiff/tif_print.c
6456d8
+++ b/libtiff/tif_print.c
6456d8
@@ -503,7 +503,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
6456d8
 			for (l = 0; l < n; l++) {
6456d8
 				fprintf(fd, "    %2lu: %5u",
6456d8
 				    l, td->td_transferfunction[0][l]);
6456d8
-				for (i = 1; i < td->td_samplesperpixel; i++)
6456d8
+				for (i = 1; i < td->td_samplesperpixel - td->td_extrasamples && i < 3; i++)
6456d8
 					fprintf(fd, " %5u",
6456d8
 					    td->td_transferfunction[i][l]);
6456d8
 				fputc('\n', fd);
6456d8
diff --git a/libtiff/tif_unix.c b/libtiff/tif_unix.c
6456d8
index b73e80d..5d29040 100644
6456d8
--- a/libtiff/tif_unix.c
6456d8
+++ b/libtiff/tif_unix.c
6456d8
@@ -241,6 +241,15 @@ _TIFFmalloc(tsize_t s)
6456d8
 	return (malloc((size_t) s));
6456d8
 }
6456d8
 
6456d8
+void*
6456d8
+_TIFFcalloc(tsize_t nmemb, tsize_t siz)
6456d8
+{
6456d8
+    if( nmemb == 0 || siz == 0 )
6456d8
+        return ((void *) NULL);
6456d8
+
6456d8
+    return calloc((size_t) nmemb, (size_t)siz);
6456d8
+}
6456d8
+
6456d8
 void
6456d8
 _TIFFfree(tdata_t p)
6456d8
 {
6456d8
diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h
6456d8
index 06ec25c..3cf8e75 100644
6456d8
--- a/libtiff/tiffio.h
6456d8
+++ b/libtiff/tiffio.h
6456d8
@@ -281,6 +281,7 @@ extern	TIFFCodec* TIFFGetConfiguredCODECs(void);
6456d8
  */
6456d8
 
6456d8
 extern	tdata_t _TIFFmalloc(tsize_t);
6456d8
+extern	tdata_t _TIFFcalloc(tsize_t, tsize_t);
6456d8
 extern	tdata_t _TIFFrealloc(tdata_t, tsize_t);
6456d8
 extern	void _TIFFmemset(tdata_t, int, tsize_t);
6456d8
 extern	void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t);
6456d8
-- 
6456d8
2.17.0
6456d8