diff options
Diffstat (limited to 'src/libtiff/tif_read.c')
-rw-r--r-- | src/libtiff/tif_read.c | 375 |
1 files changed, 233 insertions, 142 deletions
diff --git a/src/libtiff/tif_read.c b/src/libtiff/tif_read.c index 7bc580e..888e4d7 100644 --- a/src/libtiff/tif_read.c +++ b/src/libtiff/tif_read.c @@ -1,4 +1,4 @@ -/* $Id: tif_read.c,v 1.1 2008/10/17 06:16:07 scuri Exp $ */ +/* $Id: tif_read.c,v 1.2 2009/08/21 04:01:59 scuri Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -50,8 +50,10 @@ TIFFSeek(TIFF* tif, uint32 row, tsample_t sample) tstrip_t strip; if (row >= td->td_imagelength) { /* out of range */ - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Row out of range, max %lu", - (unsigned long) row, (unsigned long) td->td_imagelength); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Row out of range, max %lu", + (unsigned long) row, + (unsigned long) td->td_imagelength); return (0); } if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { @@ -64,7 +66,7 @@ TIFFSeek(TIFF* tif, uint32 row, tsample_t sample) strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; - if (strip != tif->tif_curstrip) { /* different strip, refill */ + if (strip != tif->tif_curstrip) { /* different strip, refill */ if (!TIFFFillStrip(tif, strip)) return (0); } else if (row < tif->tif_row) { @@ -104,8 +106,8 @@ TIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) e = (*tif->tif_decoderow) (tif, (tidata_t) buf, tif->tif_scanlinesize, sample); - /* we are now poised at the beginning of the next row */ - tif->tif_row = row + 1; + /* we are now poised at the beginning of the next row */ + tif->tif_row = row + 1; if (e) (*tif->tif_postdecode)(tif, (tidata_t) buf, @@ -129,22 +131,23 @@ TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) if (!TIFFCheckRead(tif, 0)) return (-1); if (strip >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%ld: Strip out of range, max %ld", - (long) strip, (long) td->td_nstrips); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%ld: Strip out of range, max %ld", + (long) strip, (long) td->td_nstrips); return (-1); } /* * Calculate the strip size according to the number of * rows in the strip (check for truncated last strip on any - * of the separations). + * of the separations). */ - if( td->td_rowsperstrip >= td->td_imagelength ) - strips_per_sep = 1; - else - strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1) - / td->td_rowsperstrip; + if( td->td_rowsperstrip >= td->td_imagelength ) + strips_per_sep = 1; + else + strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1) + / td->td_rowsperstrip; - sep_strip = strip % strips_per_sep; + sep_strip = strip % strips_per_sep; if (sep_strip != strips_per_sep-1 || (nrows = td->td_imagelength % td->td_rowsperstrip) == 0) @@ -155,9 +158,9 @@ TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) size = stripsize; else if (size > stripsize) size = stripsize; - if (TIFFFillStrip(tif, strip) - && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size, - (tsample_t)(strip / td->td_stripsperimage)) > 0 ) { + if (TIFFFillStrip(tif, strip) + && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size, + (tsample_t)(strip / td->td_stripsperimage)) > 0 ) { (*tif->tif_postdecode)(tif, (tidata_t) buf, size); return (size); } else @@ -170,6 +173,7 @@ TIFFReadRawStrip1(TIFF* tif, { TIFFDirectory *td = &tif->tif_dir; + assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tsize_t cc; @@ -215,13 +219,27 @@ TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) { static const char module[] = "TIFFReadRawStrip"; TIFFDirectory *td = &tif->tif_dir; - tsize_t bytecount; + /* + * FIXME: butecount should have tsize_t type, but for now libtiff + * defines tsize_t as a signed 32-bit integer and we are losing + * ability to read arrays larger than 2^31 bytes. So we are using + * uint32 instead of tsize_t here. + */ + uint32 bytecount; if (!TIFFCheckRead(tif, 0)) return ((tsize_t) -1); if (strip >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Strip out of range, max %lu", - (unsigned long) strip, (unsigned long) td->td_nstrips); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Strip out of range, max %lu", + (unsigned long) strip, + (unsigned long) td->td_nstrips); + return ((tsize_t) -1); + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme does not support access to raw uncompressed data"); return ((tsize_t) -1); } bytecount = td->td_stripbytecount[strip]; @@ -231,88 +249,110 @@ TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) (unsigned long) bytecount, (unsigned long) strip); return ((tsize_t) -1); } - if (size != (tsize_t)-1 && size < bytecount) + if (size != (tsize_t)-1 && (uint32)size < bytecount) bytecount = size; return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module)); } /* - * Read the specified strip and setup for decoding. - * The data buffer is expanded, as necessary, to - * hold the strip's data. + * Read the specified strip and setup for decoding. The data buffer is + * expanded, as necessary, to hold the strip's data. */ int TIFFFillStrip(TIFF* tif, tstrip_t strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; - tsize_t bytecount; - bytecount = td->td_stripbytecount[strip]; - if (bytecount <= 0) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Invalid strip byte count, strip %lu", - (unsigned long) bytecount, (unsigned long) strip); - return (0); - } - if (isMapped(tif) && - (isFillOrder(tif, td->td_fillorder) - || (tif->tif_flags & TIFF_NOBITREV))) { + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { /* - * The image is mapped into memory and we either don't - * need to flip bits or the compression routine is going - * to handle this operation itself. In this case, avoid - * copying the raw data and instead just reference the - * data from the memory mapped file image. This assumes - * that the decompression routines do not modify the - * contents of the raw data buffer (if they try to, - * the application will get a fault since the file is - * mapped read-only). + * FIXME: butecount should have tsize_t type, but for now + * libtiff defines tsize_t as a signed 32-bit integer and we + * are losing ability to read arrays larger than 2^31 bytes. + * So we are using uint32 instead of tsize_t here. */ - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) - _TIFFfree(tif->tif_rawdata); - tif->tif_flags &= ~TIFF_MYBUFFER; - if ( td->td_stripoffset[strip] + bytecount > tif->tif_size) { - /* - * This error message might seem strange, but it's - * what would happen if a read were done instead. - */ + uint32 bytecount = td->td_stripbytecount[strip]; + if (bytecount <= 0) { TIFFErrorExt(tif->tif_clientdata, module, - "%s: Read error on strip %lu; got %lu bytes, expected %lu", - tif->tif_name, - (unsigned long) strip, - (unsigned long) tif->tif_size - td->td_stripoffset[strip], - (unsigned long) bytecount); - tif->tif_curstrip = NOSTRIP; + "%s: Invalid strip byte count %lu, strip %lu", + tif->tif_name, (unsigned long) bytecount, + (unsigned long) strip); return (0); } - tif->tif_rawdatasize = bytecount; - tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; - } else { - /* - * Expand raw data buffer, if needed, to - * hold data strip coming from file - * (perhaps should set upper bound on - * the size of a buffer we'll use?). - */ - if (bytecount > tif->tif_rawdatasize) { - tif->tif_curstrip = NOSTRIP; - if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[strip]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > tif->tif_size || + td->td_stripoffset[strip] > tif->tif_size - bytecount) { + /* + * This error message might seem strange, but + * it's what would happen if a read were done + * instead. + */ TIFFErrorExt(tif->tif_clientdata, module, - "%s: Data buffer too small to hold strip %lu", - tif->tif_name, (unsigned long) strip); + + "%s: Read error on strip %lu; " + "got %lu bytes, expected %lu", + tif->tif_name, (unsigned long) strip, + (unsigned long) tif->tif_size - td->td_stripoffset[strip], + (unsigned long) bytecount); + tif->tif_curstrip = NOSTRIP; return (0); } - if (!TIFFReadBufferSetup(tif, 0, - TIFFroundup(bytecount, 1024))) + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * strip coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + if (bytecount > (uint32)tif->tif_rawdatasize) { + tif->tif_curstrip = NOSTRIP; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, + module, + "%s: Data buffer too small to hold strip %lu", + tif->tif_name, + (unsigned long) strip); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if ((uint32)TIFFReadRawStrip1(tif, strip, + (unsigned char *)tif->tif_rawdata, + bytecount, module) != bytecount) return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); } - if (TIFFReadRawStrip1(tif, strip, (unsigned char *)tif->tif_rawdata, - bytecount, module) != bytecount) - return (0); - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits(tif->tif_rawdata, bytecount); } return (TIFFStartStrip(tif, strip)); } @@ -349,8 +389,9 @@ TIFFReadEncodedTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) if (!TIFFCheckRead(tif, 1)) return (-1); if (tile >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%ld: Tile out of range, max %ld", - (long) tile, (unsigned long) td->td_nstrips); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%ld: Tile out of range, max %ld", + (long) tile, (unsigned long) td->td_nstrips); return (-1); } if (size == (tsize_t) -1) @@ -371,6 +412,7 @@ TIFFReadRawTile1(TIFF* tif, { TIFFDirectory *td = &tif->tif_dir; + assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tsize_t cc; @@ -419,89 +461,121 @@ TIFFReadRawTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) { static const char module[] = "TIFFReadRawTile"; TIFFDirectory *td = &tif->tif_dir; - tsize_t bytecount; + /* + * FIXME: butecount should have tsize_t type, but for now libtiff + * defines tsize_t as a signed 32-bit integer and we are losing + * ability to read arrays larger than 2^31 bytes. So we are using + * uint32 instead of tsize_t here. + */ + uint32 bytecount; if (!TIFFCheckRead(tif, 1)) return ((tsize_t) -1); if (tile >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Tile out of range, max %lu", + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Tile out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tsize_t) -1); } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme does not support access to raw uncompressed data"); + return ((tsize_t) -1); + } bytecount = td->td_stripbytecount[tile]; - if (size != (tsize_t) -1 && size < bytecount) + if (size != (tsize_t) -1 && (uint32)size < bytecount) bytecount = size; return (TIFFReadRawTile1(tif, tile, buf, bytecount, module)); } /* - * Read the specified tile and setup for decoding. - * The data buffer is expanded, as necessary, to - * hold the tile's data. + * Read the specified tile and setup for decoding. The data buffer is + * expanded, as necessary, to hold the tile's data. */ int TIFFFillTile(TIFF* tif, ttile_t tile) { static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; - tsize_t bytecount; - bytecount = td->td_stripbytecount[tile]; - if (bytecount <= 0) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Invalid tile byte count, tile %lu", - (unsigned long) bytecount, (unsigned long) tile); - return (0); - } - if (isMapped(tif) && - (isFillOrder(tif, td->td_fillorder) - || (tif->tif_flags & TIFF_NOBITREV))) { + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { /* - * The image is mapped into memory and we either don't - * need to flip bits or the compression routine is going - * to handle this operation itself. In this case, avoid - * copying the raw data and instead just reference the - * data from the memory mapped file image. This assumes - * that the decompression routines do not modify the - * contents of the raw data buffer (if they try to, - * the application will get a fault since the file is - * mapped read-only). + * FIXME: butecount should have tsize_t type, but for now + * libtiff defines tsize_t as a signed 32-bit integer and we + * are losing ability to read arrays larger than 2^31 bytes. + * So we are using uint32 instead of tsize_t here. */ - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) - _TIFFfree(tif->tif_rawdata); - tif->tif_flags &= ~TIFF_MYBUFFER; - if ( td->td_stripoffset[tile] + bytecount > tif->tif_size) { - tif->tif_curtile = NOTILE; + uint32 bytecount = td->td_stripbytecount[tile]; + if (bytecount <= 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Invalid tile byte count, tile %lu", + (unsigned long) bytecount, (unsigned long) tile); return (0); } - tif->tif_rawdatasize = bytecount; - tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile]; - } else { - /* - * Expand raw data buffer, if needed, to - * hold data tile coming from file - * (perhaps should set upper bound on - * the size of a buffer we'll use?). - */ - if (bytecount > tif->tif_rawdatasize) { - tif->tif_curtile = NOTILE; - if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Data buffer too small to hold tile %ld", - tif->tif_name, (long) tile); + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[tile]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > tif->tif_size || + td->td_stripoffset[tile] > tif->tif_size - bytecount) { + tif->tif_curtile = NOTILE; return (0); } - if (!TIFFReadBufferSetup(tif, 0, - TIFFroundup(bytecount, 1024))) + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = + tif->tif_base + td->td_stripoffset[tile]; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * tile coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + if (bytecount > (uint32)tif->tif_rawdatasize) { + tif->tif_curtile = NOTILE; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, + module, + "%s: Data buffer too small to hold tile %ld", + tif->tif_name, + (long) tile); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if ((uint32)TIFFReadRawTile1(tif, tile, + (unsigned char *)tif->tif_rawdata, + bytecount, module) != bytecount) return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); } - if (TIFFReadRawTile1(tif, tile, - (unsigned char *)tif->tif_rawdata, - bytecount, module) != bytecount) - return (0); - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits(tif->tif_rawdata, bytecount); } return (TIFFStartTile(tif, tile)); } @@ -520,6 +594,7 @@ TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) { static const char module[] = "TIFFReadBufferSetup"; + assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (tif->tif_rawdata) { if (tif->tif_flags & TIFF_MYBUFFER) _TIFFfree(tif->tif_rawdata); @@ -560,8 +635,16 @@ TIFFStartStrip(TIFF* tif, tstrip_t strip) } tif->tif_curstrip = strip; tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = td->td_stripbytecount[strip]; + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[strip]; + } return ((*tif->tif_predecode)(tif, (tsample_t)(strip / td->td_stripsperimage))); } @@ -587,8 +670,16 @@ TIFFStartTile(TIFF* tif, ttile_t tile) tif->tif_col = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) * td->td_tilewidth; - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = td->td_stripbytecount[tile]; + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[tile]; + } return ((*tif->tif_predecode)(tif, (tsample_t)(tile/td->td_stripsperimage))); } |