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

b03815
From de5385cd882a5ff0970f63f4d93da0cbc87230c2 Mon Sep 17 00:00:00 2001
b03815
From: =?UTF-8?q?Nikola=20Forr=C3=B3?= <nforro@redhat.com>
b03815
Date: Tue, 17 Apr 2018 18:42:09 +0200
b03815
Subject: [PATCH] Fix NULL pointer dereference in TIFFPrintDirectory
b03815
b03815
The TIFFPrintDirectory function relies on the following assumptions,
b03815
supposed to be guaranteed by the specification:
b03815
b03815
(a) A Transfer Function field is only present if the TIFF file has
b03815
    photometric type < 3.
b03815
b03815
(b) If SamplesPerPixel > Color Channels, then the ExtraSamples field
b03815
    has count SamplesPerPixel - (Color Channels) and contains
b03815
    information about supplementary channels.
b03815
b03815
While respect of (a) and (b) are essential for the well functioning of
b03815
TIFFPrintDirectory, no checks are realized neither by the callee nor
b03815
by TIFFPrintDirectory itself. Hence, following scenarios might happen
b03815
and trigger the NULL pointer dereference:
b03815
b03815
(1) TIFF File of photometric type 4 or more has illegal Transfer
b03815
    Function field.
b03815
b03815
(2) TIFF File has photometric type 3 or less and defines a
b03815
    SamplesPerPixel field such that SamplesPerPixel > Color Channels
b03815
    without defining all extra samples in the ExtraSamples fields.
b03815
b03815
In this patch, we address both issues with respect of the following
b03815
principles:
b03815
b03815
(A) In the case of (1), the defined transfer table should be printed
b03815
    safely even if it isn't 'legal'. This allows us to avoid expensive
b03815
    checks in TIFFPrintDirectory. Also, it is quite possible that
b03815
    an alternative photometric type would be developed (not part of the
b03815
    standard) and would allow definition of Transfer Table. We want
b03815
    libtiff to be able to handle this scenario out of the box.
b03815
b03815
(B) In the case of (2), the transfer table should be printed at its
b03815
    right size, that is if TIFF file has photometric type Palette
b03815
    then the transfer table should have one row and not three, even
b03815
    if two extra samples are declared.
b03815
b03815
In order to fulfill (A) we simply add a new 'i < 3' end condition to
b03815
the broken TIFFPrintDirectory loop. This makes sure that in any case
b03815
where (b) would be respected but not (a), everything stays fine.
b03815
b03815
(B) is fulfilled by the loop condition
b03815
'i < td->td_samplesperpixel - td->td_extrasamples'. This is enough as
b03815
long as (b) is respected.
b03815
b03815
Naturally, we also make sure (b) is respected. This is done in the
b03815
TIFFReadDirectory function by making sure any non-color channel is
b03815
counted in ExtraSamples.
b03815
b03815
This commit addresses CVE-2018-7456.
b03815
---
b03815
 libtiff/tif_dirread.c | 62 +++++++++++++++++++++++++++++++++++++++++++
b03815
 libtiff/tif_print.c   |  2 +-
b03815
 2 files changed, 63 insertions(+), 1 deletion(-)
b03815
b03815
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
b03815
index 5e62e81..80aaf8d 100644
b03815
--- a/libtiff/tif_dirread.c
b03815
+++ b/libtiff/tif_dirread.c
b03815
@@ -167,6 +167,7 @@ static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uin
b03815
 static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
b03815
 static void ChopUpSingleUncompressedStrip(TIFF*);
b03815
 static uint64 TIFFReadUInt64(const uint8 *value);
b03815
+static int _TIFFGetMaxColorChannels(uint16 photometric);
b03815
 
b03815
 static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount );
b03815
 
b03815
@@ -3506,6 +3507,35 @@ static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, c
b03815
 	}
b03815
 }
b03815
 
b03815
+/*
b03815
+ * Return the maximum number of color channels specified for a given photometric
b03815
+ * type. 0 is returned if photometric type isn't supported or no default value
b03815
+ * is defined by the specification.
b03815
+ */
b03815
+static int _TIFFGetMaxColorChannels( uint16 photometric )
b03815
+{
b03815
+    switch (photometric) {
b03815
+	case PHOTOMETRIC_PALETTE:
b03815
+	case PHOTOMETRIC_MINISWHITE:
b03815
+	case PHOTOMETRIC_MINISBLACK:
b03815
+            return 1;
b03815
+	case PHOTOMETRIC_YCBCR:
b03815
+	case PHOTOMETRIC_RGB:
b03815
+	case PHOTOMETRIC_CIELAB:
b03815
+            return 3;
b03815
+	case PHOTOMETRIC_SEPARATED:
b03815
+	case PHOTOMETRIC_MASK:
b03815
+            return 4;
b03815
+	case PHOTOMETRIC_LOGL:
b03815
+	case PHOTOMETRIC_LOGLUV:
b03815
+	case PHOTOMETRIC_CFA:
b03815
+	case PHOTOMETRIC_ITULAB:
b03815
+	case PHOTOMETRIC_ICCLAB:
b03815
+	default:
b03815
+            return 0;
b03815
+    }
b03815
+}
b03815
+
b03815
 /*
b03815
  * Read the next TIFF directory from a file and convert it to the internal
b03815
  * format. We read directories sequentially.
b03815
@@ -3522,6 +3552,7 @@ TIFFReadDirectory(TIFF* tif)
b03815
 	uint32 fii=FAILED_FII;
b03815
         toff_t nextdiroff;
b03815
     int bitspersample_read = FALSE;
b03815
+        int color_channels;
b03815
 
b03815
 	tif->tif_diroff=tif->tif_nextdiroff;
b03815
 	if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff))
b03815
@@ -4026,6 +4057,37 @@ TIFFReadDirectory(TIFF* tif)
b03815
 			}
b03815
 		}
b03815
 	}
b03815
+
b03815
+	/*
b03815
+	 * Make sure all non-color channels are extrasamples.
b03815
+	 * If it's not the case, define them as such.
b03815
+	 */
b03815
+        color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric);
b03815
+        if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) {
b03815
+                uint16 old_extrasamples;
b03815
+                uint16 *new_sampleinfo;
b03815
+
b03815
+                TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related "
b03815
+                    "color channels and ExtraSamples doesn't match SamplesPerPixel. "
b03815
+                    "Defining non-color channels as ExtraSamples.");
b03815
+
b03815
+                old_extrasamples = tif->tif_dir.td_extrasamples;
b03815
+                tif->tif_dir.td_extrasamples = (tif->tif_dir.td_samplesperpixel - color_channels);
b03815
+
b03815
+                // sampleinfo should contain information relative to these new extra samples
b03815
+                new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16));
b03815
+                if (!new_sampleinfo) {
b03815
+                    TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for "
b03815
+                                "temporary new sampleinfo array (%d 16 bit elements)",
b03815
+                                tif->tif_dir.td_extrasamples);
b03815
+                    goto bad;
b03815
+                }
b03815
+
b03815
+                memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16));
b03815
+                _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples);
b03815
+                _TIFFfree(new_sampleinfo);
b03815
+        }
b03815
+
b03815
 	/*
b03815
 	 * Verify Palette image has a Colormap.
b03815
 	 */
b03815
diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c
b03815
index 24d4b98..10a588e 100644
b03815
--- a/libtiff/tif_print.c
b03815
+++ b/libtiff/tif_print.c
b03815
@@ -546,7 +546,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
b03815
 				uint16 i;
b03815
 				fprintf(fd, "    %2ld: %5u",
b03815
 				    l, td->td_transferfunction[0][l]);
b03815
-				for (i = 1; i < td->td_samplesperpixel; i++)
b03815
+				for (i = 1; i < td->td_samplesperpixel - td->td_extrasamples && i < 3; i++)
b03815
 					fprintf(fd, " %5u",
b03815
 					    td->td_transferfunction[i][l]);
b03815
 				fputc('\n', fd);
b03815
-- 
b03815
2.17.0
b03815