diff --git a/frmts/gtiff/libtiff/tif_dir.c b/frmts/gtiff/libtiff/tif_dir.c index a31a596b1821..459f9696fd3e 100644 --- a/frmts/gtiff/libtiff/tif_dir.c +++ b/frmts/gtiff/libtiff/tif_dir.c @@ -1864,7 +1864,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (((uint64_t)poffa != poff) || (poffb < poffa) || (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size)) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); *nextdiroff = 0; return (0); } @@ -1893,14 +1895,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, uint16_t dircount16; if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t)) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } poffa = (tmsize_t)poff; poffb = poffa + sizeof(uint64_t); if (poffb > tif->tif_size) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } _TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t)); @@ -1942,8 +1948,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (!SeekOK(tif, *nextdiroff) || !ReadOK(tif, &dircount, sizeof(uint16_t))) { - TIFFErrorExtR(tif, module, "%s: Error fetching directory count", - tif->tif_name); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) @@ -1969,15 +1976,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (!SeekOK(tif, *nextdiroff) || !ReadOK(tif, &dircount64, sizeof(uint64_t))) { - TIFFErrorExtR(tif, module, "%s: Error fetching directory count", - tif->tif_name); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&dircount64); if (dircount64 > 0xFFFF) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } dircount16 = (uint16_t)dircount64; @@ -2169,8 +2179,10 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) probablySubIFD = 1; } /* -1 because TIFFReadDirectory() will increment tif_curdir. */ - tif->tif_curdir = - curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1; + if (curdir >= 1) + tif->tif_curdir = curdir - 1; + else + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; } curdir = tif->tif_curdir; diff --git a/frmts/gtiff/libtiff/tif_dirwrite.c b/frmts/gtiff/libtiff/tif_dirwrite.c index 546fb48ad696..0701f40d97ef 100644 --- a/frmts/gtiff/libtiff/tif_dirwrite.c +++ b/frmts/gtiff/libtiff/tif_dirwrite.c @@ -2074,7 +2074,7 @@ static void EvaluateIFDdatasizeWrite(TIFF *tif, uint32_t count, uint64_t datalength = (uint64_t)count * typesize; if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U)) { - /* LibTIFF increments write address to an even offset, thus datalenght + /* LibTIFF increments write address to an even offset, thus datalength * written is also incremented. */ if (datalength & 1) datalength++; @@ -3198,7 +3198,7 @@ static int TIFFLinkDirectory(TIFF *tif) /* * Not the first directory, search to the last and append. */ - tdir_t dirn = -1; + tdir_t dirn = 0; if (tif->tif_lastdiroff != 0 && _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn)) { @@ -3276,7 +3276,7 @@ static int TIFFLinkDirectory(TIFF *tif) /* * Not the first directory, search to the last and append. */ - tdir_t dirn = -1; + tdir_t dirn = 0; if (tif->tif_lastdiroff != 0 && _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn)) { diff --git a/frmts/gtiff/libtiff/tif_fax3.c b/frmts/gtiff/libtiff/tif_fax3.c index 668e96a33073..01a784730bdc 100644 --- a/frmts/gtiff/libtiff/tif_fax3.c +++ b/frmts/gtiff/libtiff/tif_fax3.c @@ -569,7 +569,11 @@ static int Fax3SetupState(TIFF *tif) TIFFroundup and TIFFSafeMultiply return zero on integer overflow */ - dsp->runs = (uint32_t *)NULL; + if (dsp->runs != NULL) + { + _TIFFfreeExt(tif, dsp->runs); + dsp->runs = (uint32_t *)NULL; + } dsp->nruns = TIFFroundup_32(rowpixels + 1, 32); if (needsRefLine) { @@ -611,6 +615,10 @@ static int Fax3SetupState(TIFF *tif) * is referenced. The reference line must * be initialized to be ``white'' (done elsewhere). */ + if (esp->refline != NULL) + { + _TIFFfreeExt(tif, esp->refline); + } esp->refline = (unsigned char *)_TIFFmallocExt(tif, rowbytes); if (esp->refline == NULL) { @@ -1556,6 +1564,7 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) return (-1); } CACHE_STATE(tif, sp); + int start = sp->line; while (occ > 0) { a0 = 0; @@ -1604,7 +1613,9 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) } (*sp->fill)(buf, thisrun, pa, lastx); UNCACHE_STATE(tif, sp); - return (sp->line ? 1 : -1); /* don't error on badly-terminated strips */ + return (sp->line != start + ? 1 + : -1); /* don't error on badly-terminated strips */ } UNCACHE_STATE(tif, sp); return (1); diff --git a/frmts/gtiff/libtiff/tif_getimage.c b/frmts/gtiff/libtiff/tif_getimage.c index 0ada2697259c..6c7b5031a193 100644 --- a/frmts/gtiff/libtiff/tif_getimage.c +++ b/frmts/gtiff/libtiff/tif_getimage.c @@ -766,7 +766,6 @@ static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, return (0); } - /* * Leftmost tile is clipped on left side if col_offset > 0. */ @@ -1111,7 +1110,6 @@ static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, return (0); } - scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += nrow) @@ -3323,7 +3321,8 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster, TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); if (tile_xsize == 0 || tile_ysize == 0) { - TIFFErrorExtR(tif, TIFFFileName(tif), "tile_xsize or tile_ysize is zero"); + TIFFErrorExtR(tif, TIFFFileName(tif), + "tile_xsize or tile_ysize is zero"); return (0); } diff --git a/frmts/gtiff/libtiff/tif_jpeg.c b/frmts/gtiff/libtiff/tif_jpeg.c index d80bbc6f012d..10aed5463589 100644 --- a/frmts/gtiff/libtiff/tif_jpeg.c +++ b/frmts/gtiff/libtiff/tif_jpeg.c @@ -88,18 +88,18 @@ int TIFFJPEGIsFullStripRequired_12(TIFF *tif); * 16bit value? */ -/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which +/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 3.0 which * adds a dual-mode 8/12 bit API in the same library. */ #if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) #define JPEG_DUAL_MODE_8_12 /* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo - * >= 2.2 Cf + * >= 3.0 Cf * https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b */ #undef BITS_IN_JSAMPLE -/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */ +/* libjpeg-turbo >= 3.0 adds J12xxxx datatypes for the 12-bit mode. */ #if defined(FROM_TIF_JPEG_12) #define BITS_IN_JSAMPLE 12 #define TIFF_JSAMPLE J12SAMPLE @@ -1451,7 +1451,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; if (sp->bytesperline == 0) + { + memset(buf, 0, (size_t)cc); return 0; + } nrows = cc / sp->bytesperline; if (cc % sp->bytesperline) @@ -1472,7 +1475,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) JSAMPROW bufptr = (JSAMPROW)buf; if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + { + memset(buf, 0, (size_t)cc); return (0); + } ++tif->tif_row; buf += sp->bytesperline; @@ -1506,7 +1512,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; if (sp->bytesperline == 0) + { + memset(buf, 0, (size_t)cc); return 0; + } nrows = cc / sp->bytesperline; if (cc % sp->bytesperline) @@ -1542,7 +1551,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) * for 12bit data, which we need to repack. */ if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) + { + memset(buf, 0, (size_t)cc); return (0); + } if (sp->cinfo.d.data_precision == 12) { diff --git a/frmts/gtiff/libtiff/tif_lerc.c b/frmts/gtiff/libtiff/tif_lerc.c index d9d8d3342eb3..d57b1d253de5 100644 --- a/frmts/gtiff/libtiff/tif_lerc.c +++ b/frmts/gtiff/libtiff/tif_lerc.c @@ -754,6 +754,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->uncompressed_buffer == 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Uncompressed buffer not allocated"); return 0; } @@ -761,6 +762,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if ((uint64_t)sp->uncompressed_offset + (uint64_t)occ > sp->uncompressed_size) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Too many bytes read"); return 0; } diff --git a/frmts/gtiff/libtiff/tif_lzma.c b/frmts/gtiff/libtiff/tif_lzma.c index 6fdc92802627..db1c8b6829ff 100644 --- a/frmts/gtiff/libtiff/tif_lzma.c +++ b/frmts/gtiff/libtiff/tif_lzma.c @@ -44,6 +44,8 @@ typedef struct { TIFFPredictorState predict; + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ lzma_stream stream; lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_options_delta opt_delta; /* delta filter options */ @@ -156,6 +158,9 @@ static int LZMAPreDecode(TIFF *tif, uint16_t s) LZMAStrerror(ret)); return 0; } + + sp->read_error = 0; + return 1; } @@ -168,6 +173,16 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) assert(sp != NULL); assert(sp->state == LSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "LZMADecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + sp->stream.next_in = tif->tif_rawcp; sp->stream.avail_in = (size_t)tif->tif_rawcc; @@ -175,6 +190,9 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) sp->stream.avail_out = (size_t)occ; if ((tmsize_t)sp->stream.avail_out != occ) { + // read_error not set here as this is a usage issue that can be + // recovered in a following call. + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Liblzma cannot deal with buffers this size"); return 0; @@ -198,6 +216,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0); if (r != LZMA_OK) { + sp->read_error = 1; + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Error initializing the stream decoder, %s", LZMAStrerror(r)); @@ -217,6 +237,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) } while (sp->stream.avail_out > 0); if (sp->stream.avail_out != 0) { + sp->read_error = 1; + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "Not enough data at scanline %" PRIu32 " (short %" TIFF_SIZE_FORMAT " bytes)", diff --git a/frmts/gtiff/libtiff/tif_lzw.c b/frmts/gtiff/libtiff/tif_lzw.c index 05ac8aa1abe7..4baf78e50b20 100644 --- a/frmts/gtiff/libtiff/tif_lzw.c +++ b/frmts/gtiff/libtiff/tif_lzw.c @@ -417,6 +417,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) if (sp->read_error) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "LZWDecode: Scanline %" PRIu32 " cannot be read due to " "previous error", @@ -731,6 +732,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) if (occ > 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Not enough data at scanline %" PRIu32 " (short %" PRIu64 " bytes)", @@ -740,12 +742,14 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) return (1); no_eoi: + memset(op, 0, (size_t)occ); sp->read_error = 1; TIFFErrorExtR(tif, module, "LZWDecode: Strip %" PRIu32 " not terminated with EOI code", tif->tif_curstrip); return 0; error_code: + memset(op, 0, (size_t)occ); sp->read_error = 1; TIFFErrorExtR(tif, tif->tif_name, "Using code not yet in table"); return 0; diff --git a/frmts/gtiff/libtiff/tif_ojpeg.c b/frmts/gtiff/libtiff/tif_ojpeg.c index e4547cf09137..f94d2a4e45f7 100644 --- a/frmts/gtiff/libtiff/tif_ojpeg.c +++ b/frmts/gtiff/libtiff/tif_ojpeg.c @@ -755,6 +755,9 @@ static int OJPEGPreDecode(TIFF *tif, uint16_t s) if (OJPEGWriteHeaderInfo(tif) == 0) return (0); } + + sp->subsampling_convert_state = 0; + while (sp->write_curstrile < m) { if (sp->libjpeg_jpeg_query_style == 0) @@ -840,12 +843,14 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) (void)s; if (!sp->decoder_ok) { + memset(buf, 0, (size_t)cc); TIFFErrorExtR(tif, module, "Cannot decode: decoder not correctly initialized"); return 0; } if (sp->libjpeg_session_active == 0) { + memset(buf, 0, (size_t)cc); /* This should normally not happen, except that it does when */ /* using TIFFReadScanline() which calls OJPEGPostDecode() for */ /* each scanline, which assumes that a whole strile was read */ @@ -859,17 +864,24 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) } if (sp->error_in_raw_data_decoding) { + memset(buf, 0, (size_t)cc); return 0; } if (sp->libjpeg_jpeg_query_style == 0) { if (OJPEGDecodeRaw(tif, buf, cc) == 0) + { + memset(buf, 0, (size_t)cc); return (0); + } } else { if (OJPEGDecodeScanlines(tif, buf, cc) == 0) + { + memset(buf, 0, (size_t)cc); return (0); + } } return (1); } diff --git a/frmts/gtiff/libtiff/tif_packbits.c b/frmts/gtiff/libtiff/tif_packbits.c index 62849f8f3c16..1ae50cbd47ce 100644 --- a/frmts/gtiff/libtiff/tif_packbits.c +++ b/frmts/gtiff/libtiff/tif_packbits.c @@ -300,6 +300,7 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) tif->tif_rawcc = cc; if (occ > 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32, tif->tif_row); return (0); diff --git a/frmts/gtiff/libtiff/tif_pixarlog.c b/frmts/gtiff/libtiff/tif_pixarlog.c index 5ed921eb3004..56cf416a7f6b 100644 --- a/frmts/gtiff/libtiff/tif_pixarlog.c +++ b/frmts/gtiff/libtiff/tif_pixarlog.c @@ -859,6 +859,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) TIFFErrorExtR(tif, module, "%" PRIu16 " bit input not supported in PixarLog", td->td_bitspersample); + memset(op, 0, (size_t)occ); return 0; } @@ -879,12 +880,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->stream.avail_out != nsamples * sizeof(uint16_t)) { TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size"); + memset(op, 0, (size_t)occ); return (0); } /* Check that we will not fill more than what was allocated */ if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) { TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size"); + memset(op, 0, (size_t)occ); return (0); } do @@ -899,12 +902,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) TIFFErrorExtR( tif, module, "Decoding error at scanline %" PRIu32 ", %s", tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); + memset(op, 0, (size_t)occ); return (0); } if (state != Z_OK) { TIFFErrorExtR(tif, module, "ZLib error: %s", sp->stream.msg ? sp->stream.msg : "(null)"); + memset(op, 0, (size_t)occ); return (0); } } while (sp->stream.avail_out > 0); @@ -916,6 +921,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) "Not enough data at scanline %" PRIu32 " (short %u bytes)", tif->tif_row, sp->stream.avail_out); + memset(op, 0, (size_t)occ); return (0); } @@ -977,6 +983,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) default: TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16, td->td_bitspersample); + memset(op, 0, (size_t)occ); return (0); } } diff --git a/frmts/gtiff/libtiff/tif_read.c b/frmts/gtiff/libtiff/tif_read.c index df4bac69253c..7efab59c6a38 100644 --- a/frmts/gtiff/libtiff/tif_read.c +++ b/frmts/gtiff/libtiff/tif_read.c @@ -464,6 +464,10 @@ int TIFFReadScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample) if (e) (*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize); } + else + { + memset(buf, 0, (size_t)tif->tif_scanlinesize); + } return (e > 0 ? 1 : -1); } @@ -549,7 +553,10 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf, if ((size != (tmsize_t)(-1)) && (size < stripsize)) stripsize = size; if (!TIFFFillStrip(tif, strip)) + { + memset(buf, 0, (size_t)stripsize); return ((tmsize_t)(-1)); + } if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0) return ((tmsize_t)(-1)); (*tif->tif_postdecode)(tif, buf, stripsize); @@ -967,9 +974,13 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size) size = tilesize; else if (size > tilesize) size = tilesize; - if (TIFFFillTile(tif, tile) && - (*tif->tif_decodetile)(tif, (uint8_t *)buf, size, - (uint16_t)(tile / td->td_stripsperimage))) + if (!TIFFFillTile(tif, tile)) + { + memset(buf, 0, (size_t)size); + return ((tmsize_t)(-1)); + } + else if ((*tif->tif_decodetile)(tif, (uint8_t *)buf, size, + (uint16_t)(tile / td->td_stripsperimage))) { (*tif->tif_postdecode)(tif, (uint8_t *)buf, size); return (size); @@ -1555,9 +1566,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf, if (TIFFIsTiled(tif)) { - if (!TIFFStartTile(tif, strile) || - !(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize, - (uint16_t)(strile / td->td_stripsperimage))) + if (!TIFFStartTile(tif, strile)) + { + ret = 0; + memset(outbuf, 0, (size_t)outsize); + } + else if (!(*tif->tif_decodetile)( + tif, (uint8_t *)outbuf, outsize, + (uint16_t)(strile / td->td_stripsperimage))) { ret = 0; } @@ -1577,9 +1593,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf, { stripsperplane = TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); - if (!TIFFStartStrip(tif, strile) || - !(*tif->tif_decodestrip)(tif, (uint8_t *)outbuf, outsize, - (uint16_t)(strile / stripsperplane))) + if (!TIFFStartStrip(tif, strile)) + { + ret = 0; + memset(outbuf, 0, (size_t)outsize); + } + else if (!(*tif->tif_decodestrip)( + tif, (uint8_t *)outbuf, outsize, + (uint16_t)(strile / stripsperplane))) { ret = 0; } diff --git a/frmts/gtiff/libtiff/tif_strip.c b/frmts/gtiff/libtiff/tif_strip.c index ee31892af269..7ae7ce41dfa2 100644 --- a/frmts/gtiff/libtiff/tif_strip.c +++ b/frmts/gtiff/libtiff/tif_strip.c @@ -294,7 +294,25 @@ uint64_t TIFFScanlineSize64(TIFF *tif) else { uint64_t scanline_samples; - scanline_samples = _TIFFMultiply64(tif, td->td_imagewidth, + uint32_t scanline_width = td->td_imagewidth; + +#if 0 + // Tries to fix https://gitlab.com/libtiff/libtiff/-/merge_requests/564 + // but causes regression when decoding legit files with tiffcp -c none + // Cf https://gitlab.com/libtiff/libtiff/-/merge_requests/644 + if (td->td_photometric == PHOTOMETRIC_YCBCR) + { + uint16_t subsampling_hor; + uint16_t ignored; + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, + &subsampling_hor, &ignored); + if (subsampling_hor > 1) // roundup width for YCbCr + scanline_width = + TIFFroundup_32(scanline_width, subsampling_hor); + } +#endif + + scanline_samples = _TIFFMultiply64(tif, scanline_width, td->td_samplesperpixel, module); scanline_size = TIFFhowmany_64(_TIFFMultiply64(tif, scanline_samples, diff --git a/frmts/gtiff/libtiff/tif_thunder.c b/frmts/gtiff/libtiff/tif_thunder.c index 1f97362ca39d..bac0607dbe54 100644 --- a/frmts/gtiff/libtiff/tif_thunder.c +++ b/frmts/gtiff/libtiff/tif_thunder.c @@ -82,13 +82,14 @@ static int ThunderSetupDecode(TIFF *tif) return (1); } -static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) +static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels) { static const char module[] = "ThunderDecode"; register unsigned char *bp; register tmsize_t cc; unsigned int lastpixel; tmsize_t npixels; + uint8_t *op = op0; bp = (unsigned char *)tif->tif_rawcp; cc = tif->tif_rawcc; @@ -107,6 +108,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) * Replicate the last pixel n times, * where n is the lower-order 6 bits. */ + if (n == 0) + break; if (npixels & 1) { op[0] |= lastpixel; @@ -117,11 +120,10 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) else lastpixel |= lastpixel << 4; npixels += n; - if (npixels < maxpixels) - { - for (; n > 0; n -= 2) - *op++ = (uint8_t)lastpixel; - } + if (npixels > maxpixels) + break; + for (; n > 0; n -= 2) + *op++ = (uint8_t)lastpixel; if (n == -1) *--op &= 0xf0; lastpixel &= 0xf; @@ -154,6 +156,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) tif->tif_rawcc = cc; if (npixels != maxpixels) { + uint8_t *op_end = op0 + (maxpixels + 1) / 2; + memset(op, 0, (size_t)(op_end - op)); TIFFErrorExtR(tif, module, "%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")", npixels < maxpixels ? "Not enough" : "Too much", diff --git a/frmts/gtiff/libtiff/tif_webp.c b/frmts/gtiff/libtiff/tif_webp.c index bf9d77eb9beb..ccffef070377 100644 --- a/frmts/gtiff/libtiff/tif_webp.c +++ b/frmts/gtiff/libtiff/tif_webp.c @@ -47,7 +47,9 @@ typedef struct { uint16_t nSamples; /* number of samples per pixel */ - int lossless; /* lossy/lossless compression */ + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ + int lossless; /* lossy/lossless compression */ int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas with alpha = 0 will be preserved */ int quality_level; /* compression level */ @@ -133,6 +135,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) assert(sp != NULL); assert(sp->state == LSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "ZIPDecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + if (sp->psDecoder == NULL) { TIFFDirectory *td = &tif->tif_dir; @@ -158,12 +170,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) : (uint32_t)tif->tif_rawcc, &webp_width, &webp_height)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPGetInfo() failed"); return 0; } if ((uint32_t)webp_width != segment_width || (uint32_t)webp_height != segment_height) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR( tif, module, "WebP blob dimension is %dx%d. Expected %ux%u", webp_width, webp_height, segment_width, segment_height); @@ -174,6 +190,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) WebPDecoderConfig config; if (!WebPInitDecoderConfig(&config)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); return 0; } @@ -189,6 +207,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (!bWebPGetFeaturesOK) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); return 0; } @@ -202,6 +222,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) */ !(webp_bands == 3 && sp->nSamples == 4)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebP blob band count is %d. Expected %d", webp_bands, sp->nSamples); @@ -228,6 +250,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (!sp->pBuffer) { TIFFErrorExtR(tif, module, "Cannot allocate buffer"); + memset(op, 0, (size_t)occ); + sp->read_error = 1; return 0; } sp->buffer_size = buffer_size; @@ -257,6 +281,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->psDecoder == NULL) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder."); return 0; } @@ -264,6 +290,10 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (occ % sp->sDecBuffer.u.RGBA.stride) { + // read_error not set here as this is a usage issue that can be + // recovered in a following call. + memset(op, 0, (size_t)occ); + /* Do not set read_error as could potentially be recovered */ TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); return 0; } @@ -284,6 +314,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { TIFFErrorExtR(tif, module, "Unrecognized error."); } + memset(op, 0, (size_t)occ); + sp->read_error = 1; return 0; } else @@ -303,6 +335,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { if (current_y != numberOfExpectedLines) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to decode WebP data: less lines than " "expected."); @@ -332,6 +366,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) } else { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to decode WebP data."); return 0; } @@ -451,6 +487,8 @@ static int TWebPPreDecode(TIFF *tif, uint16_t s) sp->psDecoder = NULL; } + sp->read_error = 0; + return 1; } diff --git a/frmts/gtiff/libtiff/tif_zip.c b/frmts/gtiff/libtiff/tif_zip.c index a351ba5649fc..2a2a1d787f69 100644 --- a/frmts/gtiff/libtiff/tif_zip.c +++ b/frmts/gtiff/libtiff/tif_zip.c @@ -67,6 +67,8 @@ typedef struct { TIFFPredictorState predict; z_stream stream; + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ int zipquality; /* compression level */ int state; /* state flags */ int subcodec; /* DEFLATE_SUBCODEC_ZLIB or DEFLATE_SUBCODEC_LIBDEFLATE */ @@ -150,7 +152,12 @@ static int ZIPPreDecode(TIFF *tif, uint16_t s) sp->stream.avail_in = (uint64_t)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU; - return (inflateReset(&sp->stream) == Z_OK); + if (inflateReset(&sp->stream) == Z_OK) + { + sp->read_error = 0; + return 1; + } + return 0; } static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) @@ -162,6 +169,16 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) assert(sp != NULL); assert(sp->state == ZSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "ZIPDecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + #if LIBDEFLATE_SUPPORT if (sp->libdeflate_state == 1) return 0; @@ -227,8 +244,10 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (res != LIBDEFLATE_SUCCESS && res != LIBDEFLATE_INSUFFICIENT_SPACE) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Decoding error at scanline %lu", (unsigned long)tif->tif_row); + sp->read_error = 1; return 0; } @@ -263,13 +282,17 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) break; if (state == Z_DATA_ERROR) { + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s", (unsigned long)tif->tif_row, SAFE_MSG(sp)); + sp->read_error = 1; return (0); } if (state != Z_OK) { + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp)); + sp->read_error = 1; return (0); } } while (occ > 0); @@ -279,6 +302,8 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) "Not enough data at scanline %lu (short %" PRIu64 " bytes)", (unsigned long)tif->tif_row, (uint64_t)occ); + memset(sp->stream.next_out, 0, sp->stream.avail_out); + sp->read_error = 1; return (0); } diff --git a/frmts/gtiff/libtiff/tif_zstd.c b/frmts/gtiff/libtiff/tif_zstd.c index 5aaf4c44bb3a..fc73ce9cf53e 100644 --- a/frmts/gtiff/libtiff/tif_zstd.c +++ b/frmts/gtiff/libtiff/tif_zstd.c @@ -146,6 +146,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, &in_buffer); if (ZSTD_isError(zstd_ret)) { + memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos); TIFFErrorExtR(tif, module, "Error in ZSTD_decompressStream(): %s", ZSTD_getErrorName(zstd_ret)); return 0; @@ -155,6 +156,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (out_buffer.pos < (size_t)occ) { + memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos); TIFFErrorExtR(tif, module, "Not enough data at scanline %lu (short %lu bytes)", (unsigned long)tif->tif_row,