tiff: Import upstream release 4.7.0.

This commit is contained in:
Alexandre Julliard 2024-10-12 19:03:12 +02:00
parent 8f7fd7c739
commit 6ffad0c8e3
23 changed files with 1630 additions and 537 deletions

View file

@ -385,53 +385,6 @@ int TIFFGetFieldDefaulted(TIFF *tif, uint32_t tag, ...)
return (ok);
}
struct _Int64Parts
{
int32_t low, high;
};
typedef union
{
struct _Int64Parts part;
int64_t value;
} _Int64;
float _TIFFUInt64ToFloat(uint64_t ui64)
{
_Int64 i;
i.value = ui64;
if (i.part.high >= 0)
{
return (float)i.value;
}
else
{
long double df;
df = (long double)i.value;
df += 18446744073709551616.0; /* adding 2**64 */
return (float)df;
}
}
double _TIFFUInt64ToDouble(uint64_t ui64)
{
_Int64 i;
i.value = ui64;
if (i.part.high >= 0)
{
return (double)i.value;
}
else
{
long double df;
df = (long double)i.value;
df += 18446744073709551616.0; /* adding 2**64 */
return (double)df;
}
}
float _TIFFClampDoubleToFloat(double val)
{
if (val > FLT_MAX)

View file

@ -110,6 +110,14 @@ void TIFFCleanup(TIFF *tif)
_TIFFfreeExt(tif, tif->tif_fieldscompat);
}
if (tif->tif_cur_cumulated_mem_alloc != 0)
{
TIFFErrorExtR(tif, "TIFFCleanup",
"tif_cur_cumulated_mem_alloc = %" PRIu64 " whereas it "
"should be 0",
(uint64_t)tif->tif_cur_cumulated_mem_alloc);
}
_TIFFfreeExt(NULL, tif);
}

View file

@ -211,7 +211,7 @@ static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
}
bad:
TIFFErrorExtR(tif, "TIFFSetField",
"%s: Invalid InkNames value; no NUL at given buffer end "
"%s: Invalid InkNames value; no null at given buffer end "
"location %" PRIu32 ", after %" PRIu16 " ink",
tif->tif_name, slen, i);
return (0);
@ -1652,6 +1652,17 @@ void TIFFFreeDirectory(TIFF *tif)
_TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
_TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
/* Reset some internal parameters for IFD data size checking. */
tif->tif_dir.td_dirdatasize_read = 0;
tif->tif_dir.td_dirdatasize_write = 0;
if (tif->tif_dir.td_dirdatasize_offsets != NULL)
{
_TIFFfreeExt(tif, tif->tif_dir.td_dirdatasize_offsets);
tif->tif_dir.td_dirdatasize_offsets = NULL;
tif->tif_dir.td_dirdatasize_Noffsets = 0;
}
tif->tif_dir.td_iswrittentofile = FALSE;
}
#undef CleanupField
@ -1676,18 +1687,23 @@ TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender)
*/
int TIFFCreateDirectory(TIFF *tif)
{
/* Free previously allocated memory and setup default values. */
TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
tif->tif_diroff = 0;
tif->tif_nextdiroff = 0;
tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_dir.td_iswrittentofile = FALSE;
return 0;
}
int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
{
/* Free previously allocated memory and setup default values. */
TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
/*
@ -1848,7 +1864,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (((uint64_t)poffa != poff) || (poffb < poffa) ||
(poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
*nextdiroff = 0;
return (0);
}
@ -1877,14 +1895,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
uint16_t dircount16;
if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
poffa = (tmsize_t)poff;
poffb = poffa + sizeof(uint64_t);
if (poffb > tif->tif_size)
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
_TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t));
@ -1926,8 +1948,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount, sizeof(uint16_t)))
{
TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
tif->tif_name);
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@ -1953,15 +1976,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount64, sizeof(uint64_t)))
{
TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
tif->tif_name);
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&dircount64);
if (dircount64 > 0xFFFF)
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
dircount16 = (uint16_t)dircount64;
@ -2018,6 +2044,8 @@ tdir_t TIFFNumberOfDirectories(TIFF *tif)
{
++n;
}
/* Update number of main-IFDs in file. */
tif->tif_curdircount = n;
return (n);
}
@ -2100,7 +2128,19 @@ int TIFFSetDirectory(TIFF *tif, tdir_t dirn)
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
else
tif->tif_curdir--;
return (TIFFReadDirectory(tif));
tdir_t curdir = tif->tif_curdir;
int retval = TIFFReadDirectory(tif);
if (!retval && tif->tif_curdir == curdir)
{
/* If tif_curdir has not be incremented, TIFFFetchDirectory() in
* TIFFReadDirectory() has failed and tif_curdir shall be set
* specifically. */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
return (retval);
}
/*
@ -2125,8 +2165,11 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
int8_t probablySubIFD = 0;
if (diroff == 0)
{
/* Special case to invalidate the tif_lastdiroff member. */
/* Special case to set tif_diroff=0, which is done in
* TIFFReadDirectory() below to indicate that the currently read IFD is
* treated as a new, fresh IFD. */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
tif->tif_dir.td_iswrittentofile = FALSE;
}
else
{
@ -2136,32 +2179,40 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
probablySubIFD = 1;
}
/* -1 because TIFFReadDirectory() will increment tif_curdir. */
tif->tif_curdir =
curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1;
if (curdir >= 1)
tif->tif_curdir = curdir - 1;
else
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
curdir = tif->tif_curdir;
tif->tif_nextdiroff = diroff;
retval = TIFFReadDirectory(tif);
/* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
* back, but leave it for diroff==0. */
if (!retval && diroff != 0)
/* tif_curdir is incremented in TIFFReadDirectory(), but if it has not been
* incremented, TIFFFetchDirectory() has failed there and tif_curdir shall
* be set specifically. */
if (!retval && diroff != 0 && tif->tif_curdir == curdir)
{
if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
tif->tif_curdir = 0;
else
tif->tif_curdir++;
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
if (retval && probablySubIFD)
if (probablySubIFD)
{
/* Reset IFD list to start new one for SubIFD chain and also start
* SubIFD chain with tif_curdir=0. */
_TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
tif->tif_curdir = 0; /* first directory of new chain */
/* add this offset to new IFD list */
_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
if (retval)
{
/* Reset IFD list to start new one for SubIFD chain and also start
* SubIFD chain with tif_curdir=0 for IFD loop checking. */
/* invalidate IFD loop lists */
_TIFFCleanupIFDOffsetAndNumberMaps(tif);
tif->tif_curdir = 0; /* first directory of new chain */
/* add this offset to new IFD list */
_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
}
/* To be able to return from SubIFD or custom-IFD to main-IFD */
tif->tif_setdirectory_force_absolute = TRUE;
}
return (retval);
}
@ -2257,9 +2308,11 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
}
else
{
/* Need local swap because nextdir has to be used unswapped below. */
uint64_t nextdir64 = nextdir;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&nextdir);
if (!WriteOK(tif, &nextdir, sizeof(uint64_t)))
TIFFSwabLong8(&nextdir64);
if (!WriteOK(tif, &nextdir64, sizeof(uint64_t)))
{
TIFFErrorExtR(tif, module, "Error writing directory link");
return (0);
@ -2303,6 +2356,10 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
if (tif->tif_curdircount > 0)
tif->tif_curdircount--;
else
tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
_TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
return (1);
}

View file

@ -65,6 +65,12 @@ typedef struct
tif_dirread.c */
} TIFFDirEntry;
typedef struct
{
uint64_t offset;
uint64_t length;
} TIFFEntryOffsetAndLength; /* auxiliary for evaluating size of IFD data */
/*
* Internal format of a TIFF directory entry.
*/
@ -115,6 +121,9 @@ typedef struct
#ifdef STRIPBYTECOUNTSORTED_UNUSED
int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
#endif
/* Be aware that the parameters of td_stripoffset_entry and
* td_stripbytecount_entry are swapped but tdir_offset is not
* and has to be swapped when used. */
TIFFDirEntry td_stripoffset_entry; /* for deferred loading */
TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
uint16_t td_nsubifd;
@ -135,6 +144,24 @@ typedef struct
unsigned char
td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
unsigned char
td_iswrittentofile; /* indicates if current IFD is present on file */
/* LibTIFF writes all data that does not fit into the IFD entries directly
* after the IFD tag entry part. When reading, only the IFD data directly
* and continuously behind the IFD tags is taken into account for the IFD
* data size.*/
uint64_t td_dirdatasize_write; /* auxiliary for evaluating size of IFD data
to be written */
uint64_t td_dirdatasize_read; /* auxiliary for evaluating size of IFD data
read from file */
uint32_t td_dirdatasize_Noffsets; /* auxiliary counter for
tif_dir.td_dirdatasize_offsets array */
TIFFEntryOffsetAndLength
*td_dirdatasize_offsets; /* auxiliary array for all offsets of IFD tag
entries with data outside the IFD tag
entries. */
} TIFFDirectory;
/*
@ -308,11 +335,10 @@ extern "C"
TIFFDataType field_type; /* type of associated data */
uint32_t
field_anonymous; /* if true, this is a unknown / anonymous tag */
TIFFSetGetFieldType
set_field_type; /* type to be passed to TIFFSetField */
TIFFSetGetFieldType
get_field_type; /* type to be passed to TIFFGetField */
unsigned short field_bit; /* bit in fieldsset bit vector */
TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField
and TIFFGetField*/
TIFFSetGetFieldType get_field_type; /* not used */
unsigned short field_bit; /* bit in fieldsset bit vector */
unsigned char field_oktochange; /* if true, can change while writing */
unsigned char field_passcount; /* if true, pass dir count on set */
char *field_name; /* ASCII name */

View file

@ -213,8 +213,6 @@ static const TIFFField tiffFields[] = {
{TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentPreProfileMatrix", NULL},
{TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
#if 0
/* TODO: revert above #if 0 for TIFF 4.6.0 */
/* begin DNG 1.2.0.0 tags */
{TIFFTAG_COLORIMETRICREFERENCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorimetricReference", NULL},
{TIFFTAG_CAMERACALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibrationSignature", NULL},
@ -282,9 +280,11 @@ static const TIFFField tiffFields[] = {
{TIFFTAG_ILLUMINANTDATA2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData2", NULL},
{TIFFTAG_ILLUMINANTDATA3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData3", NULL},
/* end DNG tags */
#endif
/* begin TIFF/EP tags */
{TIFFTAG_EP_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CFARepeatPatternDim", NULL},
{TIFFTAG_EP_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP CFAPattern", NULL},
#if 0
/* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
* LibTiff defines it as ASCII and converts RATIONAL to an ASCII string. */
{TIFFTAG_EP_BATTERYLEVEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP BatteryLevel", NULL},
@ -887,7 +887,7 @@ const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag,
if (fld == NULL)
{
fld = _TIFFCreateAnonField(tif, tag, dt);
if (!_TIFFMergeFields(tif, fld, 1))
if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
return NULL;
}
@ -1197,12 +1197,24 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
for (i = 0; i < n; i++)
{
tp->field_tag = info[i].field_tag;
if (info[i].field_readcount < TIFF_VARIABLE2 ||
info[i].field_readcount == 0 ||
info[i].field_writecount < TIFF_VARIABLE2 ||
info[i].field_writecount == 0)
{
/* The fields (field_readcount) and (field_writecount) may use the
* values TIFF_VARIABLE (-1), TIFF_SPP (-2), TIFF_VARIABLE2 (-3). */
TIFFErrorExtR(tif, module,
"The value of field_readcount and field_writecount "
"must be greater than or equal to -3 and not zero.");
return -1;
}
tp->field_readcount = info[i].field_readcount;
tp->field_writecount = info[i].field_writecount;
tp->field_type = info[i].field_type;
tp->field_anonymous = 0;
tp->set_field_type =
_TIFFSetGetType(info[i].field_type, info[i].field_readcount,
_TIFFSetGetType(info[i].field_type, info[i].field_writecount,
info[i].field_passcount);
tp->get_field_type =
_TIFFSetGetType(info[i].field_type, info[i].field_readcount,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -41,6 +41,14 @@
#include "t4.h"
#include <stdio.h>
#ifndef EOF_REACHED_COUNT_THRESHOLD
/* Arbitrary threshold to avoid corrupted single-strip files with extremely
* large imageheight to cause apparently endless looping, such as in
* https://gitlab.com/libtiff/libtiff/-/issues/583
*/
#define EOF_REACHED_COUNT_THRESHOLD 8192
#endif
/*
* Compression+decompression state blocks are
* derived from this ``base state'' block.
@ -77,6 +85,8 @@ typedef struct
uint32_t data; /* current i/o byte/word */
int bit; /* current i/o bit in byte */
int EOLcnt; /* count of EOL codes recognized */
int eofReachedCount; /* number of times decode has been called with
EOF already reached */
TIFFFaxFillFunc fill; /* fill routine */
uint32_t *runs; /* b&w runs for current/previous row */
uint32_t nruns; /* size of the refruns / curruns arrays */
@ -120,6 +130,7 @@ typedef struct
int EOLcnt; /* # EOL codes recognized */ \
const unsigned char *bitmap = sp->bitmap; /* input data bit reverser */ \
const TIFFFaxTabEnt *TabEnt
#define DECLARE_STATE_2D(tif, sp, mod) \
DECLARE_STATE(tif, sp, mod); \
int b1; /* next change on prev line */ \
@ -162,6 +173,7 @@ static int Fax3PreDecode(TIFF *tif, uint16_t s)
sp->bit = 0; /* force initial read */
sp->data = 0;
sp->EOLcnt = 0; /* force initial scan for EOL */
sp->eofReachedCount = 0;
/*
* Decoder assumes lsb-to-msb bit order. Note that we select
* this here rather than in Fax3SetupState so that viewers can
@ -232,7 +244,12 @@ static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line,
line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
}
#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0)
#define prematureEOF(a0) \
do \
{ \
Fax3PrematureEOF(module, tif, sp->line, a0); \
++sp->eofReachedCount; \
} while (0)
#define Nop
@ -252,6 +269,14 @@ static int Fax3Decode1D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
thisrun = sp->curruns;
while (occ > 0)
@ -302,6 +327,14 @@ static int Fax3Decode2D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
while (occ > 0)
{
@ -536,7 +569,11 @@ static int Fax3SetupState(TIFF *tif)
TIFFroundup and TIFFSafeMultiply return zero on integer overflow
*/
dsp->runs = (uint32_t *)NULL;
if (dsp->runs != NULL)
{
_TIFFfreeExt(tif, dsp->runs);
dsp->runs = (uint32_t *)NULL;
}
dsp->nruns = TIFFroundup_32(rowpixels + 1, 32);
if (needsRefLine)
{
@ -578,6 +615,10 @@ static int Fax3SetupState(TIFF *tif)
* is referenced. The reference line must
* be initialized to be ``white'' (done elsewhere).
*/
if (esp->refline != NULL)
{
_TIFFfreeExt(tif, esp->refline);
}
esp->refline = (unsigned char *)_TIFFmallocExt(tif, rowbytes);
if (esp->refline == NULL)
{
@ -1514,7 +1555,16 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
int start = sp->line;
while (occ > 0)
{
a0 = 0;
@ -1563,7 +1613,9 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
}
(*sp->fill)(buf, thisrun, pa, lastx);
UNCACHE_STATE(tif, sp);
return (sp->line ? 1 : -1); /* don't error on badly-terminated strips */
return (sp->line != start
? 1
: -1); /* don't error on badly-terminated strips */
}
UNCACHE_STATE(tif, sp);
return (1);

View file

@ -146,7 +146,7 @@ TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc,
set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : TIFFHashSetEqualPointer;
set->fnFreeEltFunc = fnFreeEltFunc;
set->nSize = 0;
set->tabList = (TIFFList **)(calloc(sizeof(TIFFList *), 53));
set->tabList = (TIFFList **)(calloc(53, sizeof(TIFFList *)));
if (set->tabList == NULL)
{
free(set);
@ -367,7 +367,7 @@ static bool TIFFHashSetRehash(TIFFHashSet *set)
{
int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
TIFFList **newTabList =
(TIFFList **)(calloc(sizeof(TIFFList *), nNewAllocatedSize));
(TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *)));
if (newTabList == NULL)
return false;
#ifdef HASH_DEBUG

View file

@ -73,43 +73,6 @@ int TIFFReInitJPEG_12(TIFF *tif, const JPEGOtherSettings *otherSettings,
int scheme, int is_encode);
int TIFFJPEGIsFullStripRequired_12(TIFF *tif);
/* We undefine FAR to avoid conflict with JPEG definition */
#ifdef FAR
#undef FAR
#endif
/*
Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
not defined. Unfortunately, the MinGW and Borland compilers include
a typedef for INT32, which causes a conflict. MSVC does not include
a conflicting typedef given the headers which are included.
*/
#if defined(__BORLANDC__) || defined(__MINGW32__)
#define XMD_H 1
#endif
/*
The windows RPCNDR.H file defines boolean, but defines it with the
unsigned char size. You should compile JPEG library using appropriate
definitions in jconfig.h header, but many users compile library in wrong
way. That causes errors of the following type:
"JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
caller expects 464"
For such users we will fix the problem here. See install.doc file from
the JPEG library distribution for details.
*/
/* Define "boolean" as unsigned char, not int, per Windows custom. */
#if defined(__WIN32__) && !defined(__MINGW32__)
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#endif
#include "jerror.h"
#include "jpeglib.h"
@ -125,18 +88,18 @@ typedef unsigned char boolean;
* 16bit value?
*/
/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which
/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 3.0 which
* adds a dual-mode 8/12 bit API in the same library.
*/
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
#define JPEG_DUAL_MODE_8_12
/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo
* >= 2.2 Cf
* >= 3.0 Cf
* https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b
*/
#undef BITS_IN_JSAMPLE
/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */
/* libjpeg-turbo >= 3.0 adds J12xxxx datatypes for the 12-bit mode. */
#if defined(FROM_TIF_JPEG_12)
#define BITS_IN_JSAMPLE 12
#define TIFF_JSAMPLE J12SAMPLE
@ -182,9 +145,20 @@ typedef unsigned char boolean;
#define LONGJMP(jbuf, code) longjmp(jbuf, code)
#define JMP_BUF jmp_buf
#ifndef TIFF_jpeg_destination_mgr_defined
#define TIFF_jpeg_destination_mgr_defined
typedef struct jpeg_destination_mgr jpeg_destination_mgr;
#endif
#ifndef TIFF_jpeg_source_mgr_defined
#define TIFF_jpeg_source_mgr_defined
typedef struct jpeg_source_mgr jpeg_source_mgr;
#endif
#ifndef TIFF_jpeg_error_mgr_defined
#define TIFF_jpeg_error_mgr_defined
typedef struct jpeg_error_mgr jpeg_error_mgr;
#endif
/*
* State block for each open TIFF file using
@ -1241,6 +1215,12 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
* For PC 2, scale down the expected strip/tile size
* to match a downsampled component
*/
if (sp->h_sampling == 0 || sp->v_sampling == 0)
{
TIFFErrorExtR(tif, module,
"JPEG horizontal or vertical sampling is zero");
return (0);
}
segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
}
@ -1471,7 +1451,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
{
memset(buf, 0, (size_t)cc);
return 0;
}
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@ -1492,7 +1475,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
JSAMPROW bufptr = (JSAMPROW)buf;
if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
{
memset(buf, 0, (size_t)cc);
return (0);
}
++tif->tif_row;
buf += sp->bytesperline;
@ -1526,7 +1512,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
{
memset(buf, 0, (size_t)cc);
return 0;
}
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@ -1562,7 +1551,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
* for 12bit data, which we need to repack.
*/
if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
{
memset(buf, 0, (size_t)cc);
return (0);
}
if (sp->cinfo.d.data_precision == 12)
{
@ -2190,6 +2182,12 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s)
/* for PC 2, scale down the strip/tile size
* to match a downsampled component
*/
if (sp->h_sampling == 0 || sp->v_sampling == 0)
{
TIFFErrorExtR(tif, module,
"JPEG horizontal or vertical sampling is zero");
return (0);
}
segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
}

View file

@ -951,7 +951,8 @@ static
int
uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
{
register int vi, ui;
unsigned int vi;
int ui;
/* check for NaN */
if (u != u || v != v)
@ -980,8 +981,9 @@ static
int
uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
{
int upper, lower;
register int ui, vi;
unsigned int upper, lower;
int ui;
unsigned int vi;
if (c < 0 || c >= UV_NDIVS)
return (-1);

View file

@ -161,8 +161,8 @@ typedef struct
} LZWCodecState;
#define LZWState(tif) ((LZWBaseState *)(tif)->tif_data)
#define DecoderState(tif) ((LZWCodecState *)LZWState(tif))
#define EncoderState(tif) ((LZWCodecState *)LZWState(tif))
#define LZWDecoderState(tif) ((LZWCodecState *)LZWState(tif))
#define LZWEncoderState(tif) ((LZWCodecState *)LZWState(tif))
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s);
#ifdef LZW_COMPAT
@ -183,7 +183,7 @@ static int LZWFixupTags(TIFF *tif)
static int LZWSetupDecode(TIFF *tif)
{
static const char module[] = "LZWSetupDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
int code;
if (sp == NULL)
@ -199,7 +199,7 @@ static int LZWSetupDecode(TIFF *tif)
return (0);
}
sp = DecoderState(tif);
sp = LZWDecoderState(tif);
sp->dec_codetab = NULL;
sp->dec_decode = NULL;
@ -245,7 +245,7 @@ static int LZWSetupDecode(TIFF *tif)
static int LZWPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZWPreDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -329,10 +329,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
#ifdef WORDS_BIGENDIAN
#define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata))
#elif SIZEOF_WORDTYPE == 8
#if defined(__GNUC__) && defined(__x86_64__)
#define GetNextData(nextdata, bp) \
nextdata = __builtin_bswap64(*(uint64_t *)(bp))
#elif defined(_M_X64)
#if defined(_M_X64)
#define GetNextData(nextdata, bp) nextdata = _byteswap_uint64(*(uint64_t *)(bp))
#elif defined(__GNUC__)
#define GetNextData(nextdata, bp) \
@ -346,10 +343,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
(((uint64_t)bp[6]) << 8) | (((uint64_t)bp[7]))
#endif
#elif SIZEOF_WORDTYPE == 4
#if defined(__GNUC__) && defined(__i386__)
#define GetNextData(nextdata, bp) \
nextdata = __builtin_bswap32(*(uint32_t *)(bp))
#elif defined(_M_X86)
#if defined(_M_X86)
#define GetNextData(nextdata, bp) \
nextdata = _byteswap_ulong(*(unsigned long *)(bp))
#elif defined(__GNUC__)
@ -409,7 +403,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *bp;
@ -423,6 +417,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"LZWDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
@ -737,6 +732,7 @@ after_loop:
if (occ > 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 " (short %" PRIu64
" bytes)",
@ -746,12 +742,14 @@ after_loop:
return (1);
no_eoi:
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
tif->tif_curstrip);
return 0;
error_code:
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, tif->tif_name, "Using code not yet in table");
return 0;
@ -800,7 +798,7 @@ error_code:
static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecodeCompat";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *tp;
@ -1026,7 +1024,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
static int LZWSetupEncode(TIFF *tif)
{
static const char module[] = "LZWSetupEncode";
LZWCodecState *sp = EncoderState(tif);
LZWCodecState *sp = LZWEncoderState(tif);
assert(sp != NULL);
sp->enc_hashtab = (hash_t *)_TIFFmallocExt(tif, HSIZE * sizeof(hash_t));
@ -1043,7 +1041,7 @@ static int LZWSetupEncode(TIFF *tif)
*/
static int LZWPreEncode(TIFF *tif, uint16_t s)
{
LZWCodecState *sp = EncoderState(tif);
LZWCodecState *sp = LZWEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -1114,7 +1112,7 @@ static int LZWPreEncode(TIFF *tif, uint16_t s)
*/
static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
register LZWCodecState *sp = EncoderState(tif);
register LZWCodecState *sp = LZWEncoderState(tif);
register long fcode;
register hash_t *hp;
register int h, c;
@ -1299,7 +1297,7 @@ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
*/
static int LZWPostEncode(TIFF *tif)
{
register LZWCodecState *sp = EncoderState(tif);
register LZWCodecState *sp = LZWEncoderState(tif);
uint8_t *op = tif->tif_rawcp;
long nextbits = sp->lzw_nextbits;
WordType nextdata = sp->lzw_nextdata;
@ -1381,11 +1379,11 @@ static void LZWCleanup(TIFF *tif)
assert(tif->tif_data != 0);
if (DecoderState(tif)->dec_codetab)
_TIFFfreeExt(tif, DecoderState(tif)->dec_codetab);
if (LZWDecoderState(tif)->dec_codetab)
_TIFFfreeExt(tif, LZWDecoderState(tif)->dec_codetab);
if (EncoderState(tif)->enc_hashtab)
_TIFFfreeExt(tif, EncoderState(tif)->enc_hashtab);
if (LZWEncoderState(tif)->enc_hashtab)
_TIFFfreeExt(tif, LZWEncoderState(tif)->enc_hashtab);
_TIFFfreeExt(tif, tif->tif_data);
tif->tif_data = NULL;
@ -1404,9 +1402,9 @@ int TIFFInitLZW(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZWCodecState));
if (tif->tif_data == NULL)
goto bad;
DecoderState(tif)->dec_codetab = NULL;
DecoderState(tif)->dec_decode = NULL;
EncoderState(tif)->enc_hashtab = NULL;
LZWDecoderState(tif)->dec_codetab = NULL;
LZWDecoderState(tif)->dec_decode = NULL;
LZWEncoderState(tif)->enc_hashtab = NULL;
LZWState(tif)->rw_mode = tif->tif_mode;
/*

View file

@ -25,7 +25,13 @@
/*
* TIFF Library.
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tiffiop.h"
#include <assert.h>
#include <limits.h>
/*
@ -81,8 +87,9 @@ TIFFOpenOptions *TIFFOpenOptionsAlloc()
void TIFFOpenOptionsFree(TIFFOpenOptions *opts) { _TIFFfree(opts); }
/** Define a limit in bytes for a single memory allocation done by libtiff.
* If max_single_mem_alloc is set to 0, no other limit that the underlying
* _TIFFmalloc() will be applied, which is the default.
* If max_single_mem_alloc is set to 0, which is the default, no other limit
* that the underlying _TIFFmalloc() or
* TIFFOpenOptionsSetMaxCumulatedMemAlloc() will be applied.
*/
void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc)
@ -90,6 +97,18 @@ void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
opts->max_single_mem_alloc = max_single_mem_alloc;
}
/** Define a limit in bytes for the cumulated memory allocations done by libtiff
* on a given TIFF handle.
* If max_cumulated_mem_alloc is set to 0, which is the default, no other limit
* that the underlying _TIFFmalloc() or
* TIFFOpenOptionsSetMaxSingleMemAlloc() will be applied.
*/
void TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_cumulated_mem_alloc)
{
opts->max_cumulated_mem_alloc = max_cumulated_mem_alloc;
}
void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data)
@ -117,6 +136,30 @@ static void _TIFFEmitErrorAboveMaxSingleMemAlloc(TIFF *tif,
(uint64_t)s, (uint64_t)tif->tif_max_single_mem_alloc);
}
static void _TIFFEmitErrorAboveMaxCumulatedMemAlloc(TIFF *tif,
const char *pszFunction,
tmsize_t s)
{
TIFFErrorExtR(tif, pszFunction,
"Cumulated memory allocation of %" PRIu64 " + %" PRIu64
" bytes is beyond the %" PRIu64
" cumulated byte limit defined in open options",
(uint64_t)tif->tif_cur_cumulated_mem_alloc, (uint64_t)s,
(uint64_t)tif->tif_max_cumulated_mem_alloc);
}
/* When allocating memory, we write at the beginning of the buffer it size.
* This allows us to keep track of the total memory allocated when we
* malloc/calloc/realloc and free. In theory we need just SIZEOF_SIZE_T bytes
* for that, but on x86_64, allocations of more than 16 bytes are aligned on
* 16 bytes. Hence using 2 * SIZEOF_SIZE_T.
* It is critical that _TIFFmallocExt/_TIFFcallocExt/_TIFFreallocExt are
* paired with _TIFFfreeExt.
* CMakeLists.txt defines TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS, which in
* turn disables the definition of the non Ext version in tiffio.h
*/
#define LEADING_AREA_TO_STORE_ALLOC_SIZE (2 * SIZEOF_SIZE_T)
/** malloc() version that takes into account memory-specific open options */
void *_TIFFmallocExt(TIFF *tif, tmsize_t s)
{
@ -126,16 +169,32 @@ void *_TIFFmallocExt(TIFF *tif, tmsize_t s)
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFmallocExt", s);
return NULL;
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
if (s > tif->tif_max_cumulated_mem_alloc -
tif->tif_cur_cumulated_mem_alloc ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFmallocExt", s);
return NULL;
}
void *ptr = _TIFFmalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
if (!ptr)
return NULL;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(ptr, &s, sizeof(s));
return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFmalloc(s);
}
/** calloc() version that takes into account memory-specific open options */
void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz)
{
if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
return NULL;
if (tif != NULL && tif->tif_max_single_mem_alloc > 0)
{
if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
return NULL;
if (nmemb * siz > tif->tif_max_single_mem_alloc)
{
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFcallocExt",
@ -143,6 +202,23 @@ void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz)
return NULL;
}
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
const tmsize_t s = nmemb * siz;
if (s > tif->tif_max_cumulated_mem_alloc -
tif->tif_cur_cumulated_mem_alloc ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFcallocExt", s);
return NULL;
}
void *ptr = _TIFFcalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s, 1);
if (!ptr)
return NULL;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(ptr, &s, sizeof(s));
return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFcalloc(nmemb, siz);
}
@ -155,13 +231,49 @@ void *_TIFFreallocExt(TIFF *tif, void *p, tmsize_t s)
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFreallocExt", s);
return NULL;
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
void *oldPtr = p;
tmsize_t oldSize = 0;
if (p)
{
oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
memcpy(&oldSize, oldPtr, sizeof(oldSize));
assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
}
if (s > oldSize &&
(s > tif->tif_max_cumulated_mem_alloc -
(tif->tif_cur_cumulated_mem_alloc - oldSize) ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE))
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFreallocExt",
s - oldSize);
return NULL;
}
void *newPtr =
_TIFFrealloc(oldPtr, LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
if (newPtr == NULL)
return NULL;
tif->tif_cur_cumulated_mem_alloc -= oldSize;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(newPtr, &s, sizeof(s));
return (char *)newPtr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFrealloc(p, s);
}
/** free() version that takes into account memory-specific open options */
void _TIFFfreeExt(TIFF *tif, void *p)
{
(void)tif;
if (p != NULL && tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
void *oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
tmsize_t oldSize;
memcpy(&oldSize, oldPtr, sizeof(oldSize));
assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
tif->tif_cur_cumulated_mem_alloc -= oldSize;
p = oldPtr;
}
_TIFFfree(p);
}
@ -231,6 +343,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
(uint64_t)opts->max_single_mem_alloc);
goto bad2;
}
if (opts && opts->max_cumulated_mem_alloc > 0 &&
size_to_alloc > opts->max_cumulated_mem_alloc)
{
_TIFFErrorEarly(opts, clientdata, module,
"%s: Memory allocation of %" PRIu64
" bytes is beyond the %" PRIu64
" cumulated byte limit defined in open options",
name, (uint64_t)size_to_alloc,
(uint64_t)opts->max_cumulated_mem_alloc);
goto bad2;
}
tif = (TIFF *)_TIFFmallocExt(NULL, size_to_alloc);
if (tif == NULL)
{
@ -243,6 +366,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
strcpy(tif->tif_name, name);
tif->tif_mode = m & ~(O_CREAT | O_TRUNC);
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */
tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
tif->tif_curoff = 0;
tif->tif_curstrip = (uint32_t)-1; /* invalid strip */
tif->tif_row = (uint32_t)-1; /* read/write pre-increment */
@ -261,6 +385,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_warnhandler = opts->warnhandler;
tif->tif_warnhandler_user_data = opts->warnhandler_user_data;
tif->tif_max_single_mem_alloc = opts->max_single_mem_alloc;
tif->tif_max_cumulated_mem_alloc = opts->max_cumulated_mem_alloc;
}
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc)
@ -423,9 +548,9 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
TIFFErrorExtR(tif, name, "Cannot read TIFF header");
goto bad;
}
/*
* Setup header and write.
*/
/*
* Setup header and write.
*/
#ifdef WORDS_BIGENDIAN
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
@ -433,13 +558,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
#endif
TIFFHeaderUnion tif_header_swapped;
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
tif->tif_header.classic.tiff_diroff = 0;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&tif->tif_header.common.tiff_version);
tif->tif_header_size = sizeof(TIFFHeaderClassic);
/* Swapped copy for writing */
_TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
sizeof(TIFFHeaderUnion));
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&tif_header_swapped.common.tiff_version);
}
else
{
@ -447,12 +576,15 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_header.big.tiff_offsetsize = 8;
tif->tif_header.big.tiff_unused = 0;
tif->tif_header.big.tiff_diroff = 0;
tif->tif_header_size = sizeof(TIFFHeaderBig);
/* Swapped copy for writing */
_TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
sizeof(TIFFHeaderUnion));
if (tif->tif_flags & TIFF_SWAB)
{
TIFFSwabShort(&tif->tif_header.common.tiff_version);
TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
TIFFSwabShort(&tif_header_swapped.common.tiff_version);
TIFFSwabShort(&tif_header_swapped.big.tiff_offsetsize);
}
tif->tif_header_size = sizeof(TIFFHeaderBig);
}
/*
* The doc for "fopen" for some STD_C_LIBs says that if you
@ -462,26 +594,12 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
* on Solaris.
*/
TIFFSeekFile(tif, 0, SEEK_SET);
if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size)))
if (!WriteOK(tif, &tif_header_swapped,
(tmsize_t)(tif->tif_header_size)))
{
TIFFErrorExtR(tif, name, "Error writing TIFF header");
goto bad;
}
/*
* Setup the byte order handling.
*/
if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN)
{
#ifndef WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB;
#endif
}
else
{
#ifdef WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB;
#endif
}
/*
* Setup default directory.
*/
@ -490,10 +608,14 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_diroff = 0;
tif->tif_lastdiroff = 0;
tif->tif_setdirectory_force_absolute = FALSE;
/* tif_curdircount = 0 means 'empty file opened for writing, but no IFD
* written yet' */
tif->tif_curdircount = 0;
return (tif);
}
/*
* Setup the byte order handling.
* Setup the byte order handling according to the opened file for reading.
*/
if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
@ -619,9 +741,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
* example, it may be broken) and want to proceed to other
* directories. I this case we use the TIFF_HEADERONLY flag to open
* file and return immediately after reading TIFF header.
* However, the pointer to TIFFSetField() and TIFFGetField()
* (i.e. tif->tif_tagmethods.vsetfield and
* tif->tif_tagmethods.vgetfield) need to be initialized, which is
* done in TIFFDefaultDirectory().
*/
if (tif->tif_flags & TIFF_HEADERONLY)
{
if (!TIFFDefaultDirectory(tif))
goto bad;
return (tif);
}
/*
* Setup initial directory.
@ -764,10 +894,7 @@ int TIFFIsBigEndian(TIFF *tif)
/*
* Return nonzero if given file is BigTIFF style.
*/
int TIFFIsBigTIFF(TIFF *tif)
{
return (tif->tif_header.common.tiff_version == TIFF_VERSION_BIG);
}
int TIFFIsBigTIFF(TIFF *tif) { return ((tif->tif_flags & TIFF_BIGTIFF) != 0); }
/*
* Return pointer to file read method.

View file

@ -300,6 +300,7 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
tif->tif_rawcc = cc;
if (occ > 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
tif->tif_row);
return (0);

View file

@ -670,8 +670,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
return 1;
}
#define DecoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define EncoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define PixarLogDecoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define PixarLogEncoderState(tif) ((PixarLogState *)(tif)->tif_data)
static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -740,7 +740,7 @@ static int PixarLogSetupDecode(TIFF *tif)
{
static const char module[] = "PixarLogSetupDecode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t tbuf_size;
uint32_t strip_height;
@ -813,7 +813,7 @@ static int PixarLogSetupDecode(TIFF *tif)
static int PixarLogPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreDecode";
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -835,7 +835,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "PixarLogDecode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t i;
tmsize_t nsamples;
int llen;
@ -859,6 +859,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module,
"%" PRIu16 " bit input not supported in PixarLog",
td->td_bitspersample);
memset(op, 0, (size_t)occ);
return 0;
}
@ -879,12 +880,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
{
TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
memset(op, 0, (size_t)occ);
return (0);
}
/* Check that we will not fill more than what was allocated */
if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
{
TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
memset(op, 0, (size_t)occ);
return (0);
}
do
@ -899,12 +902,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(
tif, module, "Decoding error at scanline %" PRIu32 ", %s",
tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
memset(op, 0, (size_t)occ);
return (0);
}
if (state != Z_OK)
{
TIFFErrorExtR(tif, module, "ZLib error: %s",
sp->stream.msg ? sp->stream.msg : "(null)");
memset(op, 0, (size_t)occ);
return (0);
}
} while (sp->stream.avail_out > 0);
@ -916,6 +921,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
"Not enough data at scanline %" PRIu32
" (short %u bytes)",
tif->tif_row, sp->stream.avail_out);
memset(op, 0, (size_t)occ);
return (0);
}
@ -977,6 +983,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
default:
TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
td->td_bitspersample);
memset(op, 0, (size_t)occ);
return (0);
}
}
@ -988,7 +995,7 @@ static int PixarLogSetupEncode(TIFF *tif)
{
static const char module[] = "PixarLogSetupEncode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t tbuf_size;
assert(sp != NULL);
@ -1038,7 +1045,7 @@ static int PixarLogSetupEncode(TIFF *tif)
static int PixarLogPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreEncode";
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -1294,7 +1301,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "PixarLogEncode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t i;
tmsize_t n;
int llen;
@ -1401,7 +1408,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int PixarLogPostEncode(TIFF *tif)
{
static const char module[] = "PixarLogPostEncode";
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
int state;
sp->stream.avail_in = 0;

View file

@ -105,8 +105,8 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
TIFFErrorExtR(tif, module, "Invalid buffer size");
return 0;
}
new_rawdata =
(uint8_t *)_TIFFrealloc(tif->tif_rawdata, tif->tif_rawdatasize);
new_rawdata = (uint8_t *)_TIFFreallocExt(tif, tif->tif_rawdata,
tif->tif_rawdatasize);
if (new_rawdata == 0)
{
TIFFErrorExtR(tif, module,
@ -464,6 +464,10 @@ int TIFFReadScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
if (e)
(*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize);
}
else
{
memset(buf, 0, (size_t)tif->tif_scanlinesize);
}
return (e > 0 ? 1 : -1);
}
@ -495,6 +499,11 @@ static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF *tif, uint32_t strip,
rowsperstrip = td->td_rowsperstrip;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "rowsperstrip is zero");
return ((tmsize_t)(-1));
}
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
stripinplane = (strip % stripsperplane);
@ -544,7 +553,10 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf,
if ((size != (tmsize_t)(-1)) && (size < stripsize))
stripsize = size;
if (!TIFFFillStrip(tif, strip))
{
memset(buf, 0, (size_t)stripsize);
return ((tmsize_t)(-1));
}
if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0)
return ((tmsize_t)(-1));
(*tif->tif_postdecode)(tif, buf, stripsize);
@ -962,9 +974,13 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size)
size = tilesize;
else if (size > tilesize)
size = tilesize;
if (TIFFFillTile(tif, tile) &&
(*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
(uint16_t)(tile / td->td_stripsperimage)))
if (!TIFFFillTile(tif, tile))
{
memset(buf, 0, (size_t)size);
return ((tmsize_t)(-1));
}
else if ((*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
(uint16_t)(tile / td->td_stripsperimage)))
{
(*tif->tif_postdecode)(tif, (uint8_t *)buf, size);
return (size);
@ -1449,6 +1465,11 @@ static int TIFFStartTile(TIFF *tif, uint32_t tile)
tif->tif_flags |= TIFF_CODERSETUP;
}
tif->tif_curtile = tile;
if (td->td_tilewidth == 0)
{
TIFFErrorExtR(tif, module, "Zero tilewidth");
return 0;
}
howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
if (howmany32 == 0)
{
@ -1545,9 +1566,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
if (TIFFIsTiled(tif))
{
if (!TIFFStartTile(tif, strile) ||
!(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / td->td_stripsperimage)))
if (!TIFFStartTile(tif, strile))
{
ret = 0;
memset(outbuf, 0, (size_t)outsize);
}
else if (!(*tif->tif_decodetile)(
tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / td->td_stripsperimage)))
{
ret = 0;
}
@ -1558,14 +1584,27 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
uint32_t 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_t *)outbuf, outsize,
(uint16_t)(strile / stripsperplane)))
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "rowsperstrip is zero");
ret = 0;
}
else
{
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
if (!TIFFStartStrip(tif, strile))
{
ret = 0;
memset(outbuf, 0, (size_t)outsize);
}
else if (!(*tif->tif_decodestrip)(
tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / stripsperplane)))
{
ret = 0;
}
}
}
if (ret)
{

View file

@ -38,6 +38,11 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample)
TIFFDirectory *td = &tif->tif_dir;
uint32_t strip;
if (td->td_rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "Cannot compute strip: RowsPerStrip is zero");
return 0;
}
strip = row / td->td_rowsperstrip;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{
@ -61,6 +66,11 @@ uint32_t TIFFNumberOfStrips(TIFF *tif)
TIFFDirectory *td = &tif->tif_dir;
uint32_t nstrips;
if (td->td_rowsperstrip == 0)
{
TIFFWarningExtR(tif, "TIFFNumberOfStrips", "RowsPerStrip is zero");
return 0;
}
nstrips = (td->td_rowsperstrip == (uint32_t)-1
? 1
: TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip));
@ -107,7 +117,8 @@ uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 &&
ycbcrsubsampling[0] != 4) ||
(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 &&
ycbcrsubsampling[1] != 4))
ycbcrsubsampling[1] != 4) ||
(ycbcrsubsampling[0] == 0 || ycbcrsubsampling[1] == 0))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)",
ycbcrsubsampling[0], ycbcrsubsampling[1]);
@ -267,7 +278,8 @@ uint64_t TIFFScanlineSize64(TIFF *tif)
if (((ycbcrsubsampling[0] != 1) && (ycbcrsubsampling[0] != 2) &&
(ycbcrsubsampling[0] != 4)) ||
((ycbcrsubsampling[1] != 1) && (ycbcrsubsampling[1] != 2) &&
(ycbcrsubsampling[1] != 4)))
(ycbcrsubsampling[1] != 4)) ||
((ycbcrsubsampling[0] == 0) || (ycbcrsubsampling[1] == 0)))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling");
return 0;
@ -287,7 +299,25 @@ uint64_t TIFFScanlineSize64(TIFF *tif)
else
{
uint64_t scanline_samples;
scanline_samples = _TIFFMultiply64(tif, td->td_imagewidth,
uint32_t scanline_width = td->td_imagewidth;
#if 0
// Tries to fix https://gitlab.com/libtiff/libtiff/-/merge_requests/564
// but causes regression when decoding legit files with tiffcp -c none
// Cf https://gitlab.com/libtiff/libtiff/-/merge_requests/644
if (td->td_photometric == PHOTOMETRIC_YCBCR)
{
uint16_t subsampling_hor;
uint16_t ignored;
TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
&subsampling_hor, &ignored);
if (subsampling_hor > 1) // roundup width for YCbCr
scanline_width =
TIFFroundup_32(scanline_width, subsampling_hor);
}
#endif
scanline_samples = _TIFFMultiply64(tif, scanline_width,
td->td_samplesperpixel, module);
scanline_size =
TIFFhowmany_64(_TIFFMultiply64(tif, scanline_samples,

View file

@ -82,13 +82,14 @@ static int ThunderSetupDecode(TIFF *tif)
return (1);
}
static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
{
static const char module[] = "ThunderDecode";
register unsigned char *bp;
register tmsize_t cc;
unsigned int lastpixel;
tmsize_t npixels;
uint8_t *op = op0;
bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc;
@ -107,6 +108,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
* Replicate the last pixel n times,
* where n is the lower-order 6 bits.
*/
if (n == 0)
break;
if (npixels & 1)
{
op[0] |= lastpixel;
@ -117,11 +120,10 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
else
lastpixel |= lastpixel << 4;
npixels += n;
if (npixels < maxpixels)
{
for (; n > 0; n -= 2)
*op++ = (uint8_t)lastpixel;
}
if (npixels > maxpixels)
break;
for (; n > 0; n -= 2)
*op++ = (uint8_t)lastpixel;
if (n == -1)
*--op &= 0xf0;
lastpixel &= 0xf;
@ -154,6 +156,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
tif->tif_rawcc = cc;
if (npixels != maxpixels)
{
uint8_t *op_end = op0 + (maxpixels + 1) / 2;
memset(op, 0, (size_t)(op_end - op));
TIFFErrorExtR(tif, module,
"%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")",
npixels < maxpixels ? "Not enough" : "Too much",

View file

@ -27,6 +27,10 @@
* Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tiffiop.h"
#include <stdlib.h>

View file

@ -67,6 +67,8 @@ typedef struct
{
TIFFPredictorState predict;
z_stream stream;
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
int zipquality; /* compression level */
int state; /* state flags */
int subcodec; /* DEFLATE_SUBCODEC_ZLIB or DEFLATE_SUBCODEC_LIBDEFLATE */
@ -83,9 +85,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} ZIPState;
#define ZState(tif) ((ZIPState *)(tif)->tif_data)
#define DecoderState(tif) ZState(tif)
#define EncoderState(tif) ZState(tif)
#define GetZIPState(tif) ((ZIPState *)(tif)->tif_data)
#define ZIPDecoderState(tif) GetZIPState(tif)
#define ZIPEncoderState(tif) GetZIPState(tif)
static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -99,7 +101,7 @@ static int ZIPFixupTags(TIFF *tif)
static int ZIPSetupDecode(TIFF *tif)
{
static const char module[] = "ZIPSetupDecode";
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
assert(sp != NULL);
@ -131,7 +133,7 @@ static int ZIPSetupDecode(TIFF *tif)
*/
static int ZIPPreDecode(TIFF *tif, uint16_t s)
{
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -150,18 +152,33 @@ static int ZIPPreDecode(TIFF *tif, uint16_t s)
sp->stream.avail_in = (uint64_t)tif->tif_rawcc < 0xFFFFFFFFU
? (uInt)tif->tif_rawcc
: 0xFFFFFFFFU;
return (inflateReset(&sp->stream) == Z_OK);
if (inflateReset(&sp->stream) == Z_OK)
{
sp->read_error = 0;
return 1;
}
return 0;
}
static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "ZIPDecode";
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
(void)s;
assert(sp != NULL);
assert(sp->state == ZSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
#if LIBDEFLATE_SUPPORT
if (sp->libdeflate_state == 1)
return 0;
@ -227,8 +244,10 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (res != LIBDEFLATE_SUCCESS &&
res != LIBDEFLATE_INSUFFICIENT_SPACE)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
(unsigned long)tif->tif_row);
sp->read_error = 1;
return 0;
}
@ -263,13 +282,17 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
break;
if (state == Z_DATA_ERROR)
{
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s",
(unsigned long)tif->tif_row, SAFE_MSG(sp));
sp->read_error = 1;
return (0);
}
if (state != Z_OK)
{
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
sp->read_error = 1;
return (0);
}
} while (occ > 0);
@ -279,6 +302,8 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
"Not enough data at scanline %lu (short %" PRIu64
" bytes)",
(unsigned long)tif->tif_row, (uint64_t)occ);
memset(sp->stream.next_out, 0, sp->stream.avail_out);
sp->read_error = 1;
return (0);
}
@ -290,7 +315,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int ZIPSetupEncode(TIFF *tif)
{
static const char module[] = "ZIPSetupEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
int cappedQuality;
assert(sp != NULL);
@ -321,7 +346,7 @@ static int ZIPSetupEncode(TIFF *tif)
*/
static int ZIPPreEncode(TIFF *tif, uint16_t s)
{
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -348,7 +373,7 @@ static int ZIPPreEncode(TIFF *tif, uint16_t s)
static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "ZIPEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
assert(sp != NULL);
assert(sp->state == ZSTATE_INIT_ENCODE);
@ -487,7 +512,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int ZIPPostEncode(TIFF *tif)
{
static const char module[] = "ZIPPostEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
int state;
#if LIBDEFLATE_SUPPORT
@ -526,7 +551,7 @@ static int ZIPPostEncode(TIFF *tif)
static void ZIPCleanup(TIFF *tif)
{
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
assert(sp != 0);
@ -562,7 +587,7 @@ static void ZIPCleanup(TIFF *tif)
static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "ZIPVSetField";
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
switch (tag)
{
@ -628,7 +653,7 @@ static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int ZIPVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
switch (tag)
{
@ -680,7 +705,7 @@ int TIFFInitZIP(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, sizeof(ZIPState), 1);
if (tif->tif_data == NULL)
goto bad;
sp = ZState(tif);
sp = GetZIPState(tif);
sp->stream.zalloc = NULL;
sp->stream.zfree = NULL;
sp->stream.opaque = NULL;

View file

@ -77,10 +77,6 @@ typedef tstrile_t ttile_t; /* tile number */
typedef tmsize_t tsize_t; /* i/o size in bytes */
typedef void *tdata_t; /* image data ref */
#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
#define __WIN32__
#endif
/*
* On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c
* or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c).
@ -88,7 +84,7 @@ typedef void *tdata_t; /* image data ref */
* By default tif_unix.c is assumed.
*/
#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows)
#if defined(_WIN32)
#if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && \
!defined(USE_WIN32_FILEIO)
#define AVOID_WIN32_FILEIO
@ -98,11 +94,11 @@ typedef void *tdata_t; /* image data ref */
#if defined(USE_WIN32_FILEIO)
#define VC_EXTRALEAN
#include <windows.h>
#ifdef __WIN32__
#ifdef _WIN32
DECLARE_HANDLE(thandle_t); /* Win32 file handle */
#else
typedef HFILE thandle_t; /* client data handle */
#endif /* __WIN32__ */
#endif /* _WIN32 */
#else
typedef void *thandle_t; /* client data handle */
#endif /* USE_WIN32_FILEIO */
@ -311,14 +307,15 @@ extern "C"
/*
* Auxiliary functions.
*/
#ifndef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
extern void *_TIFFmalloc(tmsize_t s);
extern void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz);
extern void *_TIFFrealloc(void *p, tmsize_t s);
extern void _TIFFfree(void *p);
#endif
extern void _TIFFmemset(void *p, int v, tmsize_t c);
extern void _TIFFmemcpy(void *d, const void *s, tmsize_t c);
extern int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c);
extern void _TIFFfree(void *p);
/*
** Stuff, related to tag handling and creating custom tags.
@ -508,6 +505,9 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc);
extern void
TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_cumulated_mem_alloc);
extern void
TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data);
@ -518,11 +518,11 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
extern TIFF *TIFFOpen(const char *, const char *);
extern TIFF *TIFFOpenExt(const char *, const char *, TIFFOpenOptions *opts);
#ifdef __WIN32__
#ifdef _WIN32
extern TIFF *TIFFOpenW(const wchar_t *, const char *);
extern TIFF *TIFFOpenWExt(const wchar_t *, const char *,
TIFFOpenOptions *opts);
#endif /* __WIN32__ */
#endif /* _WIN32 */
extern TIFF *TIFFFdOpen(int, const char *, const char *);
extern TIFF *TIFFFdOpenExt(int, const char *, const char *,
TIFFOpenOptions *opts);

View file

@ -102,6 +102,13 @@ struct TIFFOffsetAndDirNumber
};
typedef struct TIFFOffsetAndDirNumber TIFFOffsetAndDirNumber;
typedef union
{
TIFFHeaderCommon common;
TIFFHeaderClassic classic;
TIFFHeaderBig big;
} TIFFHeaderUnion;
struct tiff
{
char *tif_name; /* name of open file */
@ -153,20 +160,35 @@ struct tiff
TIFFDirectory tif_dir; /* internal rep of current directory */
TIFFDirectory
tif_customdir; /* custom IFDs are separated from the main ones */
union
{
TIFFHeaderCommon common;
TIFFHeaderClassic classic;
TIFFHeaderBig big;
} tif_header;
uint16_t tif_header_size; /* file's header block and its length */
uint32_t tif_row; /* current scanline */
tdir_t tif_curdir; /* current directory (index) */
TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */
uint16_t tif_header_size; /* file's header block and its length */
uint32_t tif_row; /* current scanline */
/* There are IFDs in the file and an "active" IFD in memory,
* from which fields are "set" and "get".
* tif_curdir is set to:
* a) TIFF_NON_EXISTENT_DIR_NUMBER if there is no IFD in the file
* or the state is unknown,
* or the last read (i.e. TIFFFetchDirectory()) failed,
* or a custom directory was written.
* b) IFD index of last IFD written in the file. In this case the
* active IFD is a new (empty) one and tif_diroff is zero.
* If writing fails, tif_curdir is not changed.
* c) IFD index of IFD read from file into memory (=active IFD),
* even if IFD is corrupt and TIFFReadDirectory() returns 0.
* Then tif_diroff contains the offset of the IFD in the file.
* d) IFD index 0, whenever a custom directory or an unchained SubIFD
* was read. */
tdir_t tif_curdir; /* current directory (index) */
/* tif_curdircount: number of directories (main-IFDs) in file:
* - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'.
* - 0 means 'empty file opened for writing, but no IFD written yet' */
tdir_t tif_curdircount;
uint32_t tif_curstrip; /* current strip for read/write */
uint64_t tif_curoff; /* current offset for read/write */
uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in
place. Used only by TIFFAppendToStrip() */
uint64_t tif_dataoff; /* current offset for writing dir */
uint64_t tif_dataoff; /* current offset for writing dir (IFD) */
/* SubIFD support */
uint16_t tif_nsubifd; /* remaining subifds to write */
uint64_t tif_subifdoff; /* offset for patching SubIFD link */
@ -233,7 +255,9 @@ struct tiff
void *tif_errorhandler_user_data;
TIFFErrorHandlerExtR tif_warnhandler;
void *tif_warnhandler_user_data;
tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_cur_cumulated_mem_alloc; /* in bytes */
};
struct TIFFOpenOptions
@ -243,6 +267,7 @@ struct TIFFOpenOptions
TIFFErrorHandlerExtR warnhandler; /* may be NULL */
void *warnhandler_user_data; /* may be NULL */
tmsize_t max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
};
#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
@ -331,7 +356,7 @@ struct TIFFOpenOptions
#define ftell(stream, offset, whence) ftello(stream, offset, whence)
#endif
#endif
#if defined(__WIN32__) && !(defined(_MSC_VER) && _MSC_VER < 1400) && \
#if defined(_WIN32) && \
!(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800)
typedef unsigned int TIFFIOSize_t;
#define _TIFF_lseek_f(fildes, offset, whence) \
@ -437,9 +462,6 @@ extern "C"
extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t,
const char *);
extern double _TIFFUInt64ToDouble(uint64_t);
extern float _TIFFUInt64ToFloat(uint64_t);
extern float _TIFFClampDoubleToFloat(double);
extern uint32_t _TIFFClampDoubleToUInt32(double);

View file

@ -8,7 +8,7 @@
* Furthermore, configure_file variables of type "@VAR@" are
* modified by clang-format and won't be substituted by CMake.
*/
#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.6.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.7.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
/*
* This define can be used in code that requires
* compilation-related definitions specific to a
@ -16,13 +16,13 @@
* version checking should be done based on the
* string returned by TIFFGetVersion.
*/
#define TIFFLIB_VERSION 20230908
#define TIFFLIB_VERSION 20240911
/* The following defines have been added in 4.5.0 */
#define TIFFLIB_MAJOR_VERSION 4
#define TIFFLIB_MINOR_VERSION 6
#define TIFFLIB_MINOR_VERSION 7
#define TIFFLIB_MICRO_VERSION 0
#define TIFFLIB_VERSION_STR_MAJ_MIN_MIC "4.6.0"
#define TIFFLIB_VERSION_STR_MAJ_MIN_MIC "4.7.0"
/* Macro added in 4.5.0. Returns TRUE if the current libtiff version is
* greater or equal to major.minor.micro