|
|
70f9f0 |
From 6c4480d2980dc61f3fcd4f43a499e69764133f1a Mon Sep 17 00:00:00 2001
|
|
|
70f9f0 |
From: =?UTF-8?q?Nikola=20Forr=C3=B3?= <nforro@redhat.com>
|
|
|
70f9f0 |
Date: Wed, 11 Jan 2017 12:50:33 +0100
|
|
|
70f9f0 |
Subject: [PATCH 1/5] Fix CVE-2016-9533, CVE-2016-9534, CVE-2016-9536,
|
|
|
70f9f0 |
CVE-2016-9537
|
|
|
70f9f0 |
|
|
|
70f9f0 |
---
|
|
|
70f9f0 |
libtiff/tif_pixarlog.c | 55 +++++++++++++++++++++-----------------------------
|
|
|
70f9f0 |
libtiff/tif_write.c | 7 +++++++
|
|
|
70f9f0 |
tools/thumbnail.c | 7 ++++++-
|
|
|
70f9f0 |
tools/tiff2pdf.c | 22 ++++++++++++++++++--
|
|
|
70f9f0 |
tools/tiffcrop.c | 31 ++++++++++++++++++++++++----
|
|
|
70f9f0 |
5 files changed, 83 insertions(+), 39 deletions(-)
|
|
|
70f9f0 |
|
|
|
70f9f0 |
diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c
|
|
|
70f9f0 |
index c961529..6128f2f 100644
|
|
|
70f9f0 |
--- a/libtiff/tif_pixarlog.c
|
|
|
70f9f0 |
+++ b/libtiff/tif_pixarlog.c
|
|
|
70f9f0 |
@@ -981,17 +981,14 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
|
|
|
70f9f0 |
a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
} else {
|
|
|
70f9f0 |
- ip += n - 1; /* point to last one */
|
|
|
70f9f0 |
- wp += n - 1; /* point to last one */
|
|
|
70f9f0 |
- n -= stride;
|
|
|
70f9f0 |
- while (n > 0) {
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
|
|
|
70f9f0 |
- wp[stride] -= wp[0];
|
|
|
70f9f0 |
- wp[stride] &= mask;
|
|
|
70f9f0 |
- wp--; ip--)
|
|
|
70f9f0 |
- n -= stride;
|
|
|
70f9f0 |
- }
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
|
|
|
70f9f0 |
+ REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp++; ip++)
|
|
|
70f9f0 |
+ n -= stride;
|
|
|
70f9f0 |
+ while (n > 0) {
|
|
|
70f9f0 |
+ REPEAT(stride,
|
|
|
70f9f0 |
+ wp[0] = (uint16)(((int32)CLAMP(ip[0])-(int32)CLAMP(ip[-stride])) & mask);
|
|
|
70f9f0 |
+ wp++; ip++)
|
|
|
70f9f0 |
+ n -= stride;
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
@@ -1034,17 +1031,14 @@ horizontalDifference16(unsigned short *ip, int n, int stride,
|
|
|
70f9f0 |
a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
} else {
|
|
|
70f9f0 |
- ip += n - 1; /* point to last one */
|
|
|
70f9f0 |
- wp += n - 1; /* point to last one */
|
|
|
70f9f0 |
+ REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
|
|
|
70f9f0 |
n -= stride;
|
|
|
70f9f0 |
while (n > 0) {
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = CLAMP(ip[0]);
|
|
|
70f9f0 |
- wp[stride] -= wp[0];
|
|
|
70f9f0 |
- wp[stride] &= mask;
|
|
|
70f9f0 |
- wp--; ip--)
|
|
|
70f9f0 |
- n -= stride;
|
|
|
70f9f0 |
- }
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
|
|
|
70f9f0 |
+ REPEAT(stride,
|
|
|
70f9f0 |
+ wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask);
|
|
|
70f9f0 |
+ wp++; ip++)
|
|
|
70f9f0 |
+ n -= stride;
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
@@ -1087,18 +1081,15 @@ horizontalDifference8(unsigned char *ip, int n, int stride,
|
|
|
70f9f0 |
ip += 4;
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
} else {
|
|
|
70f9f0 |
- wp += n + stride - 1; /* point to last one */
|
|
|
70f9f0 |
- ip += n + stride - 1; /* point to last one */
|
|
|
70f9f0 |
- n -= stride;
|
|
|
70f9f0 |
- while (n > 0) {
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = CLAMP(ip[0]);
|
|
|
70f9f0 |
- wp[stride] -= wp[0];
|
|
|
70f9f0 |
- wp[stride] &= mask;
|
|
|
70f9f0 |
- wp--; ip--)
|
|
|
70f9f0 |
- n -= stride;
|
|
|
70f9f0 |
- }
|
|
|
70f9f0 |
- REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
|
|
|
70f9f0 |
- }
|
|
|
70f9f0 |
+ REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
|
|
|
70f9f0 |
+ n -= stride;
|
|
|
70f9f0 |
+ while (n > 0) {
|
|
|
70f9f0 |
+ REPEAT(stride,
|
|
|
70f9f0 |
+ wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask);
|
|
|
70f9f0 |
+ wp++; ip++)
|
|
|
70f9f0 |
+ n -= stride;
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
|
|
|
70f9f0 |
diff --git a/libtiff/tif_write.c b/libtiff/tif_write.c
|
|
|
70f9f0 |
index 8792123..ce671af 100644
|
|
|
70f9f0 |
--- a/libtiff/tif_write.c
|
|
|
70f9f0 |
+++ b/libtiff/tif_write.c
|
|
|
70f9f0 |
@@ -742,7 +742,14 @@ TIFFFlushData1(TIFF* tif)
|
|
|
70f9f0 |
if (!TIFFAppendToStrip(tif,
|
|
|
70f9f0 |
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
|
|
|
70f9f0 |
tif->tif_rawdata, tif->tif_rawcc))
|
|
|
70f9f0 |
+ {
|
|
|
70f9f0 |
+ /* We update those variables even in case of error since there's */
|
|
|
70f9f0 |
+ /* code that doesn't really check the return code of this */
|
|
|
70f9f0 |
+ /* function */
|
|
|
70f9f0 |
+ tif->tif_rawcc = 0;
|
|
|
70f9f0 |
+ tif->tif_rawcp = tif->tif_rawdata;
|
|
|
70f9f0 |
return (0);
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
tif->tif_rawcc = 0;
|
|
|
70f9f0 |
tif->tif_rawcp = tif->tif_rawdata;
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
diff --git a/tools/thumbnail.c b/tools/thumbnail.c
|
|
|
70f9f0 |
index e14d290..9a9c439 100644
|
|
|
70f9f0 |
--- a/tools/thumbnail.c
|
|
|
70f9f0 |
+++ b/tools/thumbnail.c
|
|
|
70f9f0 |
@@ -587,12 +587,17 @@ generateThumbnail(TIFF* in, TIFF* out)
|
|
|
70f9f0 |
rowsize = TIFFScanlineSize(in);
|
|
|
70f9f0 |
rastersize = sh * rowsize;
|
|
|
70f9f0 |
fprintf(stderr, "rastersize=%u\n", (unsigned int)rastersize);
|
|
|
70f9f0 |
- raster = (unsigned char*)_TIFFmalloc(rastersize + 3);
|
|
|
70f9f0 |
+ /* +3 : add a few guard bytes since setrow() can read a bit */
|
|
|
70f9f0 |
+ /* outside buffer */
|
|
|
70f9f0 |
+ raster = (unsigned char*)_TIFFmalloc(rastersize+3);
|
|
|
70f9f0 |
if (!raster) {
|
|
|
70f9f0 |
TIFFError(TIFFFileName(in),
|
|
|
70f9f0 |
"Can't allocate space for raster buffer.");
|
|
|
70f9f0 |
return 0;
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
+ raster[rastersize] = 0;
|
|
|
70f9f0 |
+ raster[rastersize+1] = 0;
|
|
|
70f9f0 |
+ raster[rastersize+2] = 0;
|
|
|
70f9f0 |
rp = raster;
|
|
|
70f9f0 |
for (s = 0; s < ns; s++) {
|
|
|
70f9f0 |
(void) TIFFReadEncodedStrip(in, s, rp, -1);
|
|
|
70f9f0 |
diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c
|
|
|
70f9f0 |
index 2a64ec3..fbca305 100644
|
|
|
70f9f0 |
--- a/tools/tiff2pdf.c
|
|
|
70f9f0 |
+++ b/tools/tiff2pdf.c
|
|
|
70f9f0 |
@@ -285,7 +285,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t);
|
|
|
70f9f0 |
int t2p_process_ojpeg_tables(T2P*, TIFF*);
|
|
|
70f9f0 |
#endif
|
|
|
70f9f0 |
#ifdef JPEG_SUPPORT
|
|
|
70f9f0 |
-int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t*, tstrip_t, uint32);
|
|
|
70f9f0 |
+int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t, tsize_t*, tstrip_t, uint32);
|
|
|
70f9f0 |
#endif
|
|
|
70f9f0 |
void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32);
|
|
|
70f9f0 |
void t2p_write_advance_directory(T2P*, TIFF*);
|
|
|
70f9f0 |
@@ -2348,7 +2348,8 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){
|
|
|
70f9f0 |
if(!t2p_process_jpeg_strip(
|
|
|
70f9f0 |
stripbuffer,
|
|
|
70f9f0 |
&striplength,
|
|
|
70f9f0 |
- buffer,
|
|
|
70f9f0 |
+ buffer,
|
|
|
70f9f0 |
+ t2p->tiff_datasize,
|
|
|
70f9f0 |
&bufferoffset,
|
|
|
70f9f0 |
i,
|
|
|
70f9f0 |
t2p->tiff_length)){
|
|
|
70f9f0 |
@@ -3378,6 +3379,7 @@ int t2p_process_jpeg_strip(
|
|
|
70f9f0 |
unsigned char* strip,
|
|
|
70f9f0 |
tsize_t* striplength,
|
|
|
70f9f0 |
unsigned char* buffer,
|
|
|
70f9f0 |
+ tsize_t buffersize,
|
|
|
70f9f0 |
tsize_t* bufferoffset,
|
|
|
70f9f0 |
tstrip_t no,
|
|
|
70f9f0 |
uint32 height){
|
|
|
70f9f0 |
@@ -3412,6 +3414,8 @@ int t2p_process_jpeg_strip(
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
switch( strip[i] ){
|
|
|
70f9f0 |
case 0xd8: /* SOI - start of image */
|
|
|
70f9f0 |
+ if( *bufferoffset + 2 > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), 2);
|
|
|
70f9f0 |
*bufferoffset+=2;
|
|
|
70f9f0 |
break;
|
|
|
70f9f0 |
@@ -3421,12 +3425,18 @@ int t2p_process_jpeg_strip(
|
|
|
70f9f0 |
case 0xc9: /* SOF9 */
|
|
|
70f9f0 |
case 0xca: /* SOF10 */
|
|
|
70f9f0 |
if(no==0){
|
|
|
70f9f0 |
+ if( *bufferoffset + datalen + 2 + 6 > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
|
|
70f9f0 |
+ if( *bufferoffset + 9 >= buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
ncomp = buffer[*bufferoffset+9];
|
|
|
70f9f0 |
if (ncomp < 1 || ncomp > 4)
|
|
|
70f9f0 |
return(0);
|
|
|
70f9f0 |
v_samp=1;
|
|
|
70f9f0 |
h_samp=1;
|
|
|
70f9f0 |
+ if( *bufferoffset + 11 + 3*(ncomp-1) >= buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
for(j=0;j
|
|
|
70f9f0 |
uint16 samp = buffer[*bufferoffset+11+(3*j)];
|
|
|
70f9f0 |
if( (samp>>4) > h_samp)
|
|
|
70f9f0 |
@@ -3458,20 +3468,28 @@ int t2p_process_jpeg_strip(
|
|
|
70f9f0 |
break;
|
|
|
70f9f0 |
case 0xc4: /* DHT */
|
|
|
70f9f0 |
case 0xdb: /* DQT */
|
|
|
70f9f0 |
+ if( *bufferoffset + datalen + 2 > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
|
|
70f9f0 |
*bufferoffset+=datalen+2;
|
|
|
70f9f0 |
break;
|
|
|
70f9f0 |
case 0xda: /* SOS */
|
|
|
70f9f0 |
if(no==0){
|
|
|
70f9f0 |
+ if( *bufferoffset + datalen + 2 > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
|
|
70f9f0 |
*bufferoffset+=datalen+2;
|
|
|
70f9f0 |
} else {
|
|
|
70f9f0 |
+ if( *bufferoffset + 2 > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
buffer[(*bufferoffset)++]=0xff;
|
|
|
70f9f0 |
buffer[(*bufferoffset)++]=
|
|
|
70f9f0 |
(unsigned char)(0xd0 | ((no-1)%8));
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
i += datalen + 1;
|
|
|
70f9f0 |
/* copy remainder of strip */
|
|
|
70f9f0 |
+ if( *bufferoffset + *striplength - i > buffersize )
|
|
|
70f9f0 |
+ return(0);
|
|
|
70f9f0 |
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i]), *striplength - i);
|
|
|
70f9f0 |
*bufferoffset+= *striplength - i;
|
|
|
70f9f0 |
return(1);
|
|
|
70f9f0 |
diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
|
|
|
70f9f0 |
index f04e2eb..02c53cd 100644
|
|
|
70f9f0 |
--- a/tools/tiffcrop.c
|
|
|
70f9f0 |
+++ b/tools/tiffcrop.c
|
|
|
70f9f0 |
@@ -5744,7 +5744,8 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
|
|
|
70f9f0 |
{
|
|
|
70f9f0 |
uint32 i;
|
|
|
70f9f0 |
float xres = 0.0, yres = 0.0;
|
|
|
70f9f0 |
- uint16 nstrips = 0, ntiles = 0, planar = 0;
|
|
|
70f9f0 |
+ uint32 nstrips = 0, ntiles = 0;
|
|
|
70f9f0 |
+ uint16 planar = 0;
|
|
|
70f9f0 |
uint16 bps = 0, spp = 0, res_unit = 0;
|
|
|
70f9f0 |
uint16 orientation = 0;
|
|
|
70f9f0 |
uint16 input_compression = 0, input_photometric = 0;
|
|
|
70f9f0 |
@@ -6049,17 +6050,31 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
|
|
|
70f9f0 |
read_buff = *read_ptr;
|
|
|
70f9f0 |
+ /* +3 : add a few guard bytes since reverseSamples16bits() can read a bit */
|
|
|
70f9f0 |
+ /* outside buffer */
|
|
|
70f9f0 |
if (!read_buff)
|
|
|
70f9f0 |
- read_buff = (unsigned char *)_TIFFmalloc(buffsize);
|
|
|
70f9f0 |
+ {
|
|
|
70f9f0 |
+ if( buffsize > 0xFFFFFFFFU - 3 )
|
|
|
70f9f0 |
+ {
|
|
|
70f9f0 |
+ TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
|
|
|
70f9f0 |
+ return (-1);
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
+ read_buff = (unsigned char *)_TIFFmalloc(buffsize+3);
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
else
|
|
|
70f9f0 |
{
|
|
|
70f9f0 |
if (prev_readsize < buffsize)
|
|
|
70f9f0 |
+ {
|
|
|
70f9f0 |
+ if( buffsize > 0xFFFFFFFFU - 3 )
|
|
|
70f9f0 |
{
|
|
|
70f9f0 |
- new_buff = _TIFFrealloc(read_buff, buffsize);
|
|
|
70f9f0 |
+ TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
|
|
|
70f9f0 |
+ return (-1);
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
+ new_buff = _TIFFrealloc(read_buff, buffsize+3);
|
|
|
70f9f0 |
if (!new_buff)
|
|
|
70f9f0 |
{
|
|
|
70f9f0 |
free (read_buff);
|
|
|
70f9f0 |
- read_buff = (unsigned char *)_TIFFmalloc(buffsize);
|
|
|
70f9f0 |
+ read_buff = (unsigned char *)_TIFFmalloc(buffsize+3);
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
else
|
|
|
70f9f0 |
read_buff = new_buff;
|
|
|
70f9f0 |
@@ -6071,6 +6086,9 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
|
|
|
70f9f0 |
TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
|
|
|
70f9f0 |
return (-1);
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
+ read_buff[buffsize] = 0;
|
|
|
70f9f0 |
+ read_buff[buffsize+1] = 0;
|
|
|
70f9f0 |
+ read_buff[buffsize+2] = 0;
|
|
|
70f9f0 |
|
|
|
70f9f0 |
prev_readsize = buffsize;
|
|
|
70f9f0 |
*read_ptr = read_buff;
|
|
|
70f9f0 |
@@ -8877,6 +8895,11 @@ reverseSamplesBytes (uint16 spp, uint16 bps, uint32 width,
|
|
|
70f9f0 |
}
|
|
|
70f9f0 |
|
|
|
70f9f0 |
bytes_per_pixel = ((bps * spp) + 7) / 8;
|
|
|
70f9f0 |
+ if( bytes_per_pixel > sizeof(swapbuff) )
|
|
|
70f9f0 |
+ {
|
|
|
70f9f0 |
+ TIFFError("reverseSamplesBytes","bytes_per_pixel too large");
|
|
|
70f9f0 |
+ return (1);
|
|
|
70f9f0 |
+ }
|
|
|
70f9f0 |
switch (bps / 8)
|
|
|
70f9f0 |
{
|
|
|
70f9f0 |
case 8: /* Use memcpy for multiple bytes per sample data */
|
|
|
70f9f0 |
--
|
|
|
70f9f0 |
2.7.4
|
|
|
70f9f0 |
|