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

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