diff --git a/ChangeLog b/ChangeLog index 8e7dea30..26d6f47d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2016-09-23 Even Rouault + + * tools/tiffcrop.c: fix various out-of-bounds write vulnerabilities + in heap or stack allocated buffers. Reported as MSVR 35093, + MSVR 35096 and MSVR 35097. Discovered by Axel Souchet and Vishal + Chauhan from the MSRC Vulnerabilities & Mitigations team. + * tools/tiff2pdf.c: fix out-of-bounds write vulnerabilities in + heap allocate buffer in t2p_process_jpeg_strip(). Reported as MSVR + 35098. Discovered by Axel Souchet and Vishal Chauhan from the MSRC + Vulnerabilities & Mitigations team. + * libtiff/tif_pixarlog.c: fix out-of-bounds write vulnerabilities + in heap allocated buffers. Reported as MSVR 35094. Discovered by + Axel Souchet and Vishal Chauhan from the MSRC Vulnerabilities & + Mitigations team. + * libtiff/tif_write.c: fix issue in error code path of TIFFFlushData1() + that didn't reset the tif_rawcc and tif_rawcp members. I'm not + completely sure if that could happen in practice outside of the odd + behaviour of t2p_seekproc() of tiff2pdf). The report points that a + better fix could be to check the return value of TIFFFlushData1() in + places where it isn't done currently, but it seems this patch is enough. + Reported as MSVR 35095. Discovered by Axel Souchet & Vishal Chauhan & + Suha Can from the MSRC Vulnerabilities & Mitigations team. + 2016-09-20 Bob Friesenhahn * html/man/index.html: Comment out links to documentation for diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c index 811b5acb..f4af2bab 100644 --- a/libtiff/tif_pixarlog.c +++ b/libtiff/tif_pixarlog.c @@ -1,4 +1,4 @@ -/* $Id: tif_pixarlog.c,v 1.47 2016-08-15 21:36:43 erouault Exp $ */ +/* $Id: tif_pixarlog.c,v 1.48 2016-09-23 22:12:18 erouault Exp $ */ /* * Copyright (c) 1996-1997 Sam Leffler @@ -983,17 +983,14 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) a1 = (int32) CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; } } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ - n -= stride; - while (n > 0) { - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--) + REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp++; ip++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[0] = (uint16)(((int32)CLAMP(ip[0])-(int32)CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } } } } @@ -1036,17 +1033,14 @@ horizontalDifference16(unsigned short *ip, int n, int stride, a1 = CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; } } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) n -= stride; while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } } } } @@ -1089,18 +1083,15 @@ horizontalDifference8(unsigned char *ip, int n, int stride, ip += 4; } } else { - wp += n + stride - 1; /* point to last one */ - ip += n + stride - 1; /* point to last one */ - n -= stride; - while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) - } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } + } } } diff --git a/libtiff/tif_write.c b/libtiff/tif_write.c index 67323611..34c4d81a 100644 --- a/libtiff/tif_write.c +++ b/libtiff/tif_write.c @@ -1,4 +1,4 @@ -/* $Id: tif_write.c,v 1.44 2016-07-03 16:02:17 erouault Exp $ */ +/* $Id: tif_write.c,v 1.45 2016-09-23 22:12:18 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -798,7 +798,14 @@ TIFFFlushData1(TIFF* tif) if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, tif->tif_rawdata, tif->tif_rawcc)) + { + /* We update those variables even in case of error since there's */ + /* code that doesn't really check the return code of this */ + /* function */ + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; return (0); + } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c index 00bf8508..b7f41b49 100644 --- a/tools/tiff2pdf.c +++ b/tools/tiff2pdf.c @@ -1,4 +1,4 @@ -/* $Id: tiff2pdf.c,v 1.91 2015-09-06 18:24:27 bfriesen Exp $ +/* $Id: tiff2pdf.c,v 1.92 2016-09-23 22:12:18 erouault Exp $ * * tiff2pdf - converts a TIFF image to a PDF document * @@ -286,7 +286,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); int t2p_process_ojpeg_tables(T2P*, TIFF*); #endif #ifdef JPEG_SUPPORT -int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t*, tstrip_t, uint32); +int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t, tsize_t*, tstrip_t, uint32); #endif void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); void t2p_write_advance_directory(T2P*, TIFF*); @@ -2408,7 +2408,8 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ if(!t2p_process_jpeg_strip( stripbuffer, &striplength, - buffer, + buffer, + t2p->tiff_datasize, &bufferoffset, i, t2p->tiff_length)){ @@ -3439,6 +3440,7 @@ int t2p_process_jpeg_strip( unsigned char* strip, tsize_t* striplength, unsigned char* buffer, + tsize_t buffersize, tsize_t* bufferoffset, tstrip_t no, uint32 height){ @@ -3473,6 +3475,8 @@ int t2p_process_jpeg_strip( } switch( strip[i] ){ case 0xd8: /* SOI - start of image */ + if( *bufferoffset + 2 > buffersize ) + return(0); _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), 2); *bufferoffset+=2; break; @@ -3482,12 +3486,18 @@ int t2p_process_jpeg_strip( case 0xc9: /* SOF9 */ case 0xca: /* SOF10 */ if(no==0){ + if( *bufferoffset + datalen + 2 + 6 > buffersize ) + return(0); _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + if( *bufferoffset + 9 >= buffersize ) + return(0); ncomp = buffer[*bufferoffset+9]; if (ncomp < 1 || ncomp > 4) return(0); v_samp=1; h_samp=1; + if( *bufferoffset + 11 + 3*(ncomp-1) >= buffersize ) + return(0); for(j=0;j>4) > h_samp) @@ -3519,20 +3529,28 @@ int t2p_process_jpeg_strip( break; case 0xc4: /* DHT */ case 0xdb: /* DQT */ + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); *bufferoffset+=datalen+2; break; case 0xda: /* SOS */ if(no==0){ + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); *bufferoffset+=datalen+2; } else { + if( *bufferoffset + 2 > buffersize ) + return(0); buffer[(*bufferoffset)++]=0xff; buffer[(*bufferoffset)++]= (unsigned char)(0xd0 | ((no-1)%8)); } i += datalen + 1; /* copy remainder of strip */ + if( *bufferoffset + *striplength - i > buffersize ) + return(0); _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i]), *striplength - i); *bufferoffset+= *striplength - i; return(1); diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c index 8751f939..ee38c97c 100644 --- a/tools/tiffcrop.c +++ b/tools/tiffcrop.c @@ -1,4 +1,4 @@ -/* $Id: tiffcrop.c,v 1.39 2016-08-16 08:54:01 erouault Exp $ */ +/* $Id: tiffcrop.c,v 1.40 2016-09-23 22:12:18 erouault Exp $ */ /* tiffcrop.c -- a port of tiffcp.c extended to include manipulations of * the image data through additional options listed below @@ -5758,7 +5758,8 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c { uint32 i; float xres = 0.0, yres = 0.0; - uint16 nstrips = 0, ntiles = 0, planar = 0; + uint32 nstrips = 0, ntiles = 0; + uint16 planar = 0; uint16 bps = 0, spp = 0, res_unit = 0; uint16 orientation = 0; uint16 input_compression = 0, input_photometric = 0; @@ -6066,11 +6067,23 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c /* +3 : add a few guard bytes since reverseSamples16bits() can read a bit */ /* outside buffer */ if (!read_buff) + { + if( buffsize > 0xFFFFFFFFU - 3 ) + { + TIFFError("loadImage", "Unable to allocate/reallocate read buffer"); + return (-1); + } read_buff = (unsigned char *)_TIFFmalloc(buffsize+3); + } else { if (prev_readsize < buffsize) + { + if( buffsize > 0xFFFFFFFFU - 3 ) { + TIFFError("loadImage", "Unable to allocate/reallocate read buffer"); + return (-1); + } new_buff = _TIFFrealloc(read_buff, buffsize+3); if (!new_buff) { @@ -8912,6 +8925,11 @@ reverseSamplesBytes (uint16 spp, uint16 bps, uint32 width, } bytes_per_pixel = ((bps * spp) + 7) / 8; + if( bytes_per_pixel > sizeof(swapbuff) ) + { + TIFFError("reverseSamplesBytes","bytes_per_pixel too large"); + return (1); + } switch (bps / 8) { case 8: /* Use memcpy for multiple bytes per sample data */