static void JBIGOutputBie(unsigned char* buffer, size_t len, void* userData) { TIFF* tif = (TIFF*)userData; if (isFillOrder(tif, tif->tif_dir.td_fillorder)) { TIFFReverseBits(buffer, (tmsize_t)len); } JBIGCopyEncodedData(tif, buffer, len, 0); }
static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) { struct jbg_dec_state decoder; int decodeStatus = 0; unsigned char* pImage = NULL; (void) size, (void) s; if (isFillOrder(tif, tif->tif_dir.td_fillorder)) { TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); } jbg_dec_init(&decoder); #if defined(HAVE_JBG_NEWLEN) jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize); /* * I do not check the return status of jbg_newlen because even if this * function fails it does not necessarily mean that decoding the image * will fail. It is generally only needed for received fax images * that do not contain the actual length of the image in the BIE * header. I do not log when an error occurs because that will cause * problems when converting JBIG encoded TIFF's to * PostScript. As long as the actual image length is contained in the * BIE header jbg_dec_in should succeed. */ #endif /* HAVE_JBG_NEWLEN */ decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata, (size_t)tif->tif_rawdatasize, NULL); if (JBG_EOK != decodeStatus) { /* * XXX: JBG_EN constant was defined in pre-2.0 releases of the * JBIG-KIT. Since the 2.0 the error reporting functions were * changed. We will handle both cases here. */ TIFFErrorExt(tif->tif_clientdata, "JBIG", "Error (%d) decoding: %s", decodeStatus, #if defined(JBG_EN) jbg_strerror(decodeStatus, JBG_EN) #else jbg_strerror(decodeStatus) #endif ); return 0; } pImage = jbg_dec_getimage(&decoder, 0); _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); jbg_dec_free(&decoder); return 1; }
/* * Internal version of TIFFFlushData that can be * called by ``encodestrip routines'' w/o concern * for infinite recursion. */ int TIFFFlushData1(TIFF* tif) { if (tif->tif_rawcc > 0) { if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, tif->tif_rawdata, tif->tif_rawcc)) return (0); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } return (1); }
/* * Read a tile of data and decompress the specified * amount into the user-supplied buffer. */ tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) { static const char module[] = "TIFFReadEncodedTile"; TIFFDirectory *td = &tif->tif_dir; tmsize_t tilesize = tif->tif_tilesize; 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)); } /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE && size!=(tmsize_t)(-1) && size >= tilesize && !isMapped(tif) && ((tif->tif_flags&TIFF_NOREADRAW)==0) ) { if (TIFFReadRawTile1(tif, tile, buf, tilesize, module) != tilesize) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(buf,tilesize); (*tif->tif_postdecode)(tif,buf,tilesize); return (tilesize); } if (size == (tmsize_t)(-1)) size = tilesize; else if (size > tilesize) size = tilesize; if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, (uint8*) buf, size, (uint16)(tile/td->td_stripsperimage))) { (*tif->tif_postdecode)(tif, (uint8*) buf, size); return (size); } else return ((tmsize_t)(-1)); }
static int JBIGDecode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s) { struct jbg_dec_state decoder; int decodeStatus = 0; unsigned char* pImage = NULL; (void) size, (void) s; if (isFillOrder(tif, tif->tif_dir.td_fillorder)) { TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); } jbg_dec_init(&decoder); #if defined(HAVE_JBG_NEWLEN) jbg_newlen(tif->tif_rawdata, tif->tif_rawdatasize); /* * I do not check the return status of jbg_newlen because even if this * function fails it does not necessarily mean that decoding the image * will fail. It is generally only needed for received fax images * that do not contain the actual length of the image in the BIE * header. I do not log when an error occurs because that will cause * problems when converting JBIG encoded TIFF's to * PostScript. As long as the actual image length is contained in the * BIE header jbg_dec_in should succeed. */ #endif /* HAVE_JBG_NEWLEN */ decodeStatus = jbg_dec_in(&decoder, tif->tif_rawdata, tif->tif_rawdatasize, NULL); if (JBG_EOK != decodeStatus) { TIFFError("JBIG", "Error (%d) decoding: %s", decodeStatus, jbg_strerror(decodeStatus, JBG_EN)); return 0; } pImage = jbg_dec_getimage(&decoder, 0); _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); jbg_dec_free(&decoder); return 1; }
/* * 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 && size!=(tmsize_t)(-1) && size >= stripsize && !isMapped(tif) && ((tif->tif_flags&TIFF_NOREADRAW)==0) ) { if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(buf,stripsize); (*tif->tif_postdecode)(tif,buf,stripsize); return (stripsize); } if ((size!=(tmsize_t)(-1))&&(size<stripsize)) stripsize=size; if (!TIFFFillStrip(tif,strip)) return((tmsize_t)(-1)); if ((*tif->tif_decodestrip)(tif,buf,stripsize,plane)<=0) return((tmsize_t)(-1)); (*tif->tif_postdecode)(tif,buf,stripsize); return(stripsize); }
/* * Internal version of TIFFFlushData that can be * called by ``encodestrip routines'' w/o concern * for infinite recursion. */ int TIFFFlushData1(TIFF* tif) { if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) { if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); 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; } return (1); }
/* * 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) { TIFFError(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))) { /* * 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; if ( td->td_stripoffset[tile] + bytecount > tif->tif_size) { tif->tif_curtile = NOTILE; 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) { TIFFError(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 (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)); }
/* * 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) { TIFFError(tif->tif_name, "%lu: Invalid strip byte count, strip %lu", (u_long) bytecount, (u_long) strip); return (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; 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. */ TIFFError(module, "%s: Read error on strip %lu; got %lu bytes, expected %lu", tif->tif_name, (u_long) strip, (u_long) tif->tif_size - td->td_stripoffset[strip], (u_long) bytecount); tif->tif_curstrip = NOSTRIP; 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) { TIFFError(module, "%s: Data buffer too small to hold strip %lu", tif->tif_name, (u_long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, TIFFroundup(bytecount, 1024))) return (0); } if (TIFFReadRawStrip1(tif, strip, (u_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)); }
/* * 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, uint32 strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[strip]; if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %I64u, strip %lu", (unsigned __int64) bytecount, (unsigned long) strip); #else TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %llu, strip %lu", (unsigned long long) bytecount, (unsigned long) strip); #endif return (0); } /* To avoid excessive memory allocations: */ /* Byte count should normally not be larger than a number of */ /* times the uncompressed size plus some margin */ if( bytecount > 1024 * 1024 ) { /* 10 and 4096 are just values that could be adjusted. */ /* Hopefully they are safe enough for all codecs */ tmsize_t stripsize = TIFFStripSize(tif); if( stripsize != 0 && (bytecount - 4096) / 10 > (uint64)stripsize ) { uint64 newbytecount = (uint64)stripsize * 10 + 4096; if( (int64)newbytecount >= 0 ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFWarningExt(tif->tif_clientdata, module, "Too large strip byte count %I64u, strip %lu. Limiting to %I64u", (unsigned __int64) bytecount, (unsigned long) strip, (unsigned __int64) newbytecount); #else TIFFErrorExt(tif->tif_clientdata, module, "Too large strip byte count %llu, strip %lu. Limiting to %llu", (unsigned long long) bytecount, (unsigned long) strip, (unsigned long long) newbytecount); #endif bytecount = newbytecount; } } } if (isMapped(tif)) { /* * 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 > (uint64)tif->tif_size || td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { /* * This error message might seem strange, but * it's what would happen if a read were done * instead. */ #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %I64u bytes, expected %I64u", (unsigned long) strip, (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], (unsigned __int64) bytecount); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %llu bytes, expected %llu", (unsigned long) strip, (unsigned long long) tif->tif_size - td->td_stripoffset[strip], (unsigned long long) bytecount); #endif tif->tif_curstrip = NOSTRIP; return (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_rawdata = NULL; tif->tif_rawdatasize = 0; } tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; /* * When we have tif_rawdata reference directly into the memory mapped file * we need to be pretty careful about how we use the rawdata. It is not * a general purpose working buffer as it normally otherwise is. So we * keep track of this fact to avoid using it improperly. */ tif->tif_flags |= TIFF_BUFFERMMAP; } 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?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold strip %lu", (unsigned long) strip); return (0); } } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curstrip = NOSTRIP; tif->tif_rawdata = NULL; tif->tif_rawdatasize = 0; tif->tif_flags &= ~TIFF_BUFFERMMAP; } if( isMapped(tif) ) { if (bytecountm > tif->tif_rawdatasize && !TIFFReadBufferSetup(tif, 0, bytecountm)) { return (0); } if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, bytecountm, module) != bytecountm) { return (0); } } else { if (TIFFReadRawStripOrTile2(tif, strip, 1, bytecountm, module) != bytecountm) { return (0); } } tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecountm); } } return (TIFFStartStrip(tif, strip)); }
static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { static const char module[] = "TIFFFillStripPartial"; register TIFFDirectory *td = &tif->tif_dir; tmsize_t unused_data; uint64 read_offset; tmsize_t to_read; tmsize_t read_ahead_mod; /* tmsize_t bytecountm; */ if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; /* * 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?). */ /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ /* Not completely sure where the * 2 comes from, but probably for */ /* an exponentional growth strategy of tif_rawdatasize */ if( read_ahead < TIFF_TMSIZE_T_MAX / 2 ) read_ahead_mod = read_ahead * 2; else read_ahead_mod = read_ahead; if (read_ahead_mod > tif->tif_rawdatasize) { assert( restart ); tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold part of strip %lu", (unsigned long) strip); return (0); } } if( restart ) { tif->tif_rawdataloaded = 0; tif->tif_rawdataoff = 0; } /* ** If we are reading more data, move any unused data to the ** start of the buffer. */ if( tif->tif_rawdataloaded > 0 ) unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata); else unused_data = 0; if( unused_data > 0 ) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data ); } /* ** Seek to the point in the file where more data should be read. */ read_offset = td->td_stripoffset[strip] + tif->tif_rawdataoff + tif->tif_rawdataloaded; if (!SeekOK(tif, read_offset)) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); return 0; } /* ** How much do we want to read? */ if( read_ahead_mod > tif->tif_rawdatasize ) to_read = read_ahead_mod - unused_data; else to_read = tif->tif_rawdatasize - unused_data; if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { to_read = (tmsize_t) td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded; } assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); if( !TIFFReadAndRealloc( tif, to_read, unused_data, 1, /* is_strip */ 0, /* strip_or_tile */ module) ) { return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcp = tif->tif_rawdata; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); TIFFReverseBits(tif->tif_rawdata + unused_data, to_read ); } /* ** When starting a strip from the beginning we need to ** restart the decoder. */ if( restart ) { #ifdef JPEG_SUPPORT /* A bit messy since breaks the codec abstraction. Ultimately */ /* there should be a function pointer for that, but it seems */ /* only JPEG is affected. */ /* For JPEG, if there are multiple scans (can generally be known */ /* with the read_ahead used), we need to read the whole strip */ if( tif->tif_dir.td_compression==COMPRESSION_JPEG && (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] ) { if( TIFFJPEGIsFullStripRequired(tif) ) { return TIFFFillStrip(tif, strip); } } #endif return TIFFStartStrip(tif, strip); } else { return 1; } }
/* * 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, uint32 strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[strip]; if ((int64)bytecount <= 0) { TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count " TIFF_UINT64_FORMAT ", strip %lu", (TIFF_UINT64_T) bytecount, (unsigned long) strip); return (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_rawdata = NULL; tif->tif_rawdatasize = 0; } 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 > (uint64)tif->tif_size || td->td_stripoffset[strip] > (uint64)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, "Read error on strip %lu; " "got " TIFF_UINT64_FORMAT " bytes, expected " TIFF_UINT64_FORMAT, (unsigned long) strip, (TIFF_UINT64_T) tif->tif_size - td->td_stripoffset[strip], (TIFF_UINT64_T) bytecount); tif->tif_curstrip = NOSTRIP; return (0); } tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; /* * When we have tif_rawdata reference directly into the memory mapped file * we need to be pretty careful about how we use the rawdata. It is not * a general purpose working buffer as it normally otherwise is. So we * keep track of this fact to avoid using it improperly. */ tif->tif_flags |= TIFF_BUFFERMMAP; } 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?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curstrip = NOSTRIP; if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, bytecountm, module) != bytecountm) return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecountm); } } return (TIFFStartStrip(tif, strip)); }
/* * Encode the supplied data and write it to the * specified tile. There must be space for the * data. The function clamps individual writes * to a tile to the tile size, but does not (and * can not) check that multiple writes to the same * tile do not write more than tile size data. * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ tsize_t TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) { static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; tsample_t sample; if (!WRITECHECKTILES(tif, module)) return ((tsize_t) -1); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tsize_t) -1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tsize_t) -1); tif->tif_curtile = tile; tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; if( td->td_stripbytecount[tile] > 0 ) { /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } /* * Compute tiles per row & per column to compute * current row and column */ tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) * td->td_tilelength; tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) * td->td_tilewidth; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; sample = (tsample_t)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tsize_t) -1); /* * Clamp write amount to the tile size. This is mostly * done so that callers can pass in some large number * (e.g. -1) and have the tile size used instead. */ if ( cc < 1 || cc > tif->tif_tilesize) cc = tif->tif_tilesize; /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (tidata_t) data, cc ); if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) return ((tsize_t) 0); if (!(*tif->tif_postencode)(tif)) return ((tsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) return ((tsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Encode the supplied data and write it to the * specified strip. * * NB: Image length must be setup before writing. */ tsize_t TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) { static const char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; tsample_t sample; if (!WRITECHECKSTRIPS(tif, module)) return ((tsize_t) -1); /* * Check strip array to make sure there's space. * We don't support dynamically growing files that * have data organized in separate bitplanes because * it's too painful. In that case we require that * the imagelength be set properly before the first * write (so that the strips array will be fully * allocated above). */ if (strip >= td->td_nstrips) { if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not grow image by strips when using separate planes"); return ((tsize_t) -1); } if (!TIFFGrowStrips(tif, 1, module)) return ((tsize_t) -1); td->td_stripsperimage = TIFFhowmany(td->td_imagelength, td->td_rowsperstrip); } /* * Handle delayed allocation of data buffer. This * permits it to be sized according to the directory * info. */ if (!BUFFERCHECK(tif)) return ((tsize_t) -1); tif->tif_curstrip = strip; tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; if( td->td_stripbytecount[strip] > 0 ) { /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_flags &= ~TIFF_POSTENCODE; sample = (tsample_t)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tsize_t) -1); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (tidata_t) data, cc ); if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) return ((tsize_t) 0); if (!(*tif->tif_postencode)(tif)) return ((tsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) return ((tsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * 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; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { /* * 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 = 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))) { /* * 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); } 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); } } return (TIFFStartTile(tif, tile)); }
/* * 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, uint32 tile) { static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[tile]; if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "%I64u: Invalid tile byte count, tile %lu", (unsigned __int64) bytecount, (unsigned long) tile); #else TIFFErrorExt(tif->tif_clientdata, module, "%llu: Invalid tile byte count, tile %lu", (unsigned long long) bytecount, (unsigned long) tile); #endif return (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_rawdata = NULL; tif->tif_rawdatasize = 0; } 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 > (uint64)tif->tif_size || td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { tif->tif_curtile = NOTILE; return (0); } tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_flags |= TIFF_BUFFERMMAP; } 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?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curtile = NOTILE; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold tile %lu", (unsigned long) tile); return (0); } if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curtile = NOTILE; if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, bytecountm, module) != bytecountm) return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdataloaded); } } return (TIFFStartTile(tif, tile)); }
static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { static const char module[] = "TIFFFillStripPartial"; register TIFFDirectory *td = &tif->tif_dir; tmsize_t unused_data; uint64 read_offset; tmsize_t cc, to_read; /* tmsize_t bytecountm; */ if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; /* * 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?). */ /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ if (read_ahead*2 > tif->tif_rawdatasize) { assert( restart ); tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold part of strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, read_ahead*2)) return (0); } if( restart ) { tif->tif_rawdataloaded = 0; tif->tif_rawdataoff = 0; } /* ** If we are reading more data, move any unused data to the ** start of the buffer. */ if( tif->tif_rawdataloaded > 0 ) unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata); else unused_data = 0; if( unused_data > 0 ) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data ); } /* ** Seek to the point in the file where more data should be read. */ read_offset = td->td_stripoffset[strip] + tif->tif_rawdataoff + tif->tif_rawdataloaded; if (!SeekOK(tif, read_offset)) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); return 0; } /* ** How much do we want to read? */ to_read = tif->tif_rawdatasize - unused_data; if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { to_read = (tmsize_t) td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded; } assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read); if (cc != to_read) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned __int64) cc, (unsigned __int64) to_read); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long long) cc, (unsigned long long) to_read); #endif return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; tif->tif_rawcp = tif->tif_rawdata; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); TIFFReverseBits(tif->tif_rawdata + unused_data, to_read ); } /* ** When starting a strip from the beginning we need to ** restart the decoder. */ if( restart ) return TIFFStartStrip(tif, strip); else return 1; }
/* * Encode the supplied data and write it to the * specified strip. * * NB: Image length must be setup before writing. */ tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; uint16 sample; if (!WRITECHECKSTRIPS(tif, module)) return ((tmsize_t) -1); /* * Check strip array to make sure there's space. * We don't support dynamically growing files that * have data organized in separate bitplanes because * it's too painful. In that case we require that * the imagelength be set properly before the first * write (so that the strips array will be fully * allocated above). */ if (strip >= td->td_nstrips) { if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { TIFFErrorExt(tif->tif_clientdata, module, "Can not grow image by strips when using separate planes"); return ((tmsize_t) -1); } if (!TIFFGrowStrips(tif, 1, module)) return ((tmsize_t) -1); td->td_stripsperimage = TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip); } /* * Handle delayed allocation of data buffer. This * permits it to be sized according to the directory * info. */ if (!BUFFERCHECK(tif)) return ((tmsize_t) -1); tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curstrip = strip; if (td->td_stripsperimage == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); return ((tmsize_t) -1); } tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tmsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } if( td->td_stripbytecount[strip] > 0 ) { /* Make sure that at the first attempt of rewriting the tile, we will have */ /* more bytes available in the output buffer than the previous byte count, */ /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] ) { if( !(TIFFWriteBufferSetup(tif, NULL, (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) ) return ((tmsize_t)(-1)); } /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; tif->tif_flags &= ~TIFF_POSTENCODE; /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE ) { /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*) data, cc); if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8*) data, cc)) return ((tmsize_t) -1); return (cc); } sample = (uint16)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t) -1); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) return ((tmsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) return ((tmsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Encode the supplied data and write it to the * specified tile. There must be space for the * data. The function clamps individual writes * to a tile to the tile size, but does not (and * can not) check that multiple writes to the same * tile do not write more than tile size data. * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; uint16 sample; uint32 howmany32; if (!WRITECHECKTILES(tif, module)) return ((tmsize_t)(-1)); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curtile = tile; if( td->td_stripbytecount[tile] > 0 ) { /* Make sure that at the first attempt of rewriting the tile, we will have */ /* more bytes available in the output buffer than the previous byte count, */ /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] ) { if( !(TIFFWriteBufferSetup(tif, NULL, (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) ) return ((tmsize_t)(-1)); } /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; /* * Compute tiles per row & per column to compute * current row and column */ howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return ((tmsize_t)(-1)); } tif->tif_row = (tile % howmany32) * td->td_tilelength; howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return ((tmsize_t)(-1)); } tif->tif_col = (tile % howmany32) * td->td_tilewidth; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; /* * Clamp write amount to the tile size. This is mostly * done so that callers can pass in some large number * (e.g. -1) and have the tile size used instead. */ if ( cc < 1 || cc > tif->tif_tilesize) cc = tif->tif_tilesize; /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE ) { /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*) data, cc); if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8*) data, cc)) return ((tmsize_t) -1); return (cc); } sample = (uint16)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t)(-1)); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) return ((tmsize_t)(-1)); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * 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, uint32 strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; _TIFFFillStriles( tif ); if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[strip]; if (bytecount <= 0) { #if defined(__WIN32__) && defined(_MSC_VER) TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %I64u, strip %lu", (unsigned __int64) bytecount, (unsigned long) strip); #else TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %llu, strip %lu", (unsigned long long) bytecount, (unsigned long) strip); #endif return (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 > (uint64)tif->tif_size || td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { /* * This error message might seem strange, but * it's what would happen if a read were done * instead. */ #if defined(__WIN32__) && defined(_MSC_VER) TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %I64u bytes, expected %I64u", (unsigned long) strip, (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], (unsigned __int64) bytecount); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %llu bytes, expected %llu", (unsigned long) strip, (unsigned long long) tif->tif_size - td->td_stripoffset[strip], (unsigned long long) bytecount); #endif tif->tif_curstrip = NOSTRIP; return (0); } tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; } 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?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, bytecountm, module) != bytecountm) return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecountm); } } return (TIFFStartStrip(tif, strip)); }
/* * Return nonzero if the data is returned in MSB-to-LSB bit order. */ int TIFFIsMSB2LSB(TIFF* tif) { return (isFillOrder(tif, FILLORDER_MSB2LSB)); }
/* * 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; uint32 rowsperstrip; uint32 stripsperplane; uint32 stripinplane; uint16 plane; uint32 rows; tmsize_t stripsize; if (!TIFFCheckRead(tif,0)) return((tmsize_t)(-1)); if (strip>=td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata,module, "%lu: Strip out of range, max %lu",(unsigned long)strip, (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); rows=td->td_imagelength-stripinplane*rowsperstrip; if (rows>rowsperstrip) rows=rowsperstrip; stripsize=TIFFVStripSize(tif,rows); if (stripsize==0) return((tmsize_t)(-1)); /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE && size!=(tmsize_t)(-1) && size >= stripsize && !isMapped(tif) && ((tif->tif_flags&TIFF_NOREADRAW)==0) ) { if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(buf,stripsize); (*tif->tif_postdecode)(tif,buf,stripsize); return (stripsize); } if ((size!=(tmsize_t)(-1))&&(size<stripsize)) stripsize=size; if (!TIFFFillStrip(tif,strip)) return((tmsize_t)(-1)); if ((*tif->tif_decodestrip)(tif,buf,stripsize,plane)<=0) return((tmsize_t)(-1)); (*tif->tif_postdecode)(tif,buf,stripsize); return(stripsize); }