|  | From aaab5c3c9d2a2c6984f23ccbc79702610439bc65 Mon Sep 17 00:00:00 2001 | 
|  | From: erouault <erouault> | 
|  | Date: Sun, 27 Dec 2015 16:25:11 +0000 | 
|  | Subject: [PATCH] * libtiff/tif_luv.c: fix potential out-of-bound writes in | 
|  | decode functions in non debug builds by replacing assert()s by regular if | 
|  | checks (bugzilla #2522). Fix potential out-of-bound reads in case of short | 
|  | input data. | 
|  |  | 
|  | --- | 
|  | ChangeLog         |  7 +++++++ | 
|  | libtiff/tif_luv.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- | 
|  | 2 files changed, 51 insertions(+), 11 deletions(-) | 
|  |  | 
|  | Index: tiff-4.0.3/libtiff/tif_luv.c | 
|  | =================================================================== | 
|  | --- tiff-4.0.3.orig/libtiff/tif_luv.c	2016-03-23 10:13:56.868540963 -0400 | 
|  | +++ tiff-4.0.3/libtiff/tif_luv.c	2016-03-23 10:13:56.864540914 -0400 | 
|  | @@ -202,7 +202,11 @@ | 
|  | if (sp->user_datafmt == SGILOGDATAFMT_16BIT) | 
|  | tp = (int16*) op; | 
|  | else { | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | tp = (int16*) sp->tbuf; | 
|  | } | 
|  | _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); | 
|  | @@ -211,9 +215,11 @@ | 
|  | cc = tif->tif_rawcc; | 
|  | /* get each byte string */ | 
|  | for (shft = 2*8; (shft -= 8) >= 0; ) { | 
|  | -		for (i = 0; i < npixels && cc > 0; ) | 
|  | +		for (i = 0; i < npixels && cc > 0; ) { | 
|  | if (*bp >= 128) {		/* run */ | 
|  | -				rc = *bp++ + (2-128);   /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ | 
|  | +				if( cc < 2 ) | 
|  | +					break; | 
|  | +				rc = *bp++ + (2-128); | 
|  | b = (int16)(*bp++ << shft); | 
|  | cc -= 2; | 
|  | while (rc-- && i < npixels) | 
|  | @@ -223,6 +229,7 @@ | 
|  | while (--cc && rc-- && i < npixels) | 
|  | tp[i++] |= (int16)*bp++ << shft; | 
|  | } | 
|  | +		} | 
|  | if (i != npixels) { | 
|  | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | 
|  | TIFFErrorExt(tif->tif_clientdata, module, | 
|  | @@ -268,13 +275,17 @@ | 
|  | if (sp->user_datafmt == SGILOGDATAFMT_RAW) | 
|  | tp = (uint32 *)op; | 
|  | else { | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | tp = (uint32 *) sp->tbuf; | 
|  | } | 
|  | /* copy to array of uint32 */ | 
|  | bp = (unsigned char*) tif->tif_rawcp; | 
|  | cc = tif->tif_rawcc; | 
|  | -	for (i = 0; i < npixels && cc > 0; i++) { | 
|  | +	for (i = 0; i < npixels && cc >= 3; i++) { | 
|  | tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; | 
|  | bp += 3; | 
|  | cc -= 3; | 
|  | @@ -325,7 +336,11 @@ | 
|  | if (sp->user_datafmt == SGILOGDATAFMT_RAW) | 
|  | tp = (uint32*) op; | 
|  | else { | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | tp = (uint32*) sp->tbuf; | 
|  | } | 
|  | _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); | 
|  | @@ -334,11 +349,13 @@ | 
|  | cc = tif->tif_rawcc; | 
|  | /* get each byte string */ | 
|  | for (shft = 4*8; (shft -= 8) >= 0; ) { | 
|  | -		for (i = 0; i < npixels && cc > 0; ) | 
|  | +		for (i = 0; i < npixels && cc > 0; ) { | 
|  | if (*bp >= 128) {		/* run */ | 
|  | +				if( cc < 2 ) | 
|  | +					break; | 
|  | rc = *bp++ + (2-128); | 
|  | b = (uint32)*bp++ << shft; | 
|  | -				cc -= 2;                /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ | 
|  | +				cc -= 2; | 
|  | while (rc-- && i < npixels) | 
|  | tp[i++] |= b; | 
|  | } else {			/* non-run */ | 
|  | @@ -346,6 +363,7 @@ | 
|  | while (--cc && rc-- && i < npixels) | 
|  | tp[i++] |= (uint32)*bp++ << shft; | 
|  | } | 
|  | +		} | 
|  | if (i != npixels) { | 
|  | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | 
|  | TIFFErrorExt(tif->tif_clientdata, module, | 
|  | @@ -407,6 +425,7 @@ | 
|  | static int | 
|  | LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) | 
|  | { | 
|  | +	static const char module[] = "LogL16Encode"; | 
|  | LogLuvState* sp = EncoderState(tif); | 
|  | int shft; | 
|  | tmsize_t i; | 
|  | @@ -427,7 +446,11 @@ | 
|  | tp = (int16*) bp; | 
|  | else { | 
|  | tp = (int16*) sp->tbuf; | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | (*sp->tfunc)(sp, bp, npixels); | 
|  | } | 
|  | /* compress each byte string */ | 
|  | @@ -500,6 +523,7 @@ | 
|  | static int | 
|  | LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) | 
|  | { | 
|  | +	static const char module[] = "LogLuvEncode24"; | 
|  | LogLuvState* sp = EncoderState(tif); | 
|  | tmsize_t i; | 
|  | tmsize_t npixels; | 
|  | @@ -515,7 +539,11 @@ | 
|  | tp = (uint32*) bp; | 
|  | else { | 
|  | tp = (uint32*) sp->tbuf; | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | (*sp->tfunc)(sp, bp, npixels); | 
|  | } | 
|  | /* write out encoded pixels */ | 
|  | @@ -547,6 +575,7 @@ | 
|  | static int | 
|  | LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) | 
|  | { | 
|  | +	static const char module[] = "LogLuvEncode32"; | 
|  | LogLuvState* sp = EncoderState(tif); | 
|  | int shft; | 
|  | tmsize_t i; | 
|  | @@ -568,7 +597,11 @@ | 
|  | tp = (uint32*) bp; | 
|  | else { | 
|  | tp = (uint32*) sp->tbuf; | 
|  | -		assert(sp->tbuflen >= npixels); | 
|  | +		if(sp->tbuflen < npixels) { | 
|  | +			TIFFErrorExt(tif->tif_clientdata, module, | 
|  | +						 "Translation buffer too short"); | 
|  | +			return (0); | 
|  | +		} | 
|  | (*sp->tfunc)(sp, bp, npixels); | 
|  | } | 
|  | /* compress each byte string */ |