CVE-2016-9535 (Other, published 2016-11-22T19:59Z)
Description: 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."
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-119 \u2014 Improper Restriction of Operations within the Bounds of a Memory Buffer
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.
Repository: https://github.com/vadz/libtiff
Files changed:
ChangeLog
libtiff/tif_predict.c
libtiff/tif_predict.h
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.


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 */