libtiff: Fix TransferFunction writing of only two transfer functions. (e3e87)

From e3e876d9631cbafb3c615396c075b54a2cb506dd Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Mon, 16 Oct 2023 23:10:32 +0300
Subject: [PATCH] Fix TransferFunction writing of only two transfer functions.

Author: Su_Laus <sulau@freenet.de>
Fri, 9 Jun 2023 16:41:19 +0200

The TIFFWriteDirectoryTagTransferfunction() function writes in some cases
only two transfer functions, although only exactly one or exactly three
transfer functions are allowed. This then leads to an error when reading.
 --> TIFFReadDirectory: Warning, Incorrect count for "TransferFunction"; tag ignored.

This MR corrects the behaviour of TIFFWriteDirectoryTagTransferfunction()
accordingly. Furthermore, a possible buffer overflow is avoided.

Origin: https://gitlab.com/libtiff/libtiff/-/merge_requests/502
https://gitlab.com/libtiff/libtiff/-/commit/7b1f03c386ef9870225f8be79c414b5715d4220a
---
 libtiff/tif_dirwrite.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c
index 53be7d8a..8743a3e3 100644
--- a/libtiff/tif_dirwrite.c
+++ b/libtiff/tif_dirwrite.c
@@ -2087,30 +2087,33 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir
 		(*ndir)++;
 		return(1);
 	}
+	/* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with
+	 *  (1 << BitsPerSample) * uint16 values.
+	 */
 	m=(1<<tif->tif_dir.td_bitspersample);
-	n=tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples;
+	n=(tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples) > 1 ? 3 : 1;
+	/* Check for proper number of transferfunctions */
+	for (p=0; p<n; p++)
+	{
+		if (tif->tif_dir.td_transferfunction[p] == NULL)
+		{
+			TIFFWarningExt(tif->tif_clientdata,module,
+				"Too few TransferFunctions provided. Tag not written to file");
+			return (1); /* Not an error; only tag is not written. */
+		}
+	}
 	/*
 	 * Check if the table can be written as a single column,
 	 * or if it must be written as 3 columns.  Note that we
 	 * write a 3-column tag if there are 2 samples/pixel and
 	 * a single column of data won't suffice--hmm.
 	 */
-	if (n>3)
-		n=3;
 	if (n==3)
 	{
-		if (tif->tif_dir.td_transferfunction[2] == NULL ||
-		    !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
-			n=2;
-	}
-	if (n==2)
-	{
-		if (tif->tif_dir.td_transferfunction[1] == NULL ||
+		if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)) &&
 		    !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
 			n=1;
 	}
-	if (n==0)
-		n=1;
 	o=_TIFFmalloc(n*m*sizeof(uint16));
 	if (o==NULL)
 	{