libtiff: Merge branch 'predictor_2_64bit' into 'master'

https://github.com/libsdl-org/libtiff/commit/f9e12f146a80babab2d1cfab50fa14acf765ef2a

From b0456acbba36927eeb2f937f4abed66deab4a029 Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Wed, 9 Feb 2022 21:53:39 +0100
Subject: [PATCH] Predictor 2 (horizontal differenciation): support 64-bit

There's no reason not to support 64-bit. The TIFF 6 specification
doesn't say anything about that (and even mention 4-bit, which we don't
support)
---
 libtiff/tif_predict.c                         |  90 +++++++++++++++++-
 test/CMakeLists.txt                           |   2 +
 test/Makefile.am                              |   2 +
 .../images/test_float64_predictor2_be_lzw.tif | Bin 0 -> 872 bytes
 .../images/test_float64_predictor2_le_lzw.tif | Bin 0 -> 887 bytes
 5 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 test/images/test_float64_predictor2_be_lzw.tif
 create mode 100644 test/images/test_float64_predictor2_le_lzw.tif

diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c
index 4aa4af69..ffe7133c 100644
--- a/libtiff/tif_predict.c
+++ b/libtiff/tif_predict.c
@@ -35,13 +35,17 @@
 static int horAcc8(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int horAcc16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int horAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int horAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int swabHorAcc16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int swabHorAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int swabHorAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int horDiff8(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int horDiff16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int horDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int horDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int swabHorDiff16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int swabHorDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int swabHorDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int fpAcc(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int fpDiff(TIFF* tif, uint8_t* cp0, tmsize_t cc);
 static int PredictorDecodeRow(TIFF* tif, uint8_t* op0, tmsize_t occ0, uint16_t s);
@@ -64,7 +68,8 @@ PredictorSetup(TIFF* tif)
 		case PREDICTOR_HORIZONTAL:
 			if (td->td_bitspersample != 8
 			    && td->td_bitspersample != 16
-			    && td->td_bitspersample != 32) {
+			    && td->td_bitspersample != 32
+			    && td->td_bitspersample != 64) {
 				TIFFErrorExt(tif->tif_clientdata, module,
 				    "Horizontal differencing \"Predictor\" not supported with %"PRIu16"-bit samples",
 				    td->td_bitspersample);
@@ -126,6 +131,7 @@ PredictorSetupDecode(TIFF* tif)
 			case 8:  sp->decodepfunc = horAcc8; break;
 			case 16: sp->decodepfunc = horAcc16; break;
 			case 32: sp->decodepfunc = horAcc32; break;
+			case 64: sp->decodepfunc = horAcc64; break;
 		}
 		/*
 		 * Override default decoding method with one that does the
@@ -155,6 +161,9 @@ PredictorSetupDecode(TIFF* tif)
             } else if (sp->decodepfunc == horAcc32) {
 				sp->decodepfunc = swabHorAcc32;
 				tif->tif_postdecode = _TIFFNoPostDecode;
+			} else if (sp->decodepfunc == horAcc64) {
+				sp->decodepfunc = swabHorAcc64;
+				tif->tif_postdecode = _TIFFNoPostDecode;
             }
 		}
 	}
@@ -205,6 +214,7 @@ PredictorSetupEncode(TIFF* tif)
 			case 8:  sp->encodepfunc = horDiff8; break;
 			case 16: sp->encodepfunc = horDiff16; break;
 			case 32: sp->encodepfunc = horDiff32; break;
+			case 64: sp->encodepfunc = horDiff64; break;
 		}
 		/*
 		 * Override default encoding method with one that does the
@@ -234,6 +244,9 @@ PredictorSetupEncode(TIFF* tif)
                     } else if (sp->encodepfunc == horDiff32) {
                             sp->encodepfunc = swabHorDiff32;
                             tif->tif_postdecode = _TIFFNoPostDecode;
+                    } else if (sp->encodepfunc == horDiff64) {
+                            sp->encodepfunc = swabHorDiff64;
+                            tif->tif_postdecode = _TIFFNoPostDecode;
                     }
                 }
         }
@@ -403,6 +416,41 @@ horAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc)
 	return 1;
 }
 
+static int
+swabHorAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+	uint64_t* wp = (uint64_t*) cp0;
+	tmsize_t wc = cc / 8;
+
+	TIFFSwabArrayOfLong8(wp, wc);
+	return horAcc64(tif, cp0, cc);
+}
+
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static int
+horAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+	tmsize_t stride = PredictorState(tif)->stride;
+	uint64_t* wp = (uint64_t*) cp0;
+	tmsize_t wc = cc / 8;
+
+	if ((cc % (8 * stride)) != 0)
+	{
+		TIFFErrorExt(tif->tif_clientdata, "horAcc64",
+		             "%s", "cc%(8*stride))!=0");
+		return 0;
+	}
+
+	if (wc > stride) {
+		wc -= stride;
+		do {
+			REPEAT4(stride, wp[stride] += wp[0]; wp++)
+			wc -= stride;
+		} while (wc > 0);
+	}
+	return 1;
+}
+
 /*
  * Floating point predictor accumulation routine.
  */
@@ -638,6 +686,46 @@ swabHorDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc)
     return 1;
 }
 
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static int
+horDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+	TIFFPredictorState* sp = PredictorState(tif);
+	tmsize_t stride = sp->stride;
+	uint64_t *wp = (uint64_t*) cp0;
+	tmsize_t wc = cc/8;
+
+	if ((cc % (8 * stride)) != 0)
+	{
+		TIFFErrorExt(tif->tif_clientdata, "horDiff64",
+		             "%s", "(cc%(8*stride))!=0");
+		return 0;
+	}
+
+	if (wc > stride) {
+		wc -= stride;
+		wp += wc - 1;
+		do {
+			REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+			wc -= stride;
+		} while (wc > 0);
+	}
+	return 1;
+}
+
+static int
+swabHorDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+    uint64_t* wp = (uint64_t*) cp0;
+    tmsize_t wc = cc / 8;
+
+    if (!horDiff64(tif, cp0, cc))
+        return 0;
+
+    TIFFSwabArrayOfLong8(wp, wc);
+    return 1;
+}
+
 /*
  * Floating point predictor differencing routine.
  */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3336b58c..1bdb283e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -356,6 +356,8 @@ add_convert_test_multi(tiffcp thumbnail "" thumbnail "-c g3:1d" "" ""
                        "images/miniswhite-1c-1b.tiff"    FALSE)
 add_convert_test(tiffcp   none       "-c none"       "images/quad-lzw-compat.tiff" FALSE)
 add_convert_test(tiffcp   noner1     "-c none -r 1"  "images/lzw-single-strip.tiff" FALSE)
+add_convert_test(tiffcp   float64_lzw_2_le "-c lzw:2       "images/test_float64_predictor2_le_lzw.tif" FALSE)
+add_convert_test(tiffcp   float64_lzw_2_be "-c lzw:2       "images/test_float64_predictor2_be_lzw.tif" FALSE)
 
 # tiffdump
 add_reader_test(tiffdump "" "images/miniswhite-1c-1b.tiff")
diff --git a/test/Makefile.am b/test/Makefile.am
index cb338884..6c1bae62 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -199,6 +199,8 @@ PNMIMAGES = \
 IMAGES_EXTRA_DIST = \
 	images/README.txt \
 	images/miniswhite-1c-1b.g3 \
+	images/test_float64_predictor2_le_lzw.tif \
+	images/test_float64_predictor2_be_lzw.tif \
 	$(PNMIMAGES) \
 	$(TIFFIMAGES)
 
diff --git a/test/images/test_float64_predictor2_be_lzw.tif b/test/images/test_float64_predictor2_be_lzw.tif
new file mode 100644
index 0000000000000000000000000000000000000000..7cbbae148974575b57d7055789ee62c01f585fcb
GIT binary patch
literal 872
zcmebEWzb?^VBlcjVPs%n2C^6#M1TY%5}OIib^wYqL)olAHXD=;)W|5vzyj9Gz%Y+d
z6iHkR$_AM!4pYN)ictnhjV+YT1XL3YWrJJ-1Pub*J`5~kJS@#l4hA0He}6c%9CRo+
z(G$YJ*tP%u$BZYD|9*A2IBfLLsdMI>csy|v#~LN2|Mjj7mmFBKv>fz&83ZkBHYw|M
zoL4QXFpxc{U&Eog+5PvkPSyop%hs>hAUEUR@}ti~HL@RV;+o~B9-<MFX0E>`O6h=C
zs+G3!^nI_*Jav~z{pt3~p782SRkA3fTmFYhjGc^GTjC1>vzL@5`p<CPVA0X%_kPlz
z%i1@%V~w7Q9-F`;QN@$`Tdc?X&G#L(MWNGL9_LRC(3K1K>Nxa#$J(WR#`6zJUXk>g
zVx4<*zL(~#JNv%HpSkgV>HDY?(&7u&9&NN_@40jFaNEnDe=7CXcR!o-?2&1XzYxFA
zm*l+x^Ha>;a?NEd7s$$g_iFZrb5+llS!x)4`Devpz_Lt!P1A>S)&jzJnznK3$aU;G
z`AUavPv^=f|D8H_>{-3BFKRQ_g0+|4Gj2Uo9kW)G>(pXyHD4EBu?-mp4F+5KG~cah
z<VvZVwwbTm=<Xr@EnTOMozI>%|KzI2u5w4;Z&p~Pw0`xE-^V7Mno;c*6eY~MbR+X`
zWsga#jJb~o%3L*Z7D%pCbzOd{gh~6u%YRizgsc9nTJ@%-sHuZl`yh*dFw=eUg{Py8
zbv!#(NZJNuuKB65W6Nr#t`nM7cRCt_FMj9SuxU}Y*Wyl-OH)s6oRw{+vF1v{d2It5
zUF{1(#fz@0eSB*3YGwPX>%zNUWPY2=;J3Eh-o>ywm1)7&P1&xt*&HXGmn?r{)xG^g
z=}g1TD{I;{{J5S3FvPr_A~fsVm8UGTcLdD*A9(Y!(PWN=%QveUT)yV=yuc}eWy_Zv
zeI-i_ubjMdrZzf3<xI`_jln;DF8D0uRk_?Dbg%0MF=wBxXO2JJ)*n-Nm8WZW#_FK9
z`6fP`3927*Kk7aa%-tH7F0}P@*Ym8VJmYAdGS@k4w*69Vzg_4Wvf$}2llx1<#Il4M
F8UWR}Up4>$

literal 0
HcmV?d00001

diff --git a/test/images/test_float64_predictor2_le_lzw.tif b/test/images/test_float64_predictor2_le_lzw.tif
new file mode 100644
index 0000000000000000000000000000000000000000..3dd57a5491ea51187543f801ecdff16b1c36b98c
GIT binary patch
literal 887
zcmebD)MDUZU|`^3U|?isU<9&6fS3`9%>-pT0L7W1Y*rwf4ax@T5oBZm>zxN=iz11O
zLD?WP#i43$GBGg7AgQs1vVp=3!B93ckPQM23<?2ij2Vs0jg5)|4m>&x4t4eqa~Nc-
zbeY-?&;O{gr;N>^)?FcoLC4BbsmU|>;!hqcQNDUFpm$87%!TzF9}0S!Y!la?do;1A
zBD#T}Pry#ihl{25vk^mZYVk{1xpu?OW2uFgShdu++6~kVtwi*;a?C!&A=(kU$vvq3
z@}uG?>37pp`)@BOl$f(>yTA(9_W=qb(QFNdehVe6<Jfu2*B;oonX64)lkc?C`w4r_
z^!=4zpRQxh#Cq!_pM!*9fb|jH-vOHsyfxax=4L&&DLe7!4(VolCV^1J$#+V>>F&C8
zW(r$v3^%)YLB8@8&wKyN177<4x*f$Y=ks+%tnN;pP6lDIich^V7ufc7-(<*nTCY*p
zwp#7^gO`)@bXUJ=(mEad<wgS|^BMs?e<`semg^q5J+bh+<nv|*?;*MG#y+bKJ+b4f
z(P6OT7ZT){!;m$h(%ECio^SR6PlDzim{44F+bHX1qs0CfLJtLOw0V+#7<f)(FxcC%
zp`m(Zf|IX`>WMA(T-F60jQoc$mDK#P=4yH<z3r?|x0L0F&PImyMyJ$`jNG?u)mAFl
z;IP9{*r@Kd@`fehR!SF^xSVw6x;?L3Lcq&zhYUB9n1GG&;hev|9Mzwm@~q2VG?PO(
zNY-}o`Id4`r{fF~$1i;Gc6D9Fe`U(T3m&3e?J~SZf^0^w|19<0zrv-QD{$4DNs~j*
zd{JBB6M81<pJS0~z|zYMtgen{Cj^zpZ3_51+5X&wzl<E3d3SZ@UR=s>($jy1Omc=o
z5bLUoCyS$Gi;cx{<l`5WddUahJRv<@Of57w>w&qK_lefq8Gr0`?>VuqEmtT>@|8K2
z&Aq030<-ii0dsd2W%HHdQ+6zTIPs27f?UZ`UY<*@dF=V`80d1A=>{bU1O#bGpKEt$
zXESZs6fA0>kgEAKsqryS=fNraw3=T^Efl%(xis~$$-eI|&bEp=KiWP`YT=o%W6RgR
K`l;;F&;S4%t}{9S

literal 0
HcmV?d00001