| diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c |
| index 53c938a89..03c9a81fb 100644 |
| --- a/third_party/libtiff/tif_getimage.c |
| +++ b/third_party/libtiff/tif_getimage.c |
| @@ -627,7 +627,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| uint32 col, row, y, rowstoread; |
| tmsize_t pos; |
| uint32 tw, th; |
| - unsigned char* buf; |
| + unsigned char* buf = NULL; |
| int32 fromskew, toskew; |
| int64 safeskew; |
| uint32 nrow; |
| @@ -636,13 +636,14 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| int32 this_toskew, leftmost_toskew; |
| int32 leftmost_fromskew; |
| uint32 leftmost_tw; |
| + tmsize_t bufsize; |
| |
| - buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); |
| - if (buf == 0) { |
| - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); |
| - return (0); |
| + bufsize = TIFFTileSize(tif); |
| + if (bufsize == 0) { |
| + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); |
| + return (0); |
| } |
| - _TIFFmemset(buf, 0, TIFFTileSize(tif)); |
| + |
| TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); |
| TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); |
| |
| @@ -691,8 +692,9 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| col = img->col_offset; |
| while (tocol < w) |
| { |
| - if (TIFFReadTile(tif, buf, col, |
| - row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr) |
| + if (_TIFFReadTileAndAllocBuffer(tif, (void**) &buf, bufsize, col, |
| + row+img->row_offset, 0, 0)==(tmsize_t)(-1) && |
| + (buf == NULL || img->stoponerr)) |
| { |
| ret = 0; |
| break; |
| @@ -772,11 +774,11 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| uint32 col, row, y, rowstoread; |
| tmsize_t pos; |
| uint32 tw, th; |
| - unsigned char* buf; |
| - unsigned char* p0; |
| - unsigned char* p1; |
| - unsigned char* p2; |
| - unsigned char* pa; |
| + unsigned char* buf = NULL; |
| + unsigned char* p0 = NULL; |
| + unsigned char* p1 = NULL; |
| + unsigned char* p2 = NULL; |
| + unsigned char* pa = NULL; |
| tmsize_t tilesize; |
| tmsize_t bufsize; |
| int32 fromskew, toskew; |
| @@ -795,16 +797,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate"); |
| return (0); |
| } |
| - buf = (unsigned char*) _TIFFmalloc(bufsize); |
| - if (buf == 0) { |
| - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); |
| - return (0); |
| - } |
| - _TIFFmemset(buf, 0, bufsize); |
| - p0 = buf; |
| - p1 = p0 + tilesize; |
| - p2 = p1 + tilesize; |
| - pa = (alpha?(p2+tilesize):NULL); |
| + |
| TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); |
| TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); |
| |
| @@ -824,7 +817,6 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| case PHOTOMETRIC_MINISBLACK: |
| case PHOTOMETRIC_PALETTE: |
| colorchannels = 1; |
| - p2 = p1 = p0; |
| break; |
| |
| default: |
| @@ -849,7 +841,30 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| col = img->col_offset; |
| while (tocol < w) |
| { |
| - if (TIFFReadTile(tif, p0, col, |
| + if( buf == NULL ) |
| + { |
| + if (_TIFFReadTileAndAllocBuffer( |
| + tif, (void**) &buf, bufsize, col, |
| + row+img->row_offset,0,0)==(tmsize_t)(-1) |
| + && (buf == NULL || img->stoponerr)) |
| + { |
| + ret = 0; |
| + break; |
| + } |
| + p0 = buf; |
| + if( colorchannels == 1 ) |
| + { |
| + p2 = p1 = p0; |
| + pa = (alpha?(p0+3*tilesize):NULL); |
| + } |
| + else |
| + { |
| + p1 = p0 + tilesize; |
| + p2 = p1 + tilesize; |
| + pa = (alpha?(p2+tilesize):NULL); |
| + } |
| + } |
| + else if (TIFFReadTile(tif, p0, col, |
| row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) |
| { |
| ret = 0; |
| @@ -940,13 +955,14 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| tileContigRoutine put = img->put.contig; |
| uint32 row, y, nrow, nrowsub, rowstoread; |
| tmsize_t pos; |
| - unsigned char* buf; |
| + unsigned char* buf = NULL; |
| uint32 rowsperstrip; |
| uint16 subsamplinghor,subsamplingver; |
| uint32 imagewidth = img->width; |
| tmsize_t scanline; |
| int32 fromskew, toskew; |
| int ret = 1, flip; |
| + tmsize_t maxstripsize; |
| |
| TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); |
| if( subsamplingver == 0 ) { |
| @@ -954,12 +970,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| return (0); |
| } |
| |
| - buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); |
| - if (buf == 0) { |
| - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); |
| - return (0); |
| - } |
| - _TIFFmemset(buf, 0, TIFFStripSize(tif)); |
| + maxstripsize = TIFFStripSize(tif); |
| |
| flip = setorientation(img); |
| if (flip & FLIP_VERTICALLY) { |
| @@ -981,11 +992,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| nrowsub = nrow; |
| if ((nrowsub%subsamplingver)!=0) |
| nrowsub+=subsamplingver-nrowsub%subsamplingver; |
| - if (TIFFReadEncodedStrip(tif, |
| + if (_TIFFReadEncodedStripAndAllocBuffer(tif, |
| TIFFComputeStrip(tif,row+img->row_offset, 0), |
| - buf, |
| + (void**)(&buf), |
| + maxstripsize, |
| ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) |
| - && img->stoponerr) |
| + && (buf == NULL || img->stoponerr)) |
| { |
| ret = 0; |
| break; |
| @@ -1029,8 +1041,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| { |
| TIFF* tif = img->tif; |
| tileSeparateRoutine put = img->put.separate; |
| - unsigned char *buf; |
| - unsigned char *p0, *p1, *p2, *pa; |
| + unsigned char *buf = NULL; |
| + unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL; |
| uint32 row, y, nrow, rowstoread; |
| tmsize_t pos; |
| tmsize_t scanline; |
| @@ -1049,15 +1061,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate"); |
| return (0); |
| } |
| - p0 = buf = (unsigned char *)_TIFFmalloc(bufsize); |
| - if (buf == 0) { |
| - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); |
| - return (0); |
| - } |
| - _TIFFmemset(buf, 0, bufsize); |
| - p1 = p0 + stripsize; |
| - p2 = p1 + stripsize; |
| - pa = (alpha?(p2+stripsize):NULL); |
| |
| flip = setorientation(img); |
| if (flip & FLIP_VERTICALLY) { |
| @@ -1075,7 +1078,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| case PHOTOMETRIC_MINISBLACK: |
| case PHOTOMETRIC_PALETTE: |
| colorchannels = 1; |
| - p2 = p1 = p0; |
| break; |
| |
| default: |
| @@ -1091,7 +1093,31 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) |
| rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; |
| nrow = (row + rowstoread > h ? h - row : rowstoread); |
| offset_row = row + img->row_offset; |
| - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), |
| + if( buf == NULL ) |
| + { |
| + if (_TIFFReadEncodedStripAndAllocBuffer( |
| + tif, TIFFComputeStrip(tif, offset_row, 0), |
| + (void**) &buf, bufsize, |
| + ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) |
| + && (buf == NULL || img->stoponerr)) |
| + { |
| + ret = 0; |
| + break; |
| + } |
| + p0 = buf; |
| + if( colorchannels == 1 ) |
| + { |
| + p2 = p1 = p0; |
| + pa = (alpha?(p0+3*stripsize):NULL); |
| + } |
| + else |
| + { |
| + p1 = p0 + stripsize; |
| + p2 = p1 + stripsize; |
| + pa = (alpha?(p2+stripsize):NULL); |
| + } |
| + } |
| + else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), |
| p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) |
| && img->stoponerr) |
| { |
| diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c |
| index cc4f5d2f6..ad0a778c0 100644 |
| --- a/third_party/libtiff/tif_read.c |
| +++ b/third_party/libtiff/tif_read.c |
| @@ -442,18 +442,17 @@ TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) |
| } |
| |
| /* |
| - * Read a strip of data and decompress the specified |
| - * amount into the user-supplied buffer. |
| + * Calculate the strip size according to the number of |
| + * rows in the strip (check for truncated last strip on any |
| + * of the separations). |
| */ |
| -tmsize_t |
| -TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) |
| +static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF* tif, uint32 strip, uint16* pplane) |
| { |
| static const char module[] = "TIFFReadEncodedStrip"; |
| TIFFDirectory *td = &tif->tif_dir; |
| uint32 rowsperstrip; |
| uint32 stripsperplane; |
| uint32 stripinplane; |
| - uint16 plane; |
| uint32 rows; |
| tmsize_t stripsize; |
| if (!TIFFCheckRead(tif,0)) |
| @@ -465,23 +464,37 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) |
| (unsigned long)td->td_nstrips); |
| return((tmsize_t)(-1)); |
| } |
| - /* |
| - * Calculate the strip size according to the number of |
| - * rows in the strip (check for truncated last strip on any |
| - * of the separations). |
| - */ |
| + |
| rowsperstrip=td->td_rowsperstrip; |
| if (rowsperstrip>td->td_imagelength) |
| rowsperstrip=td->td_imagelength; |
| stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); |
| stripinplane=(strip%stripsperplane); |
| - plane=(uint16)(strip/stripsperplane); |
| + if( pplane ) *pplane=(uint16)(strip/stripsperplane); |
| rows=td->td_imagelength-stripinplane*rowsperstrip; |
| if (rows>rowsperstrip) |
| rows=rowsperstrip; |
| stripsize=TIFFVStripSize(tif,rows); |
| if (stripsize==0) |
| return((tmsize_t)(-1)); |
| + return stripsize; |
| +} |
| + |
| +/* |
| + * Read a strip of data and decompress the specified |
| + * amount into the user-supplied buffer. |
| + */ |
| +tmsize_t |
| +TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) |
| +{ |
| + static const char module[] = "TIFFReadEncodedStrip"; |
| + TIFFDirectory *td = &tif->tif_dir; |
| + tmsize_t stripsize; |
| + uint16 plane; |
| + |
| + stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); |
| + if (stripsize==((tmsize_t)(-1))) |
| + return((tmsize_t)(-1)); |
| |
| /* shortcut to avoid an extra memcpy() */ |
| if( td->td_compression == COMPRESSION_NONE && |
| @@ -510,6 +523,50 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) |
| return(stripsize); |
| } |
| |
| +/* Variant of TIFFReadEncodedStrip() that does |
| + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillStrip() has |
| + * suceeded. This avoid excessive memory allocation in case of truncated |
| + * file. |
| + * * calls regular TIFFReadEncodedStrip() if *buf != NULL |
| + */ |
| +tmsize_t |
| +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + tmsize_t size_to_read) |
| +{ |
| + tmsize_t this_stripsize; |
| + uint16 plane; |
| + |
| + if( *buf != NULL ) |
| + { |
| + return TIFFReadEncodedStrip(tif, strip, *buf, size_to_read); |
| + } |
| + |
| + this_stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); |
| + if (this_stripsize==((tmsize_t)(-1))) |
| + return((tmsize_t)(-1)); |
| + |
| + if ((size_to_read!=(tmsize_t)(-1))&&(size_to_read<this_stripsize)) |
| + this_stripsize=size_to_read; |
| + if (!TIFFFillStrip(tif,strip)) |
| + return((tmsize_t)(-1)); |
| + |
| + *buf = _TIFFmalloc(bufsizetoalloc); |
| + if (*buf == NULL) { |
| + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); |
| + return((tmsize_t)(-1)); |
| + } |
| + _TIFFmemset(*buf, 0, bufsizetoalloc); |
| + |
| + if ((*tif->tif_decodestrip)(tif,*buf,this_stripsize,plane)<=0) |
| + return((tmsize_t)(-1)); |
| + (*tif->tif_postdecode)(tif,*buf,this_stripsize); |
| + return(this_stripsize); |
| + |
| + |
| +} |
| + |
| + |
| static tmsize_t |
| TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, |
| const char* module) |
| @@ -939,6 +996,78 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) |
| return ((tmsize_t)(-1)); |
| } |
| |
| +/* Variant of TIFFReadTile() that does |
| + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has |
| + * suceeded. This avoid excessive memory allocation in case of truncated |
| + * file. |
| + * * calls regular TIFFReadEncodedTile() if *buf != NULL |
| + */ |
| +tmsize_t |
| +_TIFFReadTileAndAllocBuffer(TIFF* tif, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + uint32 x, uint32 y, uint32 z, uint16 s) |
| +{ |
| + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) |
| + return ((tmsize_t)(-1)); |
| + return (_TIFFReadEncodedTileAndAllocBuffer(tif, |
| + TIFFComputeTile(tif, x, y, z, s), |
| + buf, bufsizetoalloc, |
| + (tmsize_t)(-1))); |
| +} |
| + |
| +/* Variant of TIFFReadEncodedTile() that does |
| + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has |
| + * suceeded. This avoid excessive memory allocation in case of truncated |
| + * file. |
| + * * calls regular TIFFReadEncodedTile() if *buf != NULL |
| + */ |
| +tmsize_t |
| +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + tmsize_t size_to_read) |
| +{ |
| + static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; |
| + TIFFDirectory *td = &tif->tif_dir; |
| + tmsize_t tilesize = tif->tif_tilesize; |
| + |
| + if( *buf != NULL ) |
| + { |
| + return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); |
| + } |
| + |
| + if (!TIFFCheckRead(tif, 1)) |
| + return ((tmsize_t)(-1)); |
| + if (tile >= td->td_nstrips) { |
| + TIFFErrorExt(tif->tif_clientdata, module, |
| + "%lu: Tile out of range, max %lu", |
| + (unsigned long) tile, (unsigned long) td->td_nstrips); |
| + return ((tmsize_t)(-1)); |
| + } |
| + |
| + if (!TIFFFillTile(tif,tile)) |
| + return((tmsize_t)(-1)); |
| + |
| + *buf = _TIFFmalloc(bufsizetoalloc); |
| + if (*buf == NULL) { |
| + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), |
| + "No space for tile buffer"); |
| + return((tmsize_t)(-1)); |
| + } |
| + _TIFFmemset(*buf, 0, bufsizetoalloc); |
| + |
| + if (size_to_read == (tmsize_t)(-1)) |
| + size_to_read = tilesize; |
| + else if (size_to_read > tilesize) |
| + size_to_read = tilesize; |
| + if( (*tif->tif_decodetile)(tif, |
| + (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { |
| + (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); |
| + return (size_to_read); |
| + } else |
| + return ((tmsize_t)(-1)); |
| +} |
| + |
| + |
| static tmsize_t |
| TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) |
| { |
| diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h |
| index 7e415c750..6fb47de5b 100644 |
| --- a/third_party/libtiff/tiffiop.h |
| +++ b/third_party/libtiff/tiffiop.h |
| @@ -364,6 +364,20 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); |
| extern double _TIFFUInt64ToDouble(uint64); |
| extern float _TIFFUInt64ToFloat(uint64); |
| |
| +extern tmsize_t |
| +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + tmsize_t size_to_read); |
| +extern tmsize_t |
| +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + tmsize_t size_to_read); |
| +extern tmsize_t |
| +_TIFFReadTileAndAllocBuffer(TIFF* tif, |
| + void **buf, tmsize_t bufsizetoalloc, |
| + uint32 x, uint32 y, uint32 z, uint16 s); |
| + |
| + |
| extern int TIFFInitDumpMode(TIFF*, int); |
| #ifdef PACKBITS_SUPPORT |
| extern int TIFFInitPackBits(TIFF*, int); |