From: Robin Watts <Robin.Watts@artifex.com>
Date: Fri, 23 Jul 2021 16:35:21 +0900
Subject: Bug 703076: Fix buffer overrun in tiff decoder.

Harden tiff_expand_colormap against badly formed TIFFs.
Correctly allocate space, and avoid overreading. Skip any excess
input data.

Cherry-picked-from: http://git.ghostscript.com/?p=mupdf.git;a=commitdiff;h=2c4f11f8dcdbd18c35a65e58cc789be0e46012a8
---
 source/fitz/load-tiff.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/source/fitz/load-tiff.c b/source/fitz/load-tiff.c
index bb69e2f..40db0fe 100644
--- a/source/fitz/load-tiff.c
+++ b/source/fitz/load-tiff.c
@@ -236,6 +236,7 @@ tiff_expand_colormap(fz_context *ctx, struct tiff *tiff)
 	unsigned char *src, *dst;
 	unsigned int x, y;
 	unsigned int stride;
+	unsigned int srcstride;
 
 	/* colormap has first all red, then all green, then all blue values */
 	/* colormap values are 0..65535, bits is 4 or 8 */
@@ -253,41 +254,40 @@ tiff_expand_colormap(fz_context *ctx, struct tiff *tiff)
 	if (tiff->imagelength > UINT_MAX / tiff->imagewidth / (tiff->samplesperpixel + 2))
 		fz_throw(ctx, FZ_ERROR_GENERIC, "image too large");
 
-	stride = tiff->imagewidth * (tiff->samplesperpixel + 2) * 2;
+	srcstride = ((1 + tiff->extrasamples) * tiff->bitspersample + 7) & ~7;
+	if (tiff->stride < 0 || srcstride > (unsigned int)tiff->stride)
+		fz_throw(ctx, FZ_ERROR_GENERIC, "insufficient data for format");
+
+	stride = tiff->imagewidth * (3 + !!tiff->extrasamples) * 2;
 
 	samples = Memento_label(fz_malloc(ctx, stride * tiff->imagelength), "tiff_samples");
 
 	for (y = 0; y < tiff->imagelength; y++)
 	{
+		int s = 0;
 		src = tiff->samples + (unsigned int)(tiff->stride * y);
 		dst = samples + (unsigned int)(stride * y);
 
 		for (x = 0; x < tiff->imagewidth; x++)
 		{
+			int c = tiff_getcomp(src, s++, tiff->bitspersample);
+			*dst++ = tiff->colormap[c + 0] >> 8;
+			*dst++ = tiff->colormap[c + 0];
+			*dst++ = tiff->colormap[c + maxval] >> 8;
+			*dst++ = tiff->colormap[c + maxval];
+			*dst++ = tiff->colormap[c + maxval * 2] >> 8;
+			*dst++ = tiff->colormap[c + maxval * 2];
 			if (tiff->extrasamples)
 			{
-				int c = tiff_getcomp(src, x * 2, tiff->bitspersample);
-				int a = tiff_getcomp(src, x * 2 + 1, tiff->bitspersample);
-				*dst++ = tiff->colormap[c + 0] >> 8;
-				*dst++ = tiff->colormap[c + 0];
-				*dst++ = tiff->colormap[c + maxval] >> 8;
-				*dst++ = tiff->colormap[c + maxval];
-				*dst++ = tiff->colormap[c + maxval * 2] >> 8;
-				*dst++ = tiff->colormap[c + maxval * 2];
+				/* Assume the first is alpha, and skip the rest. */
+				int a = tiff_getcomp(src, s++, tiff->bitspersample);
 				if (tiff->bitspersample <= 16)
-					*dst++ = a << (16 - tiff->bitspersample);
+					a = a << (16 - tiff->bitspersample);
 				else
-					*dst++ = a >> (tiff->bitspersample - 16);
-			}
-			else
-			{
-				int c = tiff_getcomp(src, x, tiff->bitspersample);
-				*dst++ = tiff->colormap[c + 0] >> 8;
-				*dst++ = tiff->colormap[c + 0];
-				*dst++ = tiff->colormap[c + maxval] >> 8;
-				*dst++ = tiff->colormap[c + maxval];
-				*dst++ = tiff->colormap[c + maxval * 2] >> 8;
-				*dst++ = tiff->colormap[c + maxval * 2];
+					a = a >> (tiff->bitspersample - 16);
+				*dst++ = a >> 8;
+				*dst++ = a;
+				s += tiff->extrasamples-1;
 			}
 		}
 	}
