Skip to content
This repository has been archived by the owner on Dec 1, 2017. It is now read-only.
Permalink
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
erouault committed Oct 31, 2016
1 parent ed9e07c commit 3ca657a
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 47 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
@@ -1,3 +1,12 @@
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
Expand Down
153 changes: 108 additions & 45 deletions libtiff/tif_predict.c
Expand Up @@ -34,18 +34,18 @@

#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);
Expand Down Expand Up @@ -273,13 +273,19 @@ PredictorSetupEncode(TIFF* tif)
/* - 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.
Expand Down Expand Up @@ -321,26 +327,32 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
} 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;
Expand All @@ -349,26 +361,32 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
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;
Expand All @@ -377,12 +395,13 @@ horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
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;
Expand All @@ -392,10 +411,15 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t 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] =
Expand All @@ -417,6 +441,7 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
}
}
_TIFFfree(tmp);
return 1;
}

/*
Expand All @@ -432,8 +457,7 @@ PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
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;
}
Expand All @@ -456,10 +480,16 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
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;
}
Expand All @@ -468,14 +498,19 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
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;
Expand Down Expand Up @@ -513,17 +548,23 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
} 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;
Expand All @@ -533,28 +574,36 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
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;
Expand All @@ -564,23 +613,26 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
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;
Expand All @@ -590,10 +642,14 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
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++) {
Expand All @@ -613,6 +669,7 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
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
Expand All @@ -625,7 +682,8 @@ PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
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);
}

Expand Down Expand Up @@ -660,7 +718,12 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)

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;
Expand Down

0 comments on commit 3ca657a

Please sign in to comment.