CVE-2016-9535: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: tif_predict.h and tif_predict.c in libtiff 4.0.6 have assertions that can lead to assertion failures in debug mode, or buffer overflows in release mode, when dealing with unusual tile size like YCbCr with subsampling. Reported as MSVR 35105, aka "Predictor heap-buffer-overflow."
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 9.8
Published: 2016-11-22T19:59Z
Repository: https://github.com/vadz/libtiff
Language: Other
Files changed: ChangeLog, libtiff/tif_predict.c, libtiff/tif_predict.h
Commit date: 2016-10-31 17:24:26 +0000
Commit message: * libtiff/tif_predict.h, libtiff/tif_predict.c:
Replace assertions by runtime checks to avoid assertions in debug mode,
or buffer overflows in release mode. Can happen when dealing with
unusual tile size like YCbCr with subsampling. Reported as MSVR 35105
by Axel Souchet	& Vishal Chauhan from the MSRC Vulnerabilities & Mitigations
team.

Diff: diff --git a/ChangeLog b/ChangeLog
index d33b47287..0379c3b7c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
+2016-10-31 Even Rouault <even.rouault at spatialys.com>
+
+	* libtiff/tif_predict.h, libtiff/tif_predict.c:
+	Replace assertions by runtime checks to avoid assertions in debug mode,
+	or buffer overflows in release mode. Can happen when dealing with
+	unusual tile size like YCbCr with subsampling. Reported as MSVR 35105
+	by Axel Souchet	& Vishal Chauhan from the MSRC Vulnerabilities & Mitigations
+	team.
+
 2016-10-26 Even Rouault <even.rouault at spatialys.com>
 
 	* tools/fax2tiff.c: fix segfault when specifying -r without
 	argument. Patch by Yuriy M. Kaminskiy.
 	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2572
diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c
index 555f2f9ce..b829259ae 100644
--- a/libtiff/tif_predict.c
+++ b/libtiff/tif_predict.c
@@ -32,22 +32,22 @@
 #include "tiffiop.h"
 #include "tif_predict.h"
 
 #define	PredictorState(tif)	((TIFFPredictorState*) (tif)->tif_data)
 
-static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
 static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
 static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
 static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
 static int PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s);
 
@@ -271,17 +271,23 @@ PredictorSetupEncode(TIFF* tif)
 /* - to avoid any undefined behaviour, we only operate on unsigned types */
 /*   since the behaviour of "overflows" is defined (wrap over) */
 /* - when storing into the byte stream, we explicitly mask with 0xff so */
 /*   as to make icc -check=conversions happy (not necessary by the standard) */
 
-static void
+static int
 horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 
 	unsigned char* cp = (unsigned char*) cp0;
-	assert((cc%stride)==0);
+    if((cc%stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc8",
+                     "%s", "(cc%stride)!=0");
+        return 0;
+    }
+
 	if (cc > stride) {
 		/*
 		 * Pipeline the most common cases.
 		 */
 		if (stride == 3)  {
@@ -319,85 +325,103 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 					(unsigned char) ((cp[stride] + *cp) & 0xff); cp++)
 				cc -= stride;
 			} while (cc>0);
 		}
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	uint16* wp = (uint16*) cp0;
 	tmsize_t wc = cc / 2;
 
         TIFFSwabArrayOfShort(wp, wc);
-        horAcc16(tif, cp0, cc);
+        return horAcc16(tif, cp0, cc);
 }
 
-static void
+static int
 horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint16* wp = (uint16*) cp0;
 	tmsize_t wc = cc / 2;
 
-	assert((cc%(2*stride))==0);
+    if((cc%(2*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc16",
+                     "%s", "cc%(2*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
 		do {
 			REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] + (unsigned int)wp[0]) & 0xffff); wp++)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	uint32* wp = (uint32*) cp0;
 	tmsize_t wc = cc / 4;
 
         TIFFSwabArrayOfLong(wp, wc);
-	horAcc32(tif, cp0, cc);
+	return horAcc32(tif, cp0, cc);
 }
 
-static void
+static int
 horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint32* wp = (uint32*) cp0;
 	tmsize_t wc = cc / 4;
 
-	assert((cc%(4*stride))==0);
+    if((cc%(4*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc32",
+                     "%s", "cc%(4*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.
  */
-static void
+static int
 fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint32 bps = tif->tif_dir.td_bitspersample / 8;
 	tmsize_t wc = cc / bps;
 	tmsize_t count = cc;
 	uint8 *cp = (uint8 *) cp0;
 	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
 
-	assert((cc%(bps*stride))==0);
+    if(cc%(bps*stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "fpAcc",
+                     "%s", "cc%(bps*stride))!=0");
+        return 0;
+    }
 
 	if (!tmp)
-		return;
+		return 0;
 
 	while (count > stride) {
 		REPEAT4(stride, cp[stride] =
                         (unsigned char) ((cp[stride] + cp[0]) & 0xff); cp++)
 		count -= stride;
@@ -415,10 +439,11 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 				tmp[(bps - byte - 1) * wc + count];
 			#endif
 		}
 	}
 	_TIFFfree(tmp);
+    return 1;
 }
 
 /*
  * Decode a scanline and apply the predictor routine.
  */
@@ -430,12 +455,11 @@ PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	assert(sp != NULL);
 	assert(sp->decoderow != NULL);
 	assert(sp->decodepfunc != NULL);  
 
 	if ((*sp->decoderow)(tif, op0, occ0, s)) {
-		(*sp->decodepfunc)(tif, op0, occ0);
-		return 1;
+		return (*sp->decodepfunc)(tif, op0, occ0);
 	} else
 		return 0;
 }
 
 /*
@@ -454,30 +478,41 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	assert(sp->decodetile != NULL);
 
 	if ((*sp->decodetile)(tif, op0, occ0, s)) {
 		tmsize_t rowsize = sp->rowsize;
 		assert(rowsize > 0);
-		assert((occ0%rowsize)==0);
+		if((occ0%rowsize) !=0)
+        {
+            TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile",
+                         "%s", "occ0%rowsize != 0");
+            return 0;
+        }
 		assert(sp->decodepfunc != NULL);
 		while (occ0 > 0) {
-			(*sp->decodepfunc)(tif, op0, rowsize);
+			if( !(*sp->decodepfunc)(tif, op0, rowsize) )
+                return 0;
 			occ0 -= rowsize;
 			op0 += rowsize;
 		}
 		return 1;
 	} else
 		return 0;
 }
 
-static void
+static int
 horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
 	unsigned char* cp = (unsigned char*) cp0;
 
-	assert((cc%stride)==0);
+    if((cc%stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
+                     "%s", "(cc%stride)!=0");
+        return 0;
+    }
 
 	if (cc > stride) {
 		cc -= stride;
 		/*
 		 * Pipeline the most common cases.
@@ -511,91 +546,112 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			do {
 				REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--)
 			} while ((cc -= stride) > 0);
 		}
 	}
+	return 1;
 }
 
-static void
+static int
 horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
 	uint16 *wp = (uint16*) cp0;
 	tmsize_t wc = cc/2;
 
-	assert((cc%(2*stride))==0);
+    if((cc%(2*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
+                     "%s", "(cc%(2*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
 		wp += wc - 1;
 		do {
 			REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] - (unsigned int)wp[0]) & 0xffff); wp--)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
     uint16* wp = (uint16*) cp0;
     tmsize_t wc = cc / 2;
 
-    horDiff16(tif, cp0, cc);
+    if( !horDiff16(tif, cp0, cc) )
+        return 0;
 
     TIFFSwabArrayOfShort(wp, wc);
+    return 1;
 }
 
-static void
+static int
 horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
 	uint32 *wp = (uint32*) cp0;
 	tmsize_t wc = cc/4;
 
-	assert((cc%(4*stride))==0);
+    if((cc%(4*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff32",
+                     "%s", "(cc%(4*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 void
+static int
 swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
     uint32* wp = (uint32*) cp0;
     tmsize_t wc = cc / 4;
 
-    horDiff32(tif, cp0, cc);
+    if( !horDiff32(tif, cp0, cc) )
+        return 0;
 
     TIFFSwabArrayOfLong(wp, wc);
+    return 1;
 }
 
 /*
  * Floating point predictor differencing routine.
  */
-static void
+static int
 fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint32 bps = tif->tif_dir.td_bitspersample / 8;
 	tmsize_t wc = cc / bps;
 	tmsize_t count;
 	uint8 *cp = (uint8 *) cp0;
 	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
 
-	assert((cc%(bps*stride))==0);
-
+    if((cc%(bps*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "fpDiff",
+                     "%s", "(cc%(bps*stride))!=0");
+        return 0;
+    }
 	if (!tmp)
-		return;
+		return 0;
 
 	_TIFFmemcpy(tmp, cp0, cc);
 	for (count = 0; count < wc; count++) {
 		uint32 byte;
 		for (byte = 0; byte < bps; byte++) {
@@ -611,10 +667,11 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 
 	cp = (uint8 *) cp0;
 	cp += cc - stride - 1;
 	for (count = cc; count > stride; count -= stride)
 		REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--)
+    return 1;
 }
 
 static int
 PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
@@ -623,11 +680,12 @@ PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	assert(sp != NULL);
 	assert(sp->encodepfunc != NULL);
 	assert(sp->encoderow != NULL);
 
 	/* XXX horizontal differencing alters user's data XXX */
-	(*sp->encodepfunc)(tif, bp, cc);
+	if( !(*sp->encodepfunc)(tif, bp, cc) )
+        return 0;
 	return (*sp->encoderow)(tif, bp, cc, s);
 }
 
 static int
 PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)
@@ -658,11 +716,16 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)
         memcpy( working_copy, bp0, cc0 );
         bp = working_copy;
 
 	rowsize = sp->rowsize;
 	assert(rowsize > 0);
-	assert((cc0%rowsize)==0);
+	if((cc0%rowsize)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile",
+                     "%s", "(cc0%rowsize)!=0");
+        return 0;
+    }
 	while (cc > 0) {
 		(*sp->encodepfunc)(tif, bp, rowsize);
 		cc -= rowsize;
 		bp += rowsize;
 	}
diff --git a/libtiff/tif_predict.h b/libtiff/tif_predict.h
index 91330ccec..9e485a4b8 100644
--- a/libtiff/tif_predict.h
+++ b/libtiff/tif_predict.h
@@ -28,10 +28,12 @@
 #define	_TIFFPREDICT_
 /*
  * ``Library-private'' Support for the Predictor Tag
  */
 
+typedef int (*TIFFEncodeDecodeMethod)(TIFF* tif, uint8* buf, tmsize_t size);
+
 /*
  * Codecs that want to support the Predictor tag must place
  * this structure first in their private state block so that
  * the predictor code can cast tif_data to find its state.
  */
@@ -41,16 +43,16 @@ typedef struct {
 	tmsize_t        rowsize;	/* tile/strip row size */
 
 	TIFFCodeMethod  encoderow;	/* parent codec encode/decode row */
 	TIFFCodeMethod  encodestrip;	/* parent codec encode/decode strip */
 	TIFFCodeMethod  encodetile;	/* parent codec encode/decode tile */ 
-	TIFFPostMethod  encodepfunc;	/* horizontal differencer */
+	TIFFEncodeDecodeMethod  encodepfunc;	/* horizontal differencer */
 
 	TIFFCodeMethod  decoderow;	/* parent codec encode/decode row */
 	TIFFCodeMethod  decodestrip;	/* parent codec encode/decode strip */
 	TIFFCodeMethod  decodetile;	/* parent codec encode/decode tile */ 
-	TIFFPostMethod  decodepfunc;	/* horizontal accumulator */
+	TIFFEncodeDecodeMethod  decodepfunc;	/* horizontal accumulator */
 
 	TIFFVGetMethod  vgetparent;	/* super-class method */
 	TIFFVSetMethod  vsetparent;	/* super-class method */
 	TIFFPrintMethod printdir;	/* super-class method */
 	TIFFBoolMethod  setupdecode;	/* super-class method */

Vulnerable code: static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
static void swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
static void swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
static void
	assert((cc%stride)==0);
static void
        horAcc16(tif, cp0, cc);
static void
	assert((cc%(2*stride))==0);
static void
	horAcc32(tif, cp0, cc);
static void
	assert((cc%(4*stride))==0);
static void
	assert((cc%(bps*stride))==0);
		return;
		(*sp->decodepfunc)(tif, op0, occ0);
		return 1;
		assert((occ0%rowsize)==0);
			(*sp->decodepfunc)(tif, op0, rowsize);
static void
	assert((cc%stride)==0);
static void
	assert((cc%(2*stride))==0);
static void
    horDiff16(tif, cp0, cc);
static void
	assert((cc%(4*stride))==0);
static void
    horDiff32(tif, cp0, cc);
static void
	assert((cc%(bps*stride))==0);

		return;
	(*sp->encodepfunc)(tif, bp, cc);
	assert((cc0%rowsize)==0);
	TIFFPostMethod  encodepfunc;	/* horizontal differencer */
	TIFFPostMethod  decodepfunc;	/* horizontal accumulator */
Fixed code: 2016-10-31 Even Rouault <even.rouault at spatialys.com>

	* libtiff/tif_predict.h, libtiff/tif_predict.c:
	Replace assertions by runtime checks to avoid assertions in debug mode,
	or buffer overflows in release mode. Can happen when dealing with
	unusual tile size like YCbCr with subsampling. Reported as MSVR 35105
	by Axel Souchet	& Vishal Chauhan from the MSRC Vulnerabilities & Mitigations
	team.

static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
static int
    if((cc%stride)!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horAcc8",
                     "%s", "(cc%stride)!=0");
        return 0;
    }

	return 1;
static int
        return horAcc16(tif, cp0, cc);
static int
    if((cc%(2*stride))!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horAcc16",
                     "%s", "cc%(2*stride))!=0");
        return 0;
    }
	return 1;
static int
	return horAcc32(tif, cp0, cc);
static int
    if((cc%(4*stride))!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horAcc32",
                     "%s", "cc%(4*stride))!=0");
        return 0;
    }
	return 1;
static int
    if(cc%(bps*stride)!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "fpAcc",
                     "%s", "cc%(bps*stride))!=0");
        return 0;
    }
		return 0;
    return 1;
		return (*sp->decodepfunc)(tif, op0, occ0);
		if((occ0%rowsize) !=0)
        {
            TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile",
                         "%s", "occ0%rowsize != 0");
            return 0;
        }
			if( !(*sp->decodepfunc)(tif, op0, rowsize) )
                return 0;
static int
    if((cc%stride)!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
                     "%s", "(cc%stride)!=0");
        return 0;
    }
	return 1;
static int
    if((cc%(2*stride))!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
                     "%s", "(cc%(2*stride))!=0");
        return 0;
    }
	return 1;
static int
    if( !horDiff16(tif, cp0, cc) )
        return 0;
    return 1;
static int
    if((cc%(4*stride))!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "horDiff32",
                     "%s", "(cc%(4*stride))!=0");
        return 0;
    }
	return 1;
static int
    if( !horDiff32(tif, cp0, cc) )
        return 0;
    return 1;
static int
    if((cc%(bps*stride))!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "fpDiff",
                     "%s", "(cc%(bps*stride))!=0");
        return 0;
    }
		return 0;
    return 1;
	if( !(*sp->encodepfunc)(tif, bp, cc) )
        return 0;
	if((cc0%rowsize)!=0)
    {
        TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile",
                     "%s", "(cc0%rowsize)!=0");
        return 0;
    }
typedef int (*TIFFEncodeDecodeMethod)(TIFF* tif, uint8* buf, tmsize_t size);

	TIFFEncodeDecodeMethod  encodepfunc;	/* horizontal differencer */
	TIFFEncodeDecodeMethod  decodepfunc;	/* horizontal accumulator */