[LIBTIFF] Update to version 4.1.0. CORE-16550

This commit is contained in:
Thomas Faber 2019-12-08 12:36:30 +01:00
parent 18a6d7c36f
commit f87faf6703
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
28 changed files with 1868 additions and 866 deletions

View file

@ -40,7 +40,7 @@
#include "tif_fax3.h" #include "tif_fax3.h"
#ifndef HAVE_GETOPT #ifndef HAVE_GETOPT
extern int getopt(int, char**, char*); extern int getopt(int argc, char * const argv[], const char *optstring);
#endif #endif
#define streq(a,b) (strcmp(a,b) == 0) #define streq(a,b) (strcmp(a,b) == 0)

View file

@ -31,31 +31,66 @@
#include <precomp.h> #include <precomp.h>
#include "tif_predict.h" #include "tif_predict.h"
#include <math.h> #include <math.h>
#include <float.h>
uint32 uint32
_TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where) _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where)
{ {
uint32 bytes = first * second; if (second && first > TIFF_UINT32_MAX / second) {
if (second && bytes / second != first) {
TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
bytes = 0; return 0;
} }
return bytes; return first * second;
} }
uint64 uint64
_TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where) _TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where)
{ {
uint64 bytes = first * second; if (second && first > TIFF_UINT64_MAX / second) {
if (second && bytes / second != first) {
TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
bytes = 0; return 0;
} }
return bytes; return first * second;
}
tmsize_t
_TIFFMultiplySSize(TIFF* tif, tmsize_t first, tmsize_t second, const char* where)
{
if( first <= 0 || second <= 0 )
{
if( tif != NULL && where != NULL )
{
TIFFErrorExt(tif->tif_clientdata, where,
"Invalid argument to _TIFFMultiplySSize() in %s", where);
}
return 0;
}
if( first > TIFF_TMSIZE_T_MAX / second )
{
if( tif != NULL && where != NULL )
{
TIFFErrorExt(tif->tif_clientdata, where,
"Integer overflow in %s", where);
}
return 0;
}
return first * second;
}
tmsize_t _TIFFCastUInt64ToSSize(TIFF* tif, uint64 val, const char* module)
{
if( val > (uint64)TIFF_TMSIZE_T_MAX )
{
if( tif != NULL && module != NULL )
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
}
return 0;
}
return (tmsize_t)val;
} }
void* void*
@ -63,13 +98,14 @@ _TIFFCheckRealloc(TIFF* tif, void* buffer,
tmsize_t nmemb, tmsize_t elem_size, const char* what) tmsize_t nmemb, tmsize_t elem_size, const char* what)
{ {
void* cp = NULL; void* cp = NULL;
tmsize_t bytes = nmemb * elem_size; tmsize_t count = _TIFFMultiplySSize(tif, nmemb, elem_size, NULL);
/* /*
* XXX: Check for integer overflow. * Check for integer overflow.
*/ */
if (nmemb && elem_size && bytes / elem_size == nmemb) if (count != 0)
cp = _TIFFrealloc(buffer, bytes); {
cp = _TIFFrealloc(buffer, count);
}
if (cp == NULL) { if (cp == NULL) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
@ -358,6 +394,15 @@ _TIFFUInt64ToDouble(uint64 ui64)
} }
} }
float _TIFFClampDoubleToFloat( double val )
{
if( val > FLT_MAX )
return FLT_MAX;
if( val < -FLT_MAX )
return -FLT_MAX;
return (float)val;
}
int _TIFFSeekOK(TIFF* tif, toff_t off) int _TIFFSeekOK(TIFF* tif, toff_t off)
{ {
/* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */

View file

@ -47,8 +47,8 @@ setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
*vpp = 0; *vpp = 0;
} }
if (vp) { if (vp) {
tmsize_t bytes = (tmsize_t)(nmemb * elem_size); tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
if (elem_size && bytes / elem_size == nmemb) if (bytes)
*vpp = (void*) _TIFFmalloc(bytes); *vpp = (void*) _TIFFmalloc(bytes);
if (*vpp) if (*vpp)
_TIFFmemcpy(*vpp, vp, bytes); _TIFFmemcpy(*vpp, vp, bytes);
@ -88,13 +88,15 @@ setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
* Install extra samples information. * Install extra samples information.
*/ */
static int static int
setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) setExtraSamples(TIFF* tif, va_list ap, uint32* v)
{ {
/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */ /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
#define EXTRASAMPLE_COREL_UNASSALPHA 999 #define EXTRASAMPLE_COREL_UNASSALPHA 999
uint16* va; uint16* va;
uint32 i; uint32 i;
TIFFDirectory* td = &tif->tif_dir;
static const char module[] = "setExtraSamples";
*v = (uint16) va_arg(ap, uint16_vap); *v = (uint16) va_arg(ap, uint16_vap);
if ((uint16) *v > td->td_samplesperpixel) if ((uint16) *v > td->td_samplesperpixel)
@ -116,6 +118,18 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
return 0; return 0;
} }
} }
if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) &&
!(td->td_samplesperpixel - td->td_extrasamples > 1))
{
TIFFWarningExt(tif->tif_clientdata,module,
"ExtraSamples tag value is changing, "
"but TransferFunction was read with a different value. Cancelling it");
TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
_TIFFfree(td->td_transferfunction[0]);
td->td_transferfunction[0] = NULL;
}
td->td_extrasamples = (uint16) *v; td->td_extrasamples = (uint16) *v;
_TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
return 1; return 1;
@ -153,15 +167,6 @@ bad:
return (0); return (0);
} }
static float TIFFClampDoubleToFloat( double val )
{
if( val > FLT_MAX )
return FLT_MAX;
if( val < -FLT_MAX )
return -FLT_MAX;
return (float)val;
}
static int static int
_TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
{ {
@ -285,6 +290,18 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFfree(td->td_smaxsamplevalue); _TIFFfree(td->td_smaxsamplevalue);
td->td_smaxsamplevalue = NULL; td->td_smaxsamplevalue = NULL;
} }
/* Test if 3 transfer functions instead of just one are now needed
See http://bugzilla.maptools.org/show_bug.cgi?id=2820 */
if( td->td_transferfunction[0] != NULL && (v - td->td_extrasamples > 1) &&
!(td->td_samplesperpixel - td->td_extrasamples > 1))
{
TIFFWarningExt(tif->tif_clientdata,module,
"SamplesPerPixel tag value is changing, "
"but TransferFunction was read with a different value. Cancelling it");
TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
_TIFFfree(td->td_transferfunction[0]);
td->td_transferfunction[0] = NULL;
}
} }
td->td_samplesperpixel = (uint16) v; td->td_samplesperpixel = (uint16) v;
break; break;
@ -320,13 +337,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_xresolution = TIFFClampDoubleToFloat( dblval ); td->td_xresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_YRESOLUTION: case TIFFTAG_YRESOLUTION:
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_yresolution = TIFFClampDoubleToFloat( dblval ); td->td_yresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_PLANARCONFIG: case TIFFTAG_PLANARCONFIG:
v = (uint16) va_arg(ap, uint16_vap); v = (uint16) va_arg(ap, uint16_vap);
@ -335,10 +352,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
td->td_planarconfig = (uint16) v; td->td_planarconfig = (uint16) v;
break; break;
case TIFFTAG_XPOSITION: case TIFFTAG_XPOSITION:
td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_YPOSITION: case TIFFTAG_YPOSITION:
td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_RESOLUTIONUNIT: case TIFFTAG_RESOLUTIONUNIT:
v = (uint16) va_arg(ap, uint16_vap); v = (uint16) va_arg(ap, uint16_vap);
@ -361,7 +378,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
break; break;
case TIFFTAG_EXTRASAMPLES: case TIFFTAG_EXTRASAMPLES:
if (!setExtraSamples(td, ap, &v)) if (!setExtraSamples(tif, ap, &v))
goto badvalue; goto badvalue;
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
@ -684,7 +701,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
case TIFF_SRATIONAL: case TIFF_SRATIONAL:
case TIFF_FLOAT: case TIFF_FLOAT:
{ {
float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double));
_TIFFmemcpy(val, &v2, tv_size); _TIFFmemcpy(val, &v2, tv_size);
} }
break; break;
@ -1002,12 +1019,12 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
case TIFFTAG_STRIPOFFSETS: case TIFFTAG_STRIPOFFSETS:
case TIFFTAG_TILEOFFSETS: case TIFFTAG_TILEOFFSETS:
_TIFFFillStriles( tif ); _TIFFFillStriles( tif );
*va_arg(ap, uint64**) = td->td_stripoffset; *va_arg(ap, uint64**) = td->td_stripoffset_p;
break; break;
case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_STRIPBYTECOUNTS:
case TIFFTAG_TILEBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS:
_TIFFFillStriles( tif ); _TIFFFillStriles( tif );
*va_arg(ap, uint64**) = td->td_stripbytecount; *va_arg(ap, uint64**) = td->td_stripbytecount_p;
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
*va_arg(ap, uint16*) = *va_arg(ap, uint16*) =
@ -1266,8 +1283,9 @@ TIFFFreeDirectory(TIFF* tif)
CleanupField(td_transferfunction[0]); CleanupField(td_transferfunction[0]);
CleanupField(td_transferfunction[1]); CleanupField(td_transferfunction[1]);
CleanupField(td_transferfunction[2]); CleanupField(td_transferfunction[2]);
CleanupField(td_stripoffset); CleanupField(td_stripoffset_p);
CleanupField(td_stripbytecount); CleanupField(td_stripbytecount_p);
td->td_stripoffsetbyteallocsize = 0;
TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
@ -1280,10 +1298,8 @@ TIFFFreeDirectory(TIFF* tif)
td->td_customValueCount = 0; td->td_customValueCount = 0;
CleanupField(td_customValues); CleanupField(td_customValues);
#if defined(DEFER_STRILE_LOAD)
_TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
_TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
#endif
} }
#undef CleanupField #undef CleanupField
@ -1371,7 +1387,9 @@ TIFFDefaultDirectory(TIFF* tif)
td->td_tilewidth = 0; td->td_tilewidth = 0;
td->td_tilelength = 0; td->td_tilelength = 0;
td->td_tiledepth = 1; td->td_tiledepth = 1;
#ifdef STRIPBYTECOUNTSORTED_UNUSED
td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
#endif
td->td_resolutionunit = RESUNIT_INCH; td->td_resolutionunit = RESUNIT_INCH;
td->td_sampleformat = SAMPLEFORMAT_UINT; td->td_sampleformat = SAMPLEFORMAT_UINT;
td->td_imagedepth = 1; td->td_imagedepth = 1;

File diff suppressed because it is too large Load diff

View file

@ -182,6 +182,51 @@ TIFFWriteDirectory(TIFF* tif)
return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL);
} }
/*
* This is an advanced writing function that must be used in a particular
* sequence, and generally together with TIFFForceStrileArrayWriting(),
* to make its intended effect. Its aim is to modify the location
* where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file.
* More precisely, when TIFFWriteCheck() will be called, the tag entries for
* those arrays will be written with type = count = offset = 0 as a temporary
* value.
*
* Its effect is only valid for the current directory, and before
* TIFFWriteDirectory() is first called, and will be reset when
* changing directory.
*
* The typical sequence of calls is:
* TIFFOpen()
* [ TIFFCreateDirectory(tif) ]
* Set fields with calls to TIFFSetField(tif, ...)
* TIFFDeferStrileArrayWriting(tif)
* TIFFWriteCheck(tif, ...)
* TIFFWriteDirectory(tif)
* ... potentially create other directories and come back to the above directory
* TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file
*
* Returns 1 in case of success, 0 otherwise.
*/
int TIFFDeferStrileArrayWriting(TIFF* tif)
{
static const char module[] = "TIFFDeferStrileArrayWriting";
if (tif->tif_mode == O_RDONLY)
{
TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
"File opened in read-only mode");
return 0;
}
if( tif->tif_diroff != 0 )
{
TIFFErrorExt(tif->tif_clientdata, module,
"Directory has already been written");
return 0;
}
tif->tif_dir.td_deferstrilearraywriting = TRUE;
return 1;
}
/* /*
* Similar to TIFFWriteDirectory(), writes the directory out * Similar to TIFFWriteDirectory(), writes the directory out
* but leaves all data structures in memory so that it can be * but leaves all data structures in memory so that it can be
@ -193,7 +238,7 @@ TIFFCheckpointDirectory(TIFF* tif)
{ {
int rc; int rc;
/* Setup the strips arrays, if they haven't already been. */ /* Setup the strips arrays, if they haven't already been. */
if (tif->tif_dir.td_stripoffset == NULL) if (tif->tif_dir.td_stripoffset_p == NULL)
(void) TIFFSetupStrips(tif); (void) TIFFSetupStrips(tif);
rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL);
(void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
@ -528,12 +573,12 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
{ {
if (!isTiled(tif)) if (!isTiled(tif))
{ {
if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p))
goto bad; goto bad;
} }
else else
{ {
if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p))
goto bad; goto bad;
} }
} }
@ -541,7 +586,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
{ {
if (!isTiled(tif)) if (!isTiled(tif))
{ {
/* td_stripoffset might be NULL in an odd OJPEG case. See /* td_stripoffset_p might be NULL in an odd OJPEG case. See
* tif_dirread.c around line 3634. * tif_dirread.c around line 3634.
* XXX: OJPEG hack. * XXX: OJPEG hack.
* If a) compression is OJPEG, b) it's not a tiled TIFF, * If a) compression is OJPEG, b) it's not a tiled TIFF,
@ -552,13 +597,13 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
* We can get here when using tiffset on such a file. * We can get here when using tiffset on such a file.
* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
*/ */
if (tif->tif_dir.td_stripoffset != NULL && if (tif->tif_dir.td_stripoffset_p != NULL &&
!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p))
goto bad; goto bad;
} }
else else
{ {
if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p))
goto bad; goto bad;
} }
} }
@ -946,15 +991,6 @@ bad:
return(0); return(0);
} }
static float TIFFClampDoubleToFloat( double val )
{
if( val > FLT_MAX )
return FLT_MAX;
if( val < -FLT_MAX )
return -FLT_MAX;
return (float)val;
}
static int8 TIFFClampDoubleToInt8( double val ) static int8 TIFFClampDoubleToInt8( double val )
{ {
if( val > 127 ) if( val > 127 )
@ -1029,7 +1065,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
if (tif->tif_dir.td_bitspersample<=32) if (tif->tif_dir.td_bitspersample<=32)
{ {
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); ((float*)conv)[i] = _TIFFClampDoubleToFloat(value[i]);
ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
} }
else else
@ -1661,22 +1697,52 @@ TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1
return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value));
} }
static int _WriteAsType(TIFF* tif, uint64 strile_size, uint64 uncompressed_threshold)
{
const uint16 compression = tif->tif_dir.td_compression;
if ( compression == COMPRESSION_NONE )
{
return strile_size > uncompressed_threshold;
}
else if ( compression == COMPRESSION_JPEG ||
compression == COMPRESSION_LZW ||
compression == COMPRESSION_ADOBE_DEFLATE ||
compression == COMPRESSION_LZMA ||
compression == COMPRESSION_LERC ||
compression == COMPRESSION_ZSTD ||
compression == COMPRESSION_WEBP )
{
/* For a few select compression types, we assume that in the worst */
/* case the compressed size will be 10 times the uncompressed size */
/* This is overly pessismistic ! */
return strile_size >= uncompressed_threshold / 10;
}
return 1;
}
static int WriteAsLong8(TIFF* tif, uint64 strile_size)
{
return _WriteAsType(tif, strile_size, 0xFFFFFFFFU);
}
static int WriteAsLong4(TIFF* tif, uint64 strile_size)
{
return _WriteAsType(tif, strile_size, 0xFFFFU);
}
/************************************************************************/ /************************************************************************/
/* TIFFWriteDirectoryTagLongLong8Array() */ /* TIFFWriteDirectoryTagLongLong8Array() */
/* */ /* */
/* Write out LONG8 array as LONG8 for BigTIFF or LONG for */ /* Write out LONG8 array and write a SHORT/LONG/LONG8 depending */
/* Classic TIFF with some checking. */ /* on strile size and Classic/BigTIFF mode. */
/************************************************************************/ /************************************************************************/
static int static int
TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{ {
static const char module[] = "TIFFWriteDirectoryTagLongLong8Array"; static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
uint64* ma;
uint32 mb;
uint32* p;
uint32* q;
int o; int o;
int write_aslong4;
/* is this just a counting pass? */ /* is this just a counting pass? */
if (dir==NULL) if (dir==NULL)
@ -1685,37 +1751,105 @@ TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
return(1); return(1);
} }
/* We always write LONG8 for BigTIFF, no checking needed. */ if( tif->tif_dir.td_deferstrilearraywriting )
if( tif->tif_flags&TIFF_BIGTIFF )
return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
tag,count,value);
/*
** For classic tiff we want to verify everything is in range for LONG
** and convert to long format.
*/
p = _TIFFmalloc(count*sizeof(uint32));
if (p==NULL)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL);
return(0);
} }
for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++) if( tif->tif_flags&TIFF_BIGTIFF )
{ {
if (*ma>0xFFFFFFFF) int write_aslong8 = 1;
/* In the case of ByteCounts array, we may be able to write them on */
/* LONG if the strip/tilesize is not too big. */
/* Also do that for count > 1 in the case someone would want to create */
/* a single-strip file with a growing height, in which case using */
/* LONG8 will be safer. */
if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
{ {
TIFFErrorExt(tif->tif_clientdata,module, write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
"Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file."); }
_TIFFfree(p); else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
{
write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
}
if( write_aslong8 )
{
return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
tag,count,value);
}
}
write_aslong4 = 1;
if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
{
write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
}
else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
{
write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
}
if( write_aslong4 )
{
/*
** For classic tiff we want to verify everything is in range for LONG
** and convert to long format.
*/
uint32* p = _TIFFmalloc(count*sizeof(uint32));
uint32* q;
uint64* ma;
uint32 mb;
if (p==NULL)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0); return(0);
} }
*q= (uint32)(*ma);
}
o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
_TIFFfree(p); {
if (*ma>0xFFFFFFFF)
{
TIFFErrorExt(tif->tif_clientdata,module,
"Attempt to write value larger than 0xFFFFFFFF in LONG array.");
_TIFFfree(p);
return(0);
}
*q= (uint32)(*ma);
}
o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p);
_TIFFfree(p);
}
else
{
uint16* p = _TIFFmalloc(count*sizeof(uint16));
uint16* q;
uint64* ma;
uint32 mb;
if (p==NULL)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
{
if (*ma>0xFFFF)
{
/* Should not happen normally given the check we did before */
TIFFErrorExt(tif->tif_clientdata,module,
"Attempt to write value larger than 0xFFFF in SHORT array.");
_TIFFfree(p);
return(0);
}
*q= (uint16)(*ma);
}
o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,p);
_TIFFfree(p);
}
return(o); return(o);
} }
@ -1893,12 +2027,14 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir
n=3; n=3;
if (n==3) if (n==3)
{ {
if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) if (tif->tif_dir.td_transferfunction[2] == NULL ||
!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
n=2; n=2;
} }
if (n==2) if (n==2)
{ {
if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) if (tif->tif_dir.td_transferfunction[1] == NULL ||
!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
n=1; n=1;
} }
if (n==0) if (n==0)
@ -2428,7 +2564,12 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag
dir[m].tdir_count=count; dir[m].tdir_count=count;
dir[m].tdir_offset.toff_long8 = 0; dir[m].tdir_offset.toff_long8 = 0;
if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U))
_TIFFmemcpy(&dir[m].tdir_offset,data,datalength); {
if( data && datalength )
{
_TIFFmemcpy(&dir[m].tdir_offset,data,datalength);
}
}
else else
{ {
uint64 na,nb; uint64 na,nb;
@ -2820,13 +2961,60 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
TIFFSwabLong8( &entry_offset ); TIFFSwabLong8( &entry_offset );
} }
/* -------------------------------------------------------------------- */
/* When a dummy tag was written due to TIFFDeferStrileArrayWriting() */
/* -------------------------------------------------------------------- */
if( entry_offset == 0 && entry_count == 0 && entry_type == 0 )
{
if( tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS )
{
entry_type = (tif->tif_flags&TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG;
}
else
{
int write_aslong8 = 1;
if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
{
write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
}
else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
{
write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
}
if( write_aslong8 )
{
entry_type = TIFF_LONG8;
}
else
{
int write_aslong4 = 1;
if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
{
write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
}
else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
{
write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
}
if( write_aslong4 )
{
entry_type = TIFF_LONG;
}
else
{
entry_type = TIFF_SHORT;
}
}
}
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* What data type do we want to write this as? */ /* What data type do we want to write this as? */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) ) if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) )
{ {
if( in_datatype == TIFF_LONG8 ) if( in_datatype == TIFF_LONG8 )
datatype = TIFF_LONG; datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG;
else if( in_datatype == TIFF_SLONG8 ) else if( in_datatype == TIFF_SLONG8 )
datatype = TIFF_SLONG; datatype = TIFF_SLONG;
else if( in_datatype == TIFF_IFD8 ) else if( in_datatype == TIFF_IFD8 )
@ -2835,7 +3023,20 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
datatype = in_datatype; datatype = in_datatype;
} }
else else
datatype = in_datatype; {
if( in_datatype == TIFF_LONG8 &&
(entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
entry_type == TIFF_LONG8 ) )
datatype = entry_type;
else if( in_datatype == TIFF_SLONG8 &&
(entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8 ) )
datatype = entry_type;
else if( in_datatype == TIFF_IFD8 &&
(entry_type == TIFF_IFD || entry_type == TIFF_IFD8 ) )
datatype = entry_type;
else
datatype = in_datatype;
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Prepare buffer of actual data to write. This includes */ /* Prepare buffer of actual data to write. This includes */
@ -2884,6 +3085,29 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
} }
} }
} }
else if( datatype == TIFF_SHORT && in_datatype == TIFF_LONG8 )
{
tmsize_t i;
for( i = 0; i < count; i++ )
{
((uint16 *) buf_to_write)[i] =
(uint16) ((uint64 *) data)[i];
if( (uint64) ((uint16 *) buf_to_write)[i] != ((uint64 *) data)[i] )
{
_TIFFfree( buf_to_write );
TIFFErrorExt( tif->tif_clientdata, module,
"Value exceeds 16bit range of output type." );
return 0;
}
}
}
else
{
TIFFErrorExt( tif->tif_clientdata, module,
"Unhandled type conversion." );
return 0;
}
if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) ) if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) )
{ {
@ -2915,6 +3139,23 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
} }
} }
if( (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) &&
tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 )
{
tif->tif_dir.td_stripoffset_entry.tdir_type = datatype;
tif->tif_dir.td_stripoffset_entry.tdir_count = count;
}
else if( (tag == TIFFTAG_TILEBYTECOUNTS || tag == TIFFTAG_STRIPBYTECOUNTS) &&
tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
{
tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype;
tif->tif_dir.td_stripbytecount_entry.tdir_count = count;
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* If the tag type, and count match, then we just write it out */ /* If the tag type, and count match, then we just write it out */
/* over the old values without altering the directory entry at */ /* over the old values without altering the directory entry at */
@ -2966,6 +3207,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
/* Adjust the directory entry. */ /* Adjust the directory entry. */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
entry_type = datatype; entry_type = datatype;
entry_count = (uint64)count;
memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) ); memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) );
if (tif->tif_flags&TIFF_SWAB) if (tif->tif_flags&TIFF_SWAB)
TIFFSwabShort( (uint16 *) (direntry_raw + 2) ); TIFFSwabShort( (uint16 *) (direntry_raw + 2) );

View file

@ -46,36 +46,8 @@ TIFFFlush(TIFF* tif)
&& !(tif->tif_flags & TIFF_DIRTYDIRECT) && !(tif->tif_flags & TIFF_DIRTYDIRECT)
&& tif->tif_mode == O_RDWR ) && tif->tif_mode == O_RDWR )
{ {
uint64 *offsets=NULL, *sizes=NULL; if( TIFFForceStrileArrayWriting(tif) )
return 1;
if( TIFFIsTiled(tif) )
{
if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets )
&& TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes )
&& _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8,
tif->tif_dir.td_nstrips, offsets )
&& _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8,
tif->tif_dir.td_nstrips, sizes ) )
{
tif->tif_flags &= ~TIFF_DIRTYSTRIP;
tif->tif_flags &= ~TIFF_BEENWRITING;
return 1;
}
}
else
{
if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets )
&& TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes )
&& _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8,
tif->tif_dir.td_nstrips, offsets )
&& _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8,
tif->tif_dir.td_nstrips, sizes ) )
{
tif->tif_flags &= ~TIFF_DIRTYSTRIP;
tif->tif_flags &= ~TIFF_BEENWRITING;
return 1;
}
}
} }
if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP))
@ -85,6 +57,92 @@ TIFFFlush(TIFF* tif)
return (1); return (1);
} }
/*
* This is an advanced writing function that must be used in a particular
* sequence, and together with TIFFDeferStrileArrayWriting(),
* to make its intended effect. Its aim is to force the writing of
* the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when
* they have not yet been rewritten.
*
* The typical sequence of calls is:
* TIFFOpen()
* [ TIFFCreateDirectory(tif) ]
* Set fields with calls to TIFFSetField(tif, ...)
* TIFFDeferStrileArrayWriting(tif)
* TIFFWriteCheck(tif, ...)
* TIFFWriteDirectory(tif)
* ... potentially create other directories and come back to the above directory
* TIFFForceStrileArrayWriting(tif)
*
* Returns 1 in case of success, 0 otherwise.
*/
int TIFFForceStrileArrayWriting(TIFF* tif)
{
static const char module[] = "TIFFForceStrileArrayWriting";
const int isTiled = TIFFIsTiled(tif);
if (tif->tif_mode == O_RDONLY)
{
TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
"File opened in read-only mode");
return 0;
}
if( tif->tif_diroff == 0 )
{
TIFFErrorExt(tif->tif_clientdata, module,
"Directory has not yet been written");
return 0;
}
if( (tif->tif_flags & TIFF_DIRTYDIRECT) != 0 )
{
TIFFErrorExt(tif->tif_clientdata, module,
"Directory has changes other than the strile arrays. "
"TIFFRewriteDirectory() should be called instead");
return 0;
}
if( !(tif->tif_flags & TIFF_DIRTYSTRIP) )
{
if( !(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0) )
{
TIFFErrorExt(tif->tif_clientdata, module,
"Function not called together with "
"TIFFDeferStrileArrayWriting()");
return 0;
}
if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
return 0;
}
if( _TIFFRewriteField( tif,
isTiled ? TIFFTAG_TILEOFFSETS :
TIFFTAG_STRIPOFFSETS,
TIFF_LONG8,
tif->tif_dir.td_nstrips,
tif->tif_dir.td_stripoffset_p )
&& _TIFFRewriteField( tif,
isTiled ? TIFFTAG_TILEBYTECOUNTS :
TIFFTAG_STRIPBYTECOUNTS,
TIFF_LONG8,
tif->tif_dir.td_nstrips,
tif->tif_dir.td_stripbytecount_p ) )
{
tif->tif_flags &= ~TIFF_DIRTYSTRIP;
tif->tif_flags &= ~TIFF_BEENWRITING;
return 1;
}
return 0;
}
/* /*
* Flush buffered data to the file. * Flush buffered data to the file.
* *

View file

@ -755,9 +755,8 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
uint32 leftmost_tw; uint32 leftmost_tw;
tilesize = TIFFTileSize(tif); tilesize = TIFFTileSize(tif);
bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize); bufsize = _TIFFMultiplySSize(tif, alpha?4:3,tilesize, "gtTileSeparate");
if (bufsize == 0) { if (bufsize == 0) {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate");
return (0); return (0);
} }
@ -950,16 +949,23 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
fromskew = (w < imagewidth ? imagewidth - w : 0); fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow) for (row = 0; row < h; row += nrow)
{ {
uint32 temp;
rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
nrow = (row + rowstoread > h ? h - row : rowstoread); nrow = (row + rowstoread > h ? h - row : rowstoread);
nrowsub = nrow; nrowsub = nrow;
if ((nrowsub%subsamplingver)!=0) if ((nrowsub%subsamplingver)!=0)
nrowsub+=subsamplingver-nrowsub%subsamplingver; nrowsub+=subsamplingver-nrowsub%subsamplingver;
temp = (row + img->row_offset)%rowsperstrip + nrowsub;
if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
{
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripContig");
return 0;
}
if (_TIFFReadEncodedStripAndAllocBuffer(tif, if (_TIFFReadEncodedStripAndAllocBuffer(tif,
TIFFComputeStrip(tif,row+img->row_offset, 0), TIFFComputeStrip(tif,row+img->row_offset, 0),
(void**)(&buf), (void**)(&buf),
maxstripsize, maxstripsize,
((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) temp * scanline)==(tmsize_t)(-1)
&& (buf == NULL || img->stoponerr)) && (buf == NULL || img->stoponerr))
{ {
ret = 0; ret = 0;
@ -1019,9 +1025,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
uint16 colorchannels; uint16 colorchannels;
stripsize = TIFFStripSize(tif); stripsize = TIFFStripSize(tif);
bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize); bufsize = _TIFFMultiplySSize(tif,alpha?4:3,stripsize, "gtStripSeparate");
if (bufsize == 0) { if (bufsize == 0) {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate");
return (0); return (0);
} }
@ -1053,15 +1058,22 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
fromskew = (w < imagewidth ? imagewidth - w : 0); fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow) for (row = 0; row < h; row += nrow)
{ {
uint32 temp;
rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
nrow = (row + rowstoread > h ? h - row : rowstoread); nrow = (row + rowstoread > h ? h - row : rowstoread);
offset_row = row + img->row_offset; offset_row = row + img->row_offset;
temp = (row + img->row_offset)%rowsperstrip + nrow;
if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
{
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripSeparate");
return 0;
}
if( buf == NULL ) if( buf == NULL )
{ {
if (_TIFFReadEncodedStripAndAllocBuffer( if (_TIFFReadEncodedStripAndAllocBuffer(
tif, TIFFComputeStrip(tif, offset_row, 0), tif, TIFFComputeStrip(tif, offset_row, 0),
(void**) &buf, bufsize, (void**) &buf, bufsize,
((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) temp * scanline)==(tmsize_t)(-1)
&& (buf == NULL || img->stoponerr)) && (buf == NULL || img->stoponerr))
{ {
ret = 0; ret = 0;
@ -1081,7 +1093,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
} }
else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) p0, temp * scanline)==(tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1089,7 +1101,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
if (colorchannels > 1 if (colorchannels > 1
&& TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) p1, temp * scanline) == (tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1097,7 +1109,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
if (colorchannels > 1 if (colorchannels > 1
&& TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) p2, temp * scanline) == (tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1106,7 +1118,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
if (alpha) if (alpha)
{ {
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels), if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels),
pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) pa, temp * scanline)==(tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -2957,7 +2969,7 @@ TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop
if( !TIFFIsTiled( tif ) ) if( !TIFFIsTiled( tif ) )
{ {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
"Can't use TIFFReadRGBATile() with stripped file."); "Can't use TIFFReadRGBATile() with striped file.");
return (0); return (0);
} }

View file

@ -780,12 +780,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
*/ */
static const char module[] = "JPEGFixupTagsSubsampling"; static const char module[] = "JPEGFixupTagsSubsampling";
struct JPEGFixupTagsSubsamplingData m; struct JPEGFixupTagsSubsamplingData m;
uint64 fileoffset = TIFFGetStrileOffset(tif, 0);
_TIFFFillStriles( tif ); if( fileoffset == 0 )
if( tif->tif_dir.td_stripbytecount == NULL
|| tif->tif_dir.td_stripoffset == NULL
|| tif->tif_dir.td_stripbytecount[0] == 0 )
{ {
/* Do not even try to check if the first strip/tile does not /* Do not even try to check if the first strip/tile does not
yet exist, as occurs when GDAL has created a new NULL file yet exist, as occurs when GDAL has created a new NULL file
@ -804,9 +801,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
} }
m.buffercurrentbyte=NULL; m.buffercurrentbyte=NULL;
m.bufferbytesleft=0; m.bufferbytesleft=0;
m.fileoffset=tif->tif_dir.td_stripoffset[0]; m.fileoffset=fileoffset;
m.filepositioned=0; m.filepositioned=0;
m.filebytesleft=tif->tif_dir.td_stripbytecount[0]; m.filebytesleft=TIFFGetStrileByteCount(tif, 0);
if (!JPEGFixupTagsSubsamplingSec(&m)) if (!JPEGFixupTagsSubsamplingSec(&m))
TIFFWarningExt(tif->tif_clientdata,module, TIFFWarningExt(tif->tif_clientdata,module,
"Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped"); "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped");
@ -1566,7 +1563,7 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset; JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;
#else #else
JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
if (cc < (tmsize_t) (clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp)) { if (cc < (tmsize_t)(clumpoffset + (tmsize_t)samples_per_clump*(clumps_per_line-1) + hsamp)) {
TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
"application buffer not large enough for all data, possible subsampling issue"); "application buffer not large enough for all data, possible subsampling issue");
return 0; return 0;
@ -2126,8 +2123,8 @@ JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
/* data is expected to be supplied in multiples of a clumpline */ /* data is expected to be supplied in multiples of a clumpline */
/* a clumpline is equivalent to v_sampling desubsampled scanlines */ /* a clumpline is equivalent to v_sampling desubsampled scanlines */
/* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */ /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */
bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) bytesperclumpline = ((((tmsize_t)sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)
*(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) *((tmsize_t)sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
/8; /8;
nrows = ( cc / bytesperclumpline ) * sp->v_sampling; nrows = ( cc / bytesperclumpline ) * sp->v_sampling;

View file

@ -742,9 +742,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
#undef exp2 /* Conflict with C'99 function */ #undef exp2 /* Conflict with C'99 function */
#define exp2(x) exp(M_LN2*(x)) #define exp2(x) exp(M_LN2*(x))
#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ static int itrunc(double x, int m)
(int)(x) : \ {
(int)((x) + rand()*(1./RAND_MAX) - .5)) if( m == SGILOGENCODE_NODITHER )
return (int)x;
/* Silence CoverityScan warning about bad crypto function */
/* coverity[dont_call] */
return (int)(x + rand()*(1./RAND_MAX) - .5);
}
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
@ -1264,16 +1269,10 @@ LogL16GuessDataFmt(TIFFDirectory *td)
return (SGILOGDATAFMT_UNKNOWN); return (SGILOGDATAFMT_UNKNOWN);
} }
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
static tmsize_t static tmsize_t
multiply_ms(tmsize_t m1, tmsize_t m2) multiply_ms(tmsize_t m1, tmsize_t m2)
{ {
if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) return _TIFFMultiplySSize(NULL, m1, m2, NULL);
return 0;
return m1 * m2;
} }
static int static int
@ -1507,7 +1506,7 @@ LogLuvSetupEncode(TIFF* tif)
switch (td->td_photometric) { switch (td->td_photometric) {
case PHOTOMETRIC_LOGLUV: case PHOTOMETRIC_LOGLUV:
if (!LogLuvInitState(tif)) if (!LogLuvInitState(tif))
break; return (0);
if (td->td_compression == COMPRESSION_SGILOG24) { if (td->td_compression == COMPRESSION_SGILOG24) {
tif->tif_encoderow = LogLuvEncode24; tif->tif_encoderow = LogLuvEncode24;
switch (sp->user_datafmt) { switch (sp->user_datafmt) {
@ -1540,7 +1539,7 @@ LogLuvSetupEncode(TIFF* tif)
break; break;
case PHOTOMETRIC_LOGL: case PHOTOMETRIC_LOGL:
if (!LogL16InitState(tif)) if (!LogL16InitState(tif))
break; return (0);
tif->tif_encoderow = LogL16Encode; tif->tif_encoderow = LogL16Encode;
switch (sp->user_datafmt) { switch (sp->user_datafmt) {
case SGILOGDATAFMT_FLOAT: case SGILOGDATAFMT_FLOAT:
@ -1556,7 +1555,7 @@ LogLuvSetupEncode(TIFF* tif)
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Inappropriate photometric interpretation %d for SGILog compression; %s", "Inappropriate photometric interpretation %d for SGILog compression; %s",
td->td_photometric, "must be either LogLUV or LogL"); td->td_photometric, "must be either LogLUV or LogL");
break; return (0);
} }
sp->encoder_state = 1; sp->encoder_state = 1;
return (1); return (1);

View file

@ -247,6 +247,8 @@ LZWSetupDecode(TIFF* tif)
/* /*
* Zero-out the unused entries * Zero-out the unused entries
*/ */
/* Silence false positive */
/* coverity[overrun-buffer-arg] */
_TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0,
(CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); (CODE_FIRST - CODE_CLEAR) * sizeof (code_t));
} }

View file

@ -243,6 +243,7 @@ typedef enum {
typedef struct { typedef struct {
TIFF* tif; TIFF* tif;
int decoder_ok; int decoder_ok;
int error_in_raw_data_decoding;
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
JMP_BUF exit_jmpbuf; JMP_BUF exit_jmpbuf;
#endif #endif
@ -678,7 +679,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s)
if (OJPEGReadSecondarySos(tif,s)==0) if (OJPEGReadSecondarySos(tif,s)==0)
return(0); return(0);
} }
if isTiled(tif) if (isTiled(tif))
m=tif->tif_curtile; m=tif->tif_curtile;
else else
m=tif->tif_curstrip; m=tif->tif_curstrip;
@ -742,6 +743,7 @@ OJPEGPreDecodeSkipRaw(TIFF* tif)
} }
m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; m-=sp->subsampling_convert_clines-sp->subsampling_convert_state;
sp->subsampling_convert_state=0; sp->subsampling_convert_state=0;
sp->error_in_raw_data_decoding=0;
} }
while (m>=sp->subsampling_convert_clines) while (m>=sp->subsampling_convert_clines)
{ {
@ -792,6 +794,10 @@ OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized");
return 0; return 0;
} }
if( sp->error_in_raw_data_decoding )
{
return 0;
}
if (sp->libjpeg_jpeg_query_style==0) if (sp->libjpeg_jpeg_query_style==0)
{ {
if (OJPEGDecodeRaw(tif,buf,cc)==0) if (OJPEGDecodeRaw(tif,buf,cc)==0)
@ -831,8 +837,41 @@ OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc)
{ {
if (sp->subsampling_convert_state==0) if (sp->subsampling_convert_state==0)
{ {
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) const jpeg_decompress_struct* cinfo = &sp->libjpeg_jpeg_decompress_struct;
int width = 0;
int last_col_width = 0;
int jpeg_bytes;
int expected_bytes;
int i;
if (cinfo->MCUs_per_row == 0)
{
sp->error_in_raw_data_decoding = 1;
return 0;
}
for (i = 0; i < cinfo->comps_in_scan; ++i)
{
const jpeg_component_info* info = cinfo->cur_comp_info[i];
#if JPEG_LIB_VERSION >= 70
width += info->MCU_width * info->DCT_h_scaled_size;
last_col_width += info->last_col_width * info->DCT_h_scaled_size;
#else
width += info->MCU_width * info->DCT_scaled_size;
last_col_width += info->last_col_width * info->DCT_scaled_size;
#endif
}
jpeg_bytes = (cinfo->MCUs_per_row - 1) * width + last_col_width;
expected_bytes = sp->subsampling_convert_clinelenout * sp->subsampling_ver * sp->subsampling_hor;
if (jpeg_bytes != expected_bytes)
{
TIFFErrorExt(tif->tif_clientdata,module,"Inconsistent number of MCU in codestream");
sp->error_in_raw_data_decoding = 1;
return(0); return(0);
}
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
{
sp->error_in_raw_data_decoding = 1;
return(0);
}
} }
oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen;
ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
@ -990,7 +1029,6 @@ OJPEGSubsamplingCorrect(TIFF* tif)
OJPEGState* sp=(OJPEGState*)tif->tif_data; OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 mh; uint8 mh;
uint8 mv; uint8 mv;
_TIFFFillStriles( tif );
assert(sp->subsamplingcorrect_done==0); assert(sp->subsamplingcorrect_done==0);
if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) &&
@ -1046,7 +1084,7 @@ OJPEGReadHeaderInfo(TIFF* tif)
assert(sp->readheader_done==0); assert(sp->readheader_done==0);
sp->image_width=tif->tif_dir.td_imagewidth; sp->image_width=tif->tif_dir.td_imagewidth;
sp->image_length=tif->tif_dir.td_imagelength; sp->image_length=tif->tif_dir.td_imagelength;
if isTiled(tif) if (isTiled(tif))
{ {
sp->strile_width=tif->tif_dir.td_tilewidth; sp->strile_width=tif->tif_dir.td_tilewidth;
sp->strile_length=tif->tif_dir.td_tilelength; sp->strile_length=tif->tif_dir.td_tilelength;
@ -1082,6 +1120,12 @@ OJPEGReadHeaderInfo(TIFF* tif)
} }
if (sp->strile_length<sp->image_length) if (sp->strile_length<sp->image_length)
{ {
if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) ||
((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4)))
{
TIFFErrorExt(tif->tif_clientdata,module,"Invalid subsampling values");
return(0);
}
if (sp->strile_length%(sp->subsampling_ver*8)!=0) if (sp->strile_length%(sp->subsampling_ver*8)!=0)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
@ -1197,7 +1241,13 @@ OJPEGWriteHeaderInfo(TIFF* tif)
sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines;
sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen;
sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen); /* The calloc is not normally necessary, except in some edge/broken cases */
/* for example for a tiled image of height 1 with a tile height of 1 and subsampling_hor=subsampling_ver=2 */
/* In that case, libjpeg will only fill the 8 first lines of the 16 lines */
/* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 */
/* Even if this case is allowed (?), its handling is broken because OJPEGPreDecode() should also likely */
/* reset subsampling_convert_state to 0 when changing tile. */
sp->subsampling_convert_ycbcrbuf=_TIFFcalloc(1, sp->subsampling_convert_ycbcrbuflen);
if (sp->subsampling_convert_ycbcrbuf==0) if (sp->subsampling_convert_ycbcrbuf==0)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
@ -1223,10 +1273,11 @@ OJPEGWriteHeaderInfo(TIFF* tif)
*m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen;
for (n=0; n<sp->subsampling_convert_clines; n++) for (n=0; n<sp->subsampling_convert_clines; n++)
*m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen;
sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor); sp->subsampling_convert_clinelenout=sp->strile_width/sp->subsampling_hor + ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0);
sp->subsampling_convert_state=0; sp->subsampling_convert_state=0;
sp->error_in_raw_data_decoding=0;
sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2);
sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver); sp->lines_per_strile=sp->strile_length/sp->subsampling_ver + ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0);
sp->subsampling_convert_log=1; sp->subsampling_convert_log=1;
} }
} }
@ -1272,7 +1323,9 @@ OJPEGReadHeaderInfoSec(TIFF* tif)
} }
else else
{ {
if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) if ((sp->jpeg_interchange_format_length==0) ||
(sp->jpeg_interchange_format > TIFF_UINT64_MAX - sp->jpeg_interchange_format_length) ||
(sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size))
sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format;
} }
} }
@ -1989,32 +2042,30 @@ OJPEGReadBufferFill(OJPEGState* sp)
sp->in_buffer_source=osibsStrile; sp->in_buffer_source=osibsStrile;
break; break;
case osibsStrile: case osibsStrile:
if (!_TIFFFillStriles( sp->tif )
|| sp->tif->tif_dir.td_stripoffset == NULL
|| sp->tif->tif_dir.td_stripbytecount == NULL)
return 0;
if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
sp->in_buffer_source=osibsEof; sp->in_buffer_source=osibsEof;
else else
{ {
sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile]; int err = 0;
sp->in_buffer_file_pos=TIFFGetStrileOffsetWithErr(sp->tif, sp->in_buffer_next_strile, &err);
if( err )
return 0;
if (sp->in_buffer_file_pos!=0) if (sp->in_buffer_file_pos!=0)
{ {
uint64 bytecount = TIFFGetStrileByteCountWithErr(sp->tif, sp->in_buffer_next_strile, &err);
if( err )
return 0;
if (sp->in_buffer_file_pos>=sp->file_size) if (sp->in_buffer_file_pos>=sp->file_size)
sp->in_buffer_file_pos=0; sp->in_buffer_file_pos=0;
else if (sp->tif->tif_dir.td_stripbytecount==NULL) else if (bytecount==0)
sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
else else
{ {
if (sp->tif->tif_dir.td_stripbytecount == 0) { sp->in_buffer_file_togo=bytecount;
TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing");
return(0);
}
sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
if (sp->in_buffer_file_togo==0) if (sp->in_buffer_file_togo==0)
sp->in_buffer_file_pos=0; sp->in_buffer_file_pos=0;
else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) else if (sp->in_buffer_file_pos > TIFF_UINT64_MAX - sp->in_buffer_file_togo ||
sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size)
sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
} }
} }

View file

@ -25,7 +25,6 @@
/* /*
* TIFF Library. * TIFF Library.
*/ */
#include <precomp.h> #include <precomp.h>
/* /*
@ -132,6 +131,7 @@ TIFFClientOpen(
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
TIFFErrorExt(clientdata, module, TIFFErrorExt(clientdata, module,
"One of the client procedures is NULL pointer."); "One of the client procedures is NULL pointer.");
_TIFFfree(tif);
goto bad2; goto bad2;
} }
tif->tif_readproc = readproc; tif->tif_readproc = readproc;
@ -182,6 +182,8 @@ TIFFClientOpen(
* 'h' read TIFF header only, do not load the first IFD * 'h' read TIFF header only, do not load the first IFD
* '4' ClassicTIFF for creating a file (default) * '4' ClassicTIFF for creating a file (default)
* '8' BigTIFF for creating a file * '8' BigTIFF for creating a file
* 'D' enable use of deferred strip/tile offset/bytecount array loading.
* 'O' on-demand loading of values instead of whole array loading (implies D)
* *
* The use of the 'l' and 'b' flags is strongly discouraged. * The use of the 'l' and 'b' flags is strongly discouraged.
* These flags are provided solely because numerous vendors, * These flags are provided solely because numerous vendors,
@ -263,7 +265,22 @@ TIFFClientOpen(
if (m&O_CREAT) if (m&O_CREAT)
tif->tif_flags |= TIFF_BIGTIFF; tif->tif_flags |= TIFF_BIGTIFF;
break; break;
case 'D':
tif->tif_flags |= TIFF_DEFERSTRILELOAD;
break;
case 'O':
if( m == O_RDONLY )
tif->tif_flags |= (TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD);
break;
} }
#ifdef DEFER_STRILE_LOAD
/* Compatibility with old DEFER_STRILE_LOAD compilation flag */
/* Probably unneeded, since to the best of my knowledge (E. Rouault) */
/* GDAL was the only user of this, and will now use the new 'D' flag */
tif->tif_flags |= TIFF_DEFERSTRILELOAD;
#endif
/* /*
* Read in TIFF header. * Read in TIFF header.
*/ */

View file

@ -23,7 +23,6 @@
*/ */
#include <precomp.h> #include <precomp.h>
#ifdef PACKBITS_SUPPORT #ifdef PACKBITS_SUPPORT
/* /*
* TIFF Library. * TIFF Library.

View file

@ -90,8 +90,8 @@
#include "tif_predict.h" #include "tif_predict.h"
#include "zlib.h" #include "zlib.h"
//#include <stdio.h> #include <stdio.h>
//#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
/* Tables for converting to/from 11 bit coded values */ /* Tables for converting to/from 11 bit coded values */
@ -634,20 +634,16 @@ PixarLogGuessDataFmt(TIFFDirectory *td)
return guess; return guess;
} }
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
static tmsize_t static tmsize_t
multiply_ms(tmsize_t m1, tmsize_t m2) multiply_ms(tmsize_t m1, tmsize_t m2)
{ {
if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) return _TIFFMultiplySSize(NULL, m1, m2, NULL);
return 0;
return m1 * m2;
} }
static tmsize_t static tmsize_t
add_ms(tmsize_t m1, tmsize_t m2) add_ms(tmsize_t m1, tmsize_t m2)
{ {
assert(m1 >= 0 && m2 >= 0);
/* if either input is zero, assume overflow already occurred */ /* if either input is zero, assume overflow already occurred */
if (m1 == 0 || m2 == 0) if (m1 == 0 || m2 == 0)
return 0; return 0;
@ -817,9 +813,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
if (inflateSync(&sp->stream) != Z_OK) return (0);
return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
@ -1153,7 +1147,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
llen = sp->stride * td->td_imagewidth; llen = sp->stride * td->td_imagewidth;
/* Check against the number of elements (of size uint16) of sp->tbuf */ /* Check against the number of elements (of size uint16) of sp->tbuf */
if( n > (tmsize_t)(td->td_rowsperstrip * llen) ) if( n > ((tmsize_t)td->td_rowsperstrip * llen) )
{ {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Too many input bytes provided"); "Too many input bytes provided");

View file

@ -27,7 +27,6 @@
* *
* Directory Printing Support * Directory Printing Support
*/ */
#include <precomp.h> #include <precomp.h>
//#include <stdio.h> //#include <stdio.h>
@ -653,8 +652,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
if (tif->tif_tagmethods.printdir) if (tif->tif_tagmethods.printdir)
(*tif->tif_tagmethods.printdir)(tif, fd, flags); (*tif->tif_tagmethods.printdir)(tif, fd, flags);
_TIFFFillStriles( tif );
if ((flags & TIFFPRINT_STRIPS) && if ((flags & TIFFPRINT_STRIPS) &&
TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
uint32 s; uint32 s;
@ -666,13 +663,13 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", fprintf(fd, " %3lu: [%8I64u, %8I64u]\n",
(unsigned long) s, (unsigned long) s,
td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0, (unsigned __int64) TIFFGetStrileOffset(tif, s),
td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0); (unsigned __int64) TIFFGetStrileByteCount(tif, s));
#else #else
fprintf(fd, " %3lu: [%8llu, %8llu]\n", fprintf(fd, " %3lu: [%8llu, %8llu]\n",
(unsigned long) s, (unsigned long) s,
td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0, (unsigned long long) TIFFGetStrileOffset(tif, s),
td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0); (unsigned long long) TIFFGetStrileByteCount(tif, s));
#endif #endif
} }
} }

View file

@ -29,9 +29,6 @@
#include <precomp.h> #include <precomp.h>
//#include <stdio.h> //#include <stdio.h>
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillStrip(TIFF* tif, uint32 strip);
int TIFFFillTile(TIFF* tif, uint32 tile); int TIFFFillTile(TIFF* tif, uint32 tile);
static int TIFFStartStrip(TIFF* tif, uint32 strip); static int TIFFStartStrip(TIFF* tif, uint32 strip);
@ -49,6 +46,8 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
#define THRESHOLD_MULTIPLIER 10 #define THRESHOLD_MULTIPLIER 10
#define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) #define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD)
#define TIFF_INT64_MAX ((((int64)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
/* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' /* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset'
* Returns 1 in case of success, 0 otherwise. */ * Returns 1 in case of success, 0 otherwise. */
static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
@ -61,6 +60,22 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
#endif #endif
tmsize_t already_read = 0; tmsize_t already_read = 0;
#if SIZEOF_SIZE_T != 8
/* On 32 bit processes, if the request is large enough, check against */
/* file size */
if( size > 1000 * 1000 * 1000 )
{
uint64 filesize = TIFFGetFileSize(tif);
if( (uint64)size >= filesize )
{
TIFFErrorExt(tif->tif_clientdata, module,
"Chunk size requested is larger than file size.");
return 0;
}
}
#endif
/* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */
/* so as to avoid allocating too much memory in case the file is too */ /* so as to avoid allocating too much memory in case the file is too */
/* short. We could ask for the file size, but this might be */ /* short. We could ask for the file size, but this might be */
@ -103,6 +118,11 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
} }
tif->tif_rawdata = new_rawdata; tif->tif_rawdata = new_rawdata;
} }
if( tif->tif_rawdata == NULL )
{
/* should not happen in practice but helps CoverityScan */
return 0;
}
bytes_read = TIFFReadFile(tif, bytes_read = TIFFReadFile(tif,
tif->tif_rawdata + rawdata_offset + already_read, to_read); tif->tif_rawdata + rawdata_offset + already_read, to_read);
@ -171,16 +191,13 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
tmsize_t read_ahead_mod; tmsize_t read_ahead_mod;
/* tmsize_t bytecountm; */ /* tmsize_t bytecountm; */
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
/* /*
* Expand raw data buffer, if needed, to hold data * Expand raw data buffer, if needed, to hold data
* strip coming from file (perhaps should set upper * strip coming from file (perhaps should set upper
* bound on the size of a buffer we'll use?). * bound on the size of a buffer we'll use?).
*/ */
/* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ /* bytecountm=(tmsize_t) TIFFGetStrileByteCount(tif, strip); */
/* Not completely sure where the * 2 comes from, but probably for */ /* Not completely sure where the * 2 comes from, but probably for */
/* an exponentional growth strategy of tif_rawdatasize */ /* an exponentional growth strategy of tif_rawdatasize */
@ -224,7 +241,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
/* /*
** Seek to the point in the file where more data should be read. ** Seek to the point in the file where more data should be read.
*/ */
read_offset = td->td_stripoffset[strip] read_offset = TIFFGetStrileOffset(tif, strip)
+ tif->tif_rawdataoff + tif->tif_rawdataloaded; + tif->tif_rawdataoff + tif->tif_rawdataloaded;
if (!SeekOK(tif, read_offset)) { if (!SeekOK(tif, read_offset)) {
@ -241,10 +258,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
to_read = read_ahead_mod - unused_data; to_read = read_ahead_mod - unused_data;
else else
to_read = tif->tif_rawdatasize - unused_data; to_read = tif->tif_rawdatasize - unused_data;
if( (uint64) to_read > td->td_stripbytecount[strip] if( (uint64) to_read > TIFFGetStrileByteCount(tif, strip)
- tif->tif_rawdataoff - tif->tif_rawdataloaded ) - tif->tif_rawdataoff - tif->tif_rawdataloaded )
{ {
to_read = (tmsize_t) td->td_stripbytecount[strip] to_read = (tmsize_t) TIFFGetStrileByteCount(tif, strip)
- tif->tif_rawdataoff - tif->tif_rawdataloaded; - tif->tif_rawdataoff - tif->tif_rawdataloaded;
} }
@ -283,7 +300,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
/* For JPEG, if there are multiple scans (can generally be known */ /* For JPEG, if there are multiple scans (can generally be known */
/* with the read_ahead used), we need to read the whole strip */ /* with the read_ahead used), we need to read the whole strip */
if( tif->tif_dir.td_compression==COMPRESSION_JPEG && if( tif->tif_dir.td_compression==COMPRESSION_JPEG &&
(uint64)tif->tif_rawcc < td->td_stripbytecount[strip] ) (uint64)tif->tif_rawcc < TIFFGetStrileByteCount(tif, strip) )
{ {
if( TIFFJPEGIsFullStripRequired(tif) ) if( TIFFJPEGIsFullStripRequired(tif) )
{ {
@ -342,9 +359,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
* read it a few lines at a time? * read it a few lines at a time?
*/ */
#if defined(CHUNKY_STRIP_READ_SUPPORT) #if defined(CHUNKY_STRIP_READ_SUPPORT)
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) whole_strip = TIFFGetStrileByteCount(tif, strip) < 10
return 0;
whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
|| isMapped(tif); || isMapped(tif);
if( td->td_compression == COMPRESSION_LERC || if( td->td_compression == COMPRESSION_LERC ||
td->td_compression == COMPRESSION_JBIG ) td->td_compression == COMPRESSION_JBIG )
@ -397,7 +412,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
else if( !whole_strip ) else if( !whole_strip )
{ {
if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead
&& (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < td->td_stripbytecount[strip] ) && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < TIFFGetStrileByteCount(tif, strip) )
{ {
if( !TIFFFillStripPartial(tif,strip,read_ahead,0) ) if( !TIFFFillStripPartial(tif,strip,read_ahead,0) )
return 0; return 0;
@ -594,16 +609,11 @@ static tmsize_t
TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
const char* module) const char* module)
{ {
TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ))
return ((tmsize_t)(-1));
assert((tif->tif_flags&TIFF_NOREADRAW)==0); assert((tif->tif_flags&TIFF_NOREADRAW)==0);
if (!isMapped(tif)) { if (!isMapped(tif)) {
tmsize_t cc; tmsize_t cc;
if (!SeekOK(tif, td->td_stripoffset[strip])) { if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip))) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at scanline %lu, strip %lu", "Seek error at scanline %lu, strip %lu",
(unsigned long) tif->tif_row, (unsigned long) strip); (unsigned long) tif->tif_row, (unsigned long) strip);
@ -629,8 +639,8 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
} else { } else {
tmsize_t ma = 0; tmsize_t ma = 0;
tmsize_t n; tmsize_t n;
if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| if ((TIFFGetStrileOffset(tif, strip) > (uint64)TIFF_TMSIZE_T_MAX)||
((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) ((ma=(tmsize_t)TIFFGetStrileOffset(tif, strip))>tif->tif_size))
{ {
n=0; n=0;
} }
@ -674,12 +684,10 @@ static tmsize_t
TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip,
tmsize_t size, const char* module) tmsize_t size, const char* module)
{ {
TIFFDirectory *td = &tif->tif_dir;
assert( !isMapped(tif) ); assert( !isMapped(tif) );
assert((tif->tif_flags&TIFF_NOREADRAW)==0); assert((tif->tif_flags&TIFF_NOREADRAW)==0);
if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) { if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip_or_tile))) {
if( is_strip ) if( is_strip )
{ {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -715,7 +723,7 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
{ {
static const char module[] = "TIFFReadRawStrip"; static const char module[] = "TIFFReadRawStrip";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint64 bytecount; uint64 bytecount64;
tmsize_t bytecountm; tmsize_t bytecountm;
if (!TIFFCheckRead(tif, 0)) if (!TIFFCheckRead(tif, 0))
@ -733,31 +741,23 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
"Compression scheme does not support access to raw uncompressed data"); "Compression scheme does not support access to raw uncompressed data");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
bytecount = td->td_stripbytecount[strip]; bytecount64 = TIFFGetStrileByteCount(tif, strip);
if ((int64)bytecount <= 0) { if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module,
"%I64u: Invalid strip byte count, strip %lu",
(unsigned __int64) bytecount,
(unsigned long) strip);
#else
TIFFErrorExt(tif->tif_clientdata, module,
"%llu: Invalid strip byte count, strip %lu",
(unsigned long long) bytecount,
(unsigned long) strip);
#endif
return ((tmsize_t)(-1));
}
bytecountm = (tmsize_t)bytecount;
if ((uint64)bytecountm!=bytecount) {
TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow");
return ((tmsize_t)(-1));
}
if (size != (tmsize_t)(-1) && size < bytecountm)
bytecountm = size; bytecountm = size;
else
bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
if( bytecountm == 0 ) {
return ((tmsize_t)(-1));
}
return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module)); return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module));
} }
TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
static uint64 NoSantizeSubUInt64(uint64 a, uint64 b)
{
return a - b;
}
/* /*
* Read the specified strip and setup for decoding. The data buffer is * Read the specified strip and setup for decoding. The data buffer is
* expanded, as necessary, to hold the strip's data. * expanded, as necessary, to hold the strip's data.
@ -768,13 +768,10 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
static const char module[] = "TIFFFillStrip"; static const char module[] = "TIFFFillStrip";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags&TIFF_NOREADRAW)==0) if ((tif->tif_flags&TIFF_NOREADRAW)==0)
{ {
uint64 bytecount = td->td_stripbytecount[strip]; uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
if ((int64)bytecount <= 0) { if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Invalid strip byte count %I64u, strip %lu", "Invalid strip byte count %I64u, strip %lu",
@ -801,7 +798,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
(bytecount - 4096) / 10 > (uint64)stripsize ) (bytecount - 4096) / 10 > (uint64)stripsize )
{ {
uint64 newbytecount = (uint64)stripsize * 10 + 4096; uint64 newbytecount = (uint64)stripsize * 10 + 4096;
if( (int64)newbytecount >= 0 ) if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
{ {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFWarningExt(tif->tif_clientdata, module, TIFFWarningExt(tif->tif_clientdata, module,
@ -826,13 +823,13 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
* We must check for overflow, potentially causing * We must check for overflow, potentially causing
* an OOB read. Instead of simple * an OOB read. Instead of simple
* *
* td->td_stripoffset[strip]+bytecount > tif->tif_size * TIFFGetStrileOffset(tif, strip)+bytecount > tif->tif_size
* *
* comparison (which can overflow) we do the following * comparison (which can overflow) we do the following
* two comparisons: * two comparisons:
*/ */
if (bytecount > (uint64)tif->tif_size || if (bytecount > (uint64)tif->tif_size ||
td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { TIFFGetStrileOffset(tif, strip) > (uint64)tif->tif_size - bytecount) {
/* /*
* This error message might seem strange, but * This error message might seem strange, but
* it's what would happen if a read were done * it's what would happen if a read were done
@ -844,7 +841,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
"Read error on strip %lu; " "Read error on strip %lu; "
"got %I64u bytes, expected %I64u", "got %I64u bytes, expected %I64u",
(unsigned long) strip, (unsigned long) strip,
(unsigned __int64) tif->tif_size - td->td_stripoffset[strip], (unsigned __int64) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)),
(unsigned __int64) bytecount); (unsigned __int64) bytecount);
#else #else
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -852,7 +849,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
"Read error on strip %lu; " "Read error on strip %lu; "
"got %llu bytes, expected %llu", "got %llu bytes, expected %llu",
(unsigned long) strip, (unsigned long) strip,
(unsigned long long) tif->tif_size - td->td_stripoffset[strip], (unsigned long long) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)),
(unsigned long long) bytecount); (unsigned long long) bytecount);
#endif #endif
tif->tif_curstrip = NOSTRIP; tif->tif_curstrip = NOSTRIP;
@ -881,7 +878,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
} }
tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_flags &= ~TIFF_MYBUFFER;
tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdatasize = (tmsize_t)bytecount;
tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdata = tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, strip);
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_rawdataloaded = (tmsize_t) bytecount;
@ -1096,16 +1093,11 @@ _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile,
static tmsize_t static tmsize_t
TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module)
{ {
TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ))
return ((tmsize_t)(-1));
assert((tif->tif_flags&TIFF_NOREADRAW)==0); assert((tif->tif_flags&TIFF_NOREADRAW)==0);
if (!isMapped(tif)) { if (!isMapped(tif)) {
tmsize_t cc; tmsize_t cc;
if (!SeekOK(tif, td->td_stripoffset[tile])) { if (!SeekOK(tif, TIFFGetStrileOffset(tif, tile))) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at row %lu, col %lu, tile %lu", "Seek error at row %lu, col %lu, tile %lu",
(unsigned long) tif->tif_row, (unsigned long) tif->tif_row,
@ -1135,9 +1127,9 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
} else { } else {
tmsize_t ma,mb; tmsize_t ma,mb;
tmsize_t n; tmsize_t n;
ma=(tmsize_t)td->td_stripoffset[tile]; ma=(tmsize_t)TIFFGetStrileOffset(tif, tile);
mb=ma+size; mb=ma+size;
if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) if ((TIFFGetStrileOffset(tif, tile) > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size))
n=0; n=0;
else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
n=tif->tif_size-ma; n=tif->tif_size-ma;
@ -1193,13 +1185,12 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size)
"Compression scheme does not support access to raw uncompressed data"); "Compression scheme does not support access to raw uncompressed data");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
bytecount64 = td->td_stripbytecount[tile]; bytecount64 = TIFFGetStrileByteCount(tif, tile);
if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
bytecount64 = (uint64)size; bytecountm = size;
bytecountm = (tmsize_t)bytecount64; else
if ((uint64)bytecountm!=bytecount64) bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
{ if( bytecountm == 0 ) {
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module));
@ -1215,13 +1206,10 @@ TIFFFillTile(TIFF* tif, uint32 tile)
static const char module[] = "TIFFFillTile"; static const char module[] = "TIFFFillTile";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags&TIFF_NOREADRAW)==0) if ((tif->tif_flags&TIFF_NOREADRAW)==0)
{ {
uint64 bytecount = td->td_stripbytecount[tile]; uint64 bytecount = TIFFGetStrileByteCount(tif, tile);
if ((int64)bytecount <= 0) { if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"%I64u: Invalid tile byte count, tile %lu", "%I64u: Invalid tile byte count, tile %lu",
@ -1248,7 +1236,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
(bytecount - 4096) / 10 > (uint64)stripsize ) (bytecount - 4096) / 10 > (uint64)stripsize )
{ {
uint64 newbytecount = (uint64)stripsize * 10 + 4096; uint64 newbytecount = (uint64)stripsize * 10 + 4096;
if( (int64)newbytecount >= 0 ) if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
{ {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFWarningExt(tif->tif_clientdata, module, TIFFWarningExt(tif->tif_clientdata, module,
@ -1273,13 +1261,13 @@ TIFFFillTile(TIFF* tif, uint32 tile)
* We must check for overflow, potentially causing * We must check for overflow, potentially causing
* an OOB read. Instead of simple * an OOB read. Instead of simple
* *
* td->td_stripoffset[tile]+bytecount > tif->tif_size * TIFFGetStrileOffset(tif, tile)+bytecount > tif->tif_size
* *
* comparison (which can overflow) we do the following * comparison (which can overflow) we do the following
* two comparisons: * two comparisons:
*/ */
if (bytecount > (uint64)tif->tif_size || if (bytecount > (uint64)tif->tif_size ||
td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { TIFFGetStrileOffset(tif, tile) > (uint64)tif->tif_size - bytecount) {
tif->tif_curtile = NOTILE; tif->tif_curtile = NOTILE;
return (0); return (0);
} }
@ -1308,7 +1296,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdatasize = (tmsize_t)bytecount;
tif->tif_rawdata = tif->tif_rawdata =
tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, tile);
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_rawdataloaded = (tmsize_t) bytecount;
tif->tif_flags |= TIFF_BUFFERMMAP; tif->tif_flags |= TIFF_BUFFERMMAP;
@ -1367,7 +1355,8 @@ TIFFFillTile(TIFF* tif, uint32 tile)
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = bytecountm; tif->tif_rawdataloaded = bytecountm;
if (!isFillOrder(tif, td->td_fillorder) && if (tif->tif_rawdata != NULL &&
!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits(tif->tif_rawdata, TIFFReverseBits(tif->tif_rawdata,
tif->tif_rawdataloaded); tif->tif_rawdataloaded);
@ -1434,9 +1423,6 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
{ {
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
if (!(*tif->tif_setupdecode)(tif)) if (!(*tif->tif_setupdecode)(tif))
return (0); return (0);
@ -1457,7 +1443,7 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
if( tif->tif_rawdataloaded > 0 ) if( tif->tif_rawdataloaded > 0 )
tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcc = tif->tif_rawdataloaded;
else else
tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, strip);
} }
return ((*tif->tif_predecode)(tif, return ((*tif->tif_predecode)(tif,
(uint16)(strip / td->td_stripsperimage))); (uint16)(strip / td->td_stripsperimage)));
@ -1474,9 +1460,6 @@ TIFFStartTile(TIFF* tif, uint32 tile)
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint32 howmany32; uint32 howmany32;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
if (!(*tif->tif_setupdecode)(tif)) if (!(*tif->tif_setupdecode)(tif))
return (0); return (0);
@ -1507,7 +1490,7 @@ TIFFStartTile(TIFF* tif, uint32 tile)
if( tif->tif_rawdataloaded > 0 ) if( tif->tif_rawdataloaded > 0 )
tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcc = tif->tif_rawdataloaded;
else else
tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, tile);
} }
return ((*tif->tif_predecode)(tif, return ((*tif->tif_predecode)(tif,
(uint16)(tile/td->td_stripsperimage))); (uint16)(tile/td->td_stripsperimage)));
@ -1522,13 +1505,100 @@ TIFFCheckRead(TIFF* tif, int tiles)
} }
if (tiles ^ isTiled(tif)) { if (tiles ^ isTiled(tif)) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
"Can not read tiles from a stripped image" : "Can not read tiles from a striped image" :
"Can not read scanlines from a tiled image"); "Can not read scanlines from a tiled image");
return (0); return (0);
} }
return (1); return (1);
} }
/* Use the provided input buffer (inbuf, insize) and decompress it into
* (outbuf, outsize).
* This function replaces the use of TIFFReadEncodedStrip()/TIFFReadEncodedTile()
* when the user can provide the buffer for the input data, for example when
* he wants to avoid libtiff to read the strile offset/count values from the
* [Strip|Tile][Offsets/ByteCounts] array.
* inbuf content must be writable (if bit reversal is needed)
* Returns 1 in case of success, 0 otherwise.
*/
int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
void* inbuf, tmsize_t insize,
void* outbuf, tmsize_t outsize)
{
static const char module[] = "TIFFReadFromUserBuffer";
TIFFDirectory *td = &tif->tif_dir;
int ret = 1;
uint32 old_tif_flags = tif->tif_flags;
tmsize_t old_rawdatasize = tif->tif_rawdatasize;
void* old_rawdata = tif->tif_rawdata;
if (tif->tif_mode == O_WRONLY) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading");
return 0;
}
if (tif->tif_flags&TIFF_NOREADRAW)
{
TIFFErrorExt(tif->tif_clientdata, module,
"Compression scheme does not support access to raw uncompressed data");
return 0;
}
tif->tif_flags &= ~TIFF_MYBUFFER;
tif->tif_flags |= TIFF_BUFFERMMAP;
tif->tif_rawdatasize = insize;
tif->tif_rawdata = inbuf;
tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = insize;
if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0)
{
TIFFReverseBits(inbuf, insize);
}
if( TIFFIsTiled(tif) )
{
if( !TIFFStartTile(tif, strile) ||
!(*tif->tif_decodetile)(tif, (uint8*) outbuf, outsize,
(uint16)(strile/td->td_stripsperimage)) )
{
ret = 0;
}
}
else
{
uint32 rowsperstrip=td->td_rowsperstrip;
uint32 stripsperplane;
if (rowsperstrip>td->td_imagelength)
rowsperstrip=td->td_imagelength;
stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
if( !TIFFStartStrip(tif, strile) ||
!(*tif->tif_decodestrip)(tif, (uint8*) outbuf, outsize,
(uint16)(strile/stripsperplane)) )
{
ret = 0;
}
}
if( ret )
{
(*tif->tif_postdecode)(tif, (uint8*) outbuf, outsize);
}
if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0)
{
TIFFReverseBits(inbuf, insize);
}
tif->tif_flags = old_tif_flags;
tif->tif_rawdatasize = old_rawdatasize;
tif->tif_rawdata = old_rawdata;
tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = 0;
return ret;
}
void void
_TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc) _TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc)
{ {

View file

@ -27,7 +27,6 @@
* *
* Strip-organized Image Support Routines. * Strip-organized Image Support Routines.
*/ */
#include <precomp.h> #include <precomp.h>
/* /*
@ -130,15 +129,8 @@ TIFFVStripSize(TIFF* tif, uint32 nrows)
{ {
static const char module[] = "TIFFVStripSize"; static const char module[] = "TIFFVStripSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFVStripSize64(tif,nrows); m=TIFFVStripSize64(tif,nrows);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -148,8 +140,7 @@ uint64
TIFFRawStripSize64(TIFF* tif, uint32 strip) TIFFRawStripSize64(TIFF* tif, uint32 strip)
{ {
static const char module[] = "TIFFRawStripSize64"; static const char module[] = "TIFFRawStripSize64";
TIFFDirectory* td = &tif->tif_dir; uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
uint64 bytecount = td->td_stripbytecount[strip];
if (bytecount == 0) if (bytecount == 0)
{ {
@ -212,15 +203,8 @@ TIFFStripSize(TIFF* tif)
{ {
static const char module[] = "TIFFStripSize"; static const char module[] = "TIFFStripSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFStripSize64(tif); m=TIFFStripSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -331,14 +315,8 @@ TIFFScanlineSize(TIFF* tif)
{ {
static const char module[] = "TIFFScanlineSize"; static const char module[] = "TIFFScanlineSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFScanlineSize64(tif); m=TIFFScanlineSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m) {
TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
n=0;
}
return(n);
} }
/* /*
@ -367,15 +345,8 @@ TIFFRasterScanlineSize(TIFF* tif)
{ {
static const char module[] = "TIFFRasterScanlineSize"; static const char module[] = "TIFFRasterScanlineSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFRasterScanlineSize64(tif); m=TIFFRasterScanlineSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
n=0;
}
return(n);
} }
/* vim: set ts=8 sts=8 sw=8 noet: */ /* vim: set ts=8 sts=8 sw=8 noet: */

View file

@ -123,17 +123,17 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
break; break;
case THUNDER_2BITDELTAS: /* 2-bit deltas */ case THUNDER_2BITDELTAS: /* 2-bit deltas */
if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP)
SETPIXEL(op, lastpixel + twobitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP)
SETPIXEL(op, lastpixel + twobitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
if ((delta = (n & 3)) != DELTA2_SKIP) if ((delta = (n & 3)) != DELTA2_SKIP)
SETPIXEL(op, lastpixel + twobitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
break; break;
case THUNDER_3BITDELTAS: /* 3-bit deltas */ case THUNDER_3BITDELTAS: /* 3-bit deltas */
if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP)
SETPIXEL(op, lastpixel + threebitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta]));
if ((delta = (n & 7)) != DELTA3_SKIP) if ((delta = (n & 7)) != DELTA3_SKIP)
SETPIXEL(op, lastpixel + threebitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta]));
break; break;
case THUNDER_RAW: /* raw data */ case THUNDER_RAW: /* raw data */
SETPIXEL(op, n); SETPIXEL(op, n);

View file

@ -27,7 +27,6 @@
* *
* Tiled Image Support Routines. * Tiled Image Support Routines.
*/ */
#include <precomp.h> #include <precomp.h>
/* /*
@ -182,15 +181,8 @@ TIFFTileRowSize(TIFF* tif)
{ {
static const char module[] = "TIFFTileRowSize"; static const char module[] = "TIFFTileRowSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFTileRowSize64(tif); m=TIFFTileRowSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -249,15 +241,8 @@ TIFFVTileSize(TIFF* tif, uint32 nrows)
{ {
static const char module[] = "TIFFVTileSize"; static const char module[] = "TIFFVTileSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFVTileSize64(tif,nrows); m=TIFFVTileSize64(tif,nrows);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -273,15 +258,8 @@ TIFFTileSize(TIFF* tif)
{ {
static const char module[] = "TIFFTileSize"; static const char module[] = "TIFFTileSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFTileSize64(tif); m=TIFFTileSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*

View file

@ -21,7 +21,6 @@
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE. * OF THIS SOFTWARE.
*/ */
#include <precomp.h> #include <precomp.h>
static const char TIFFVersion[] = TIFFLIB_VERSION_STR; static const char TIFFVersion[] = TIFFLIB_VERSION_STR;

View file

@ -349,6 +349,12 @@ TWebPSetupEncode(TIFF* tif)
sp->state |= LSTATE_INIT_ENCODE; sp->state |= LSTATE_INIT_ENCODE;
if (!WebPPictureInit(&sp->sPicture)) {
TIFFErrorExt(tif->tif_clientdata, module,
"Error initializing WebP picture.");
return 0;
}
if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
sp->quality_level, sp->quality_level,
WEBP_ENCODER_ABI_VERSION)) { WEBP_ENCODER_ABI_VERSION)) {
@ -357,9 +363,13 @@ TWebPSetupEncode(TIFF* tif)
return 0; return 0;
} }
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 // WebPConfigInitInternal above sets lossless to false
sp->sEncoderConfig.lossless = sp->lossless; #if WEBP_ENCODER_ABI_VERSION >= 0x0100
#endif sp->sEncoderConfig.lossless = sp->lossless;
if (sp->lossless) {
sp->sPicture.use_argb = 1;
}
#endif
if (!WebPValidateConfig(&sp->sEncoderConfig)) { if (!WebPValidateConfig(&sp->sEncoderConfig)) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -367,12 +377,6 @@ TWebPSetupEncode(TIFF* tif)
return 0; return 0;
} }
if (!WebPPictureInit(&sp->sPicture)) {
TIFFErrorExt(tif->tif_clientdata, module,
"Error initializing WebP picture.");
return 0;
}
return 1; return 1;
} }
@ -415,6 +419,12 @@ TWebPPreEncode(TIFF* tif, uint16 s)
/* set up buffer for raw data */ /* set up buffer for raw data */
/* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
sp->buffer_size = segment_width * segment_height * sp->nSamples; sp->buffer_size = segment_width * segment_height * sp->nSamples;
if (sp->pBuffer != NULL) {
_TIFFfree(sp->pBuffer);
sp->pBuffer = NULL;
}
sp->pBuffer = _TIFFmalloc(sp->buffer_size); sp->pBuffer = _TIFFmalloc(sp->buffer_size);
if( !sp->pBuffer) { if( !sp->pBuffer) {
TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer");
@ -540,14 +550,12 @@ TWebPCleanup(TIFF* tif)
} }
if (sp->pBuffer != NULL) { if (sp->pBuffer != NULL) {
_TIFFfree(sp->pBuffer); _TIFFfree(sp->pBuffer);
sp->pBuffer = NULL; sp->pBuffer = NULL;
} }
if (tif->tif_data) { _TIFFfree(tif->tif_data);
_TIFFfree(tif->tif_data); tif->tif_data = NULL;
tif->tif_data = NULL;
}
_TIFFSetDefaultCompressionState(tif); _TIFFSetDefaultCompressionState(tif);
} }
@ -570,6 +578,9 @@ TWebPVSetField(TIFF* tif, uint32 tag, va_list ap)
case TIFFTAG_WEBP_LOSSLESS: case TIFFTAG_WEBP_LOSSLESS:
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
sp->lossless = va_arg(ap, int); sp->lossless = va_arg(ap, int);
if (sp->lossless){
sp->quality_level = 100.0f;
}
return 1; return 1;
#else #else
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,

View file

@ -27,7 +27,6 @@
* *
* Scanline-oriented Write Support * Scanline-oriented Write Support
*/ */
#include <precomp.h> #include <precomp.h>
//#include <stdio.h> //#include <stdio.h>
@ -129,10 +128,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
tif->tif_rawcc = 0; tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata; tif->tif_rawcp = tif->tif_rawdata;
if( td->td_stripbytecount[strip] > 0 ) if( td->td_stripbytecount_p[strip] > 0 )
{ {
/* if we are writing over existing tiles, zero length */ /* if we are writing over existing tiles, zero length */
td->td_stripbytecount[strip] = 0; td->td_stripbytecount_p[strip] = 0;
/* this forces TIFFAppendToStrip() to do a seek */ /* this forces TIFFAppendToStrip() to do a seek */
tif->tif_curoff = 0; tif->tif_curoff = 0;
@ -177,6 +176,32 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
return (status); return (status);
} }
/* Make sure that at the first attempt of rewriting a tile/strip, 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) */
static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32 strip_or_tile)
{
TIFFDirectory *td = &tif->tif_dir;
if( td->td_stripbytecount_p[strip_or_tile] > 0 )
{
/* The +1 is to ensure at least one extra bytes */
/* The +4 is because the LZW encoder flushes 4 bytes before the limit */
uint64 safe_buffer_size = (uint64)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
if( tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size )
{
if( !(TIFFWriteBufferSetup(tif, NULL,
(tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))) )
return 0;
}
/* Force TIFFAppendToStrip() to consider placing data at end
of file. */
tif->tif_curoff = 0;
}
return 1;
}
/* /*
* Encode the supplied data and write it to the * Encode the supplied data and write it to the
* specified strip. * specified strip.
@ -223,6 +248,13 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curstrip = strip; tif->tif_curstrip = strip;
if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) {
return ((tmsize_t)(-1));
}
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
if (td->td_stripsperimage == 0) { if (td->td_stripsperimage == 0) {
TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
return ((tmsize_t) -1); return ((tmsize_t) -1);
@ -235,27 +267,6 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_CODERSETUP; 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; tif->tif_flags &= ~TIFF_POSTENCODE;
/* shortcut to avoid an extra memcpy() */ /* shortcut to avoid an extra memcpy() */
@ -403,22 +414,8 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curtile = tile; tif->tif_curtile = tile;
if( td->td_stripbytecount[tile] > 0 ) if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
{ return ((tmsize_t)(-1));
/* 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_rawcc = 0;
@ -538,20 +535,20 @@ TIFFSetupStrips(TIFF* tif)
td->td_nstrips = td->td_stripsperimage; td->td_nstrips = td->td_stripsperimage;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
td->td_stripsperimage /= td->td_samplesperpixel; td->td_stripsperimage /= td->td_samplesperpixel;
td->td_stripoffset = (uint64 *) td->td_stripoffset_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripOffsets\" array"); "for \"StripOffsets\" array");
td->td_stripbytecount = (uint64 *) td->td_stripbytecount_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripByteCounts\" array"); "for \"StripByteCounts\" array");
if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
return (0); return (0);
/* /*
* Place data at the end-of-file * Place data at the end-of-file
* (by setting offsets to zero). * (by setting offsets to zero).
*/ */
_TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64));
_TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64));
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
return (1); return (1);
@ -573,7 +570,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
} }
if (tiles ^ isTiled(tif)) { if (tiles ^ isTiled(tif)) {
TIFFErrorExt(tif->tif_clientdata, module, tiles ? TIFFErrorExt(tif->tif_clientdata, module, tiles ?
"Can not write tiles to a stripped image" : "Can not write tiles to a striped image" :
"Can not write scanlines to a tiled image"); "Can not write scanlines to a tiled image");
return (0); return (0);
} }
@ -611,7 +608,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
return (0); return (0);
} }
} }
if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) {
tif->tif_dir.td_nstrips = 0; tif->tif_dir.td_nstrips = 0;
TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
isTiled(tif) ? "tile" : "strip"); isTiled(tif) ? "tile" : "strip");
@ -629,6 +626,20 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
if (tif->tif_scanlinesize == 0) if (tif->tif_scanlinesize == 0)
return (0); return (0);
tif->tif_flags |= TIFF_BEENWRITING; tif->tif_flags |= TIFF_BEENWRITING;
if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
!(tif->tif_flags & TIFF_DIRTYDIRECT) )
{
TIFFForceStrileArrayWriting(tif);
}
return (1); return (1);
} }
@ -685,9 +696,9 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
uint64* new_stripbytecount; uint64* new_stripbytecount;
assert(td->td_planarconfig == PLANARCONFIG_CONTIG); assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset_p,
(td->td_nstrips + delta) * sizeof (uint64)); (td->td_nstrips + delta) * sizeof (uint64));
new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount_p,
(td->td_nstrips + delta) * sizeof (uint64)); (td->td_nstrips + delta) * sizeof (uint64));
if (new_stripoffset == NULL || new_stripbytecount == NULL) { if (new_stripoffset == NULL || new_stripbytecount == NULL) {
if (new_stripoffset) if (new_stripoffset)
@ -698,11 +709,11 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
return (0); return (0);
} }
td->td_stripoffset = new_stripoffset; td->td_stripoffset_p = new_stripoffset;
td->td_stripbytecount = new_stripbytecount; td->td_stripbytecount_p = new_stripbytecount;
_TIFFmemset(td->td_stripoffset + td->td_nstrips, _TIFFmemset(td->td_stripoffset_p + td->td_nstrips,
0, delta*sizeof (uint64)); 0, delta*sizeof (uint64));
_TIFFmemset(td->td_stripbytecount + td->td_nstrips, _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips,
0, delta*sizeof (uint64)); 0, delta*sizeof (uint64));
td->td_nstrips += delta; td->td_nstrips += delta;
tif->tif_flags |= TIFF_DIRTYDIRECT; tif->tif_flags |= TIFF_DIRTYDIRECT;
@ -721,12 +732,12 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
uint64 m; uint64 m;
int64 old_byte_count = -1; int64 old_byte_count = -1;
if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
assert(td->td_nstrips > 0); assert(td->td_nstrips > 0);
if( td->td_stripbytecount[strip] != 0 if( td->td_stripbytecount_p[strip] != 0
&& td->td_stripoffset[strip] != 0 && td->td_stripoffset_p[strip] != 0
&& td->td_stripbytecount[strip] >= (uint64) cc ) && td->td_stripbytecount_p[strip] >= (uint64) cc )
{ {
/* /*
* There is already tile data on disk, and the new tile * There is already tile data on disk, and the new tile
@ -735,7 +746,7 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
* more data to append to this strip before we are done * more data to append to this strip before we are done
* depending on how we are getting called. * depending on how we are getting called.
*/ */
if (!SeekOK(tif, td->td_stripoffset[strip])) { if (!SeekOK(tif, td->td_stripoffset_p[strip])) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at scanline %lu", "Seek error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_row);
@ -748,17 +759,17 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
* Seek to end of file, and set that as our location to * Seek to end of file, and set that as our location to
* write this strip. * write this strip.
*/ */
td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
tif->tif_flags |= TIFF_DIRTYSTRIP; tif->tif_flags |= TIFF_DIRTYSTRIP;
} }
tif->tif_curoff = td->td_stripoffset[strip]; tif->tif_curoff = td->td_stripoffset_p[strip];
/* /*
* We are starting a fresh strip/tile, so set the size to zero. * We are starting a fresh strip/tile, so set the size to zero.
*/ */
old_byte_count = td->td_stripbytecount[strip]; old_byte_count = td->td_stripbytecount_p[strip];
td->td_stripbytecount[strip] = 0; td->td_stripbytecount_p[strip] = 0;
} }
m = tif->tif_curoff+cc; m = tif->tif_curoff+cc;
@ -775,9 +786,9 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
return (0); return (0);
} }
tif->tif_curoff = m; tif->tif_curoff = m;
td->td_stripbytecount[strip] += cc; td->td_stripbytecount_p[strip] += cc;
if( (int64) td->td_stripbytecount[strip] != old_byte_count ) if( (int64) td->td_stripbytecount_p[strip] != old_byte_count )
tif->tif_flags |= TIFF_DIRTYSTRIP; tif->tif_flags |= TIFF_DIRTYSTRIP;
return (1); return (1);

View file

@ -23,7 +23,6 @@
*/ */
#include <precomp.h> #include <precomp.h>
#ifdef ZIP_SUPPORT #ifdef ZIP_SUPPORT
/* /*
* TIFF Library. * TIFF Library.
@ -48,7 +47,7 @@
#include "tif_predict.h" #include "tif_predict.h"
#include "zlib.h" #include "zlib.h"
//#include <stdio.h> #include <stdio.h>
/* /*
* Sigh, ZLIB_VERSION is defined as a string so there's no * Sigh, ZLIB_VERSION is defined as a string so there's no
@ -125,7 +124,6 @@ ZIPSetupDecode(TIFF* tif)
static int static int
ZIPPreDecode(TIFF* tif, uint16 s) ZIPPreDecode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreDecode";
ZIPState* sp = DecoderState(tif); ZIPState* sp = DecoderState(tif);
(void) s; (void) s;
@ -139,12 +137,7 @@ ZIPPreDecode(TIFF* tif, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = (uInt) tif->tif_rawcc; sp->stream.avail_in = (uint64)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt) tif->tif_rawcc : 0xFFFFFFFFU;
if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
return (inflateReset(&sp->stream) == Z_OK); return (inflateReset(&sp->stream) == Z_OK);
} }
@ -159,46 +152,43 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
assert(sp->state == ZSTATE_INIT_DECODE); assert(sp->state == ZSTATE_INIT_DECODE);
sp->stream.next_in = tif->tif_rawcp; sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (uInt) tif->tif_rawcc;
sp->stream.next_out = op; sp->stream.next_out = op;
assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised,
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_out = (uInt) occ;
if ((tmsize_t)sp->stream.avail_out != occ)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
do { do {
int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); int state;
uInt avail_in_before = (uint64)tif->tif_rawcc <= 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU;
uInt avail_out_before = (uint64)occ < 0xFFFFFFFFU ? (uInt) occ : 0xFFFFFFFFU;
sp->stream.avail_in = avail_in_before;
sp->stream.avail_out = avail_out_before;
state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in);
occ -= (avail_out_before - sp->stream.avail_out);
if (state == Z_STREAM_END) if (state == Z_STREAM_END)
break; break;
if (state == Z_DATA_ERROR) { if (state == Z_DATA_ERROR) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, SAFE_MSG(sp)); (unsigned long) tif->tif_row, SAFE_MSG(sp));
if (inflateSync(&sp->stream) != Z_OK) return (0);
return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"ZLib error: %s", SAFE_MSG(sp)); "ZLib error: %s", SAFE_MSG(sp));
return (0); return (0);
} }
} while (sp->stream.avail_out > 0); } while (occ > 0);
if (sp->stream.avail_out != 0) { if (occ != 0) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)",
(unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); (unsigned long) tif->tif_row, (TIFF_UINT64_T) occ);
return (0); return (0);
} }
tif->tif_rawcp = sp->stream.next_in; tif->tif_rawcp = sp->stream.next_in;
tif->tif_rawcc = sp->stream.avail_in;
return (1); return (1);
} }
@ -230,7 +220,6 @@ ZIPSetupEncode(TIFF* tif)
static int static int
ZIPPreEncode(TIFF* tif, uint16 s) ZIPPreEncode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreEncode";
ZIPState *sp = EncoderState(tif); ZIPState *sp = EncoderState(tif);
(void) s; (void) s;
@ -243,12 +232,7 @@ ZIPPreEncode(TIFF* tif, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_out = (uInt)tif->tif_rawdatasize; sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
return (deflateReset(&sp->stream) == Z_OK); return (deflateReset(&sp->stream) == Z_OK);
} }
@ -270,13 +254,9 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = (uInt) cc;
if ((tmsize_t)sp->stream.avail_in != cc)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
do { do {
uInt avail_in_before = (uint64)cc <= 0xFFFFFFFFU ? (uInt)cc : 0xFFFFFFFFU;
sp->stream.avail_in = avail_in_before;
if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Encoder error: %s", "Encoder error: %s",
@ -287,9 +267,10 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
tif->tif_rawcc = tif->tif_rawdatasize; tif->tif_rawcc = tif->tif_rawdatasize;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; sp->stream.next_out = tif->tif_rawdata;
sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
} }
} while (sp->stream.avail_in > 0); cc -= (avail_in_before - sp->stream.avail_in);
} while (cc > 0);
return (1); return (1);
} }
@ -315,7 +296,7 @@ ZIPPostEncode(TIFF* tif)
tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; sp->stream.next_out = tif->tif_rawdata;
sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
} }
break; break;
default: default:

View file

@ -79,7 +79,7 @@ Used Version: 9c
Website: http://www.ijg.org/ Website: http://www.ijg.org/
Title: libtiff Title: libtiff
Used Version: 4.0.10 Used Version: 4.1.0
Website: http://www.simplesystems.org/libtiff/ Website: http://www.simplesystems.org/libtiff/
Title: mbed TLS Title: mbed TLS

View file

@ -58,6 +58,7 @@ typedef struct {
uint32 toff_long; uint32 toff_long;
uint64 toff_long8; uint64 toff_long8;
} tdir_offset; /* either offset or the data itself if fits */ } tdir_offset; /* either offset or the data itself if fits */
uint8 tdir_ignore; /* flag status to ignore tag when parsing tags in tif_dirread.c */
} TIFFDirEntry; } TIFFDirEntry;
/* /*
@ -97,13 +98,14 @@ typedef struct {
* number of striles */ * number of striles */
uint32 td_stripsperimage; uint32 td_stripsperimage;
uint32 td_nstrips; /* size of offset & bytecount arrays */ uint32 td_nstrips; /* size of offset & bytecount arrays */
uint64* td_stripoffset; uint64* td_stripoffset_p; /* should be accessed with TIFFGetStrileOffset */
uint64* td_stripbytecount; uint64* td_stripbytecount_p; /* should be accessed with TIFFGetStrileByteCount */
uint32 td_stripoffsetbyteallocsize; /* number of elements currently allocated for td_stripoffset/td_stripbytecount. Only used if TIFF_LAZYSTRILELOAD is set */
#ifdef STRIPBYTECOUNTSORTED_UNUSED
int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
#if defined(DEFER_STRILE_LOAD) #endif
TIFFDirEntry td_stripoffset_entry; /* for deferred loading */ TIFFDirEntry td_stripoffset_entry; /* for deferred loading */
TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */ TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
#endif
uint16 td_nsubifd; uint16 td_nsubifd;
uint64* td_subifd; uint64* td_subifd;
/* YCbCr parameters */ /* YCbCr parameters */
@ -118,6 +120,8 @@ typedef struct {
int td_customValueCount; int td_customValueCount;
TIFFTagValue *td_customValues; TIFFTagValue *td_customValues;
unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
} TIFFDirectory; } TIFFDirectory;
/* /*

View file

@ -94,12 +94,7 @@ typedef void* tdata_t; /* image data ref */
#if defined(USE_WIN32_FILEIO) #if defined(USE_WIN32_FILEIO)
# define VC_EXTRALEAN # define VC_EXTRALEAN
#ifdef __REACTOS__
# define WIN32_NO_STATUS
# include <windef.h>
#else /* __REACTOS__ */
# include <windows.h> # include <windows.h>
#endif /* __REACTOS__ */
# ifdef __WIN32__ # ifdef __WIN32__
DECLARE_HANDLE(thandle_t); /* Win32 file handle */ DECLARE_HANDLE(thandle_t); /* Win32 file handle */
# else # else
@ -416,6 +411,8 @@ extern int TIFFWriteDirectory(TIFF *);
extern int TIFFWriteCustomDirectory(TIFF *, uint64 *); extern int TIFFWriteCustomDirectory(TIFF *, uint64 *);
extern int TIFFCheckpointDirectory(TIFF *); extern int TIFFCheckpointDirectory(TIFF *);
extern int TIFFRewriteDirectory(TIFF *); extern int TIFFRewriteDirectory(TIFF *);
extern int TIFFDeferStrileArrayWriting(TIFF *);
extern int TIFFForceStrileArrayWriting(TIFF* );
#if defined(c_plusplus) || defined(__cplusplus) #if defined(c_plusplus) || defined(__cplusplus)
extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0);
@ -473,6 +470,9 @@ extern tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_
extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size); extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size);
extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);
extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);
extern int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
void* inbuf, tmsize_t insize,
void* outbuf, tmsize_t outsize);
extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc);
@ -493,6 +493,11 @@ extern void TIFFSwabArrayOfDouble(double* dp, tmsize_t n);
extern void TIFFReverseBits(uint8* cp, tmsize_t n); extern void TIFFReverseBits(uint8* cp, tmsize_t n);
extern const unsigned char* TIFFGetBitRevTable(int); extern const unsigned char* TIFFGetBitRevTable(int);
extern uint64 TIFFGetStrileOffset(TIFF *tif, uint32 strile);
extern uint64 TIFFGetStrileByteCount(TIFF *tif, uint32 strile);
extern uint64 TIFFGetStrileOffsetWithErr(TIFF *tif, uint32 strile, int *pbErr);
extern uint64 TIFFGetStrileByteCountWithErr(TIFF *tif, uint32 strile, int *pbErr);
#ifdef LOGLUV_PUBLIC #ifdef LOGLUV_PUBLIC
#define U_NEU 0.210526316 #define U_NEU 0.210526316
#define V_NEU 0.473684211 #define V_NEU 0.473684211

View file

@ -77,6 +77,19 @@ extern int snprintf(char* str, size_t size, const char* format, ...);
#define FALSE 0 #define FALSE 0
#endif #endif
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
/*
* Largest 32-bit unsigned integer value.
*/
#define TIFF_UINT32_MAX 0xFFFFFFFFU
/*
* Largest 64-bit unsigned integer value.
*/
#define TIFF_UINT64_MAX (((uint64)(TIFF_UINT32_MAX)) << 32 | TIFF_UINT32_MAX)
typedef struct client_info { typedef struct client_info {
struct client_info *next; struct client_info *next;
void *data; void *data;
@ -127,6 +140,9 @@ struct tiff {
#define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/ #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/
#define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */ #define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */
#define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */ #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */
#define TIFF_DEFERSTRILELOAD 0x1000000U /* defer strip/tile offset/bytecount array loading. */
#define TIFF_LAZYSTRILELOAD 0x2000000U /* lazy/ondemand loading of strip/tile offset/bytecount values. Only used if TIFF_DEFERSTRILELOAD is set and in read-only mode */
#define TIFF_CHOPPEDUPARRAYS 0x4000000U /* set when allocChoppedUpStripArrays() has modified strip array */
uint64 tif_diroff; /* file offset of current directory */ uint64 tif_diroff; /* file offset of current directory */
uint64 tif_nextdiroff; /* file offset of following directory */ uint64 tif_nextdiroff; /* file offset of following directory */
uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */
@ -258,7 +274,7 @@ struct tiff {
#define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3) #define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3)
#define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y)) #define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y))
/* Safe multiply which returns zero if there is an integer overflow */ /* Safe multiply which returns zero if there is an *unsigned* integer overflow. This macro is not safe for *signed* integer types */
#define TIFFSafeMultiply(t,v,m) ((((t)(m) != (t)0) && (((t)(((v)*(m))/(m))) == (t)(v))) ? (t)((v)*(m)) : (t)0) #define TIFFSafeMultiply(t,v,m) ((((t)(m) != (t)0) && (((t)(((v)*(m))/(m))) == (t)(v))) ? (t)((v)*(m)) : (t)0)
#define TIFFmax(A,B) ((A)>(B)?(A):(B)) #define TIFFmax(A,B) ((A)>(B)?(A):(B))
@ -368,12 +384,16 @@ extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
extern uint32 _TIFFMultiply32(TIFF*, uint32, uint32, const char*); extern uint32 _TIFFMultiply32(TIFF*, uint32, uint32, const char*);
extern uint64 _TIFFMultiply64(TIFF*, uint64, uint64, const char*); extern uint64 _TIFFMultiply64(TIFF*, uint64, uint64, const char*);
extern tmsize_t _TIFFMultiplySSize(TIFF*, tmsize_t, tmsize_t, const char*);
extern tmsize_t _TIFFCastUInt64ToSSize(TIFF*, uint64, const char*);
extern void* _TIFFCheckMalloc(TIFF*, tmsize_t, tmsize_t, const char*); extern void* _TIFFCheckMalloc(TIFF*, tmsize_t, tmsize_t, const char*);
extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*);
extern double _TIFFUInt64ToDouble(uint64); extern double _TIFFUInt64ToDouble(uint64);
extern float _TIFFUInt64ToFloat(uint64); extern float _TIFFUInt64ToFloat(uint64);
extern float _TIFFClampDoubleToFloat(double);
extern tmsize_t extern tmsize_t
_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip,
void **buf, tmsize_t bufsizetoalloc, void **buf, tmsize_t bufsizetoalloc,

View file

@ -1,4 +1,4 @@
#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.10\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." #define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.1.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
/* /*
* This define can be used in code that requires * This define can be used in code that requires
* compilation-related definitions specific to a * compilation-related definitions specific to a
@ -6,4 +6,4 @@
* version checking should be done based on the * version checking should be done based on the
* string returned by TIFFGetVersion. * string returned by TIFFGetVersion.
*/ */
#define TIFFLIB_VERSION 20181110 #define TIFFLIB_VERSION 20191103