Merge pull request #27679 from sturkmen72:libtiff-4.7.0

libtiff upgrade to version 4.7.0 #27679 
 
### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Suleyman TURKMEN 2025-08-19 13:29:17 +03:00 committed by GitHub
parent 920040d72e
commit d9c0ee234f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 3878 additions and 729 deletions

View File

@ -358,7 +358,7 @@ if(LIBLZMA_LIBRARIES)
endif()
set(LIBTIFF_MAJOR_VERSION "4")
set(LIBTIFF_MINOR_VERSION "6")
set(LIBTIFF_MINOR_VERSION "7")
set(LIBTIFF_MICRO_VERSION "0")
set(LIBTIFF_VERSION "${LIBTIFF_MAJOR_VERSION}.${LIBTIFF_MINOR_VERSION}.${LIBTIFF_MICRO_VERSION}")
file(READ "RELEASE-DATE" LIBTIFF_RELEASE_DATE content)

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
20230908
20240911

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

@ -89,7 +89,7 @@ void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
uint32_t *r, uint32_t *g, uint32_t *b)
{
int i;
size_t i;
float Yr, Yg, Yb;
float *matrix = &cielab->display.d_mat[0][0];
@ -109,16 +109,16 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
Yb = TIFFmin(Yb, cielab->display.d_YCB);
/* Turn luminosity to colour value. */
i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep);
i = TIFFmin((size_t)cielab->range, i);
*r = RINT(cielab->Yr2r[i]);
i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep);
i = TIFFmin((size_t)cielab->range, i);
*g = RINT(cielab->Yg2g[i]);
i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep);
i = TIFFmin((size_t)cielab->range, i);
*b = RINT(cielab->Yb2b[i]);
/* Clip output. */
@ -135,7 +135,7 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
float *refWhite)
{
int i;
size_t i;
double dfGamma;
cielab->range = CIELABTORGB_TABLE_RANGE;
@ -146,7 +146,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaR;
cielab->rstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yr2r[i] = cielab->display.d_Vrwr *
((float)pow((double)i / cielab->range, dfGamma));
@ -156,7 +156,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaG;
cielab->gstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yg2g[i] = cielab->display.d_Vrwg *
((float)pow((double)i / cielab->range, dfGamma));
@ -166,7 +166,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaB;
cielab->bstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yb2b[i] = cielab->display.d_Vrwb *
((float)pow((double)i / cielab->range, dfGamma));

View File

@ -40,6 +40,18 @@
/* Define to 1 if you have the `getopt' function. */
#cmakedefine HAVE_GETOPT 1
/* Define to 1 if you have the <GLUT/glut.h> header file. */
#cmakedefine HAVE_GLUT_GLUT_H 1
/* Define to 1 if you have the <GL/glut.h> header file. */
#cmakedefine HAVE_GL_GLUT_H 1
/* Define to 1 if you have the <GL/glu.h> header file. */
#cmakedefine HAVE_GL_GLU_H 1
/* Define to 1 if you have the <GL/gl.h> header file. */
#cmakedefine HAVE_GL_GL_H 1
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
@ -49,6 +61,12 @@
/* Define to 1 if you have the `mmap' function. */
#cmakedefine HAVE_MMAP 1
/* Define to 1 if you have the <OpenGL/glu.h> header file. */
#cmakedefine HAVE_OPENGL_GLU_H 1
/* Define to 1 if you have the <OpenGL/gl.h> header file. */
#cmakedefine HAVE_OPENGL_GL_H 1
/* Define to 1 if you have the `setmode' function. */
#cmakedefine HAVE_SETMODE 1

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)
{
if (retval)
{
/* 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 */
* 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,10 +335,9 @@ 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 */
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 */

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
*/
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

@ -760,6 +760,12 @@ static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
toskew = -(int32_t)(tw - w);
}
if (tw == 0 || th == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
return (0);
}
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@ -916,6 +922,12 @@ static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
break;
}
if (tw == 0 || th == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
return (0);
}
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@ -1092,6 +1104,11 @@ static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
@ -1216,6 +1233,12 @@ static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow)
@ -3213,6 +3236,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
if ((row % rowsperstrip) != 0)
{
TIFFErrorExtR(
@ -3224,6 +3254,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
if (TIFFRGBAImageOK(tif, emsg) &&
TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
{
if (row >= img.height)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"Invalid row passed to TIFFReadRGBAStrip().");
TIFFRGBAImageEnd(&img);
return (0);
}
img.row_offset = row;
img.col_offset = 0;
@ -3282,6 +3319,13 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
if (tile_xsize == 0 || tile_ysize == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"tile_xsize or tile_ysize is zero");
return (0);
}
if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
@ -3301,6 +3345,14 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
return (0);
}
if (col >= img.width || row >= img.height)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"Invalid row/col passed to TIFFReadRGBATile().");
TIFFRGBAImageEnd(&img);
return (0);
}
/*
* The TIFFRGBAImageGet() function doesn't allow us to get off the
* edge of the image, even to fill an otherwise valid tile. So we

View File

@ -92,6 +92,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
jbg_strerror(decodeStatus)
#endif
);
memset(buffer, 0, (size_t)size);
jbg_dec_free(&decoder);
return 0;
}
@ -99,6 +100,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
decodedSize = jbg_dec_getsize(&decoder);
if ((tmsize_t)decodedSize < size)
{
memset(buffer + decodedSize, 0, (size_t)(size - decodedSize));
TIFFWarningExtR(tif, "JBIG",
"Only decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT
" requested",

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

@ -71,6 +71,9 @@ typedef struct
uint8_t *uncompressed_buffer;
unsigned int uncompressed_offset;
uint8_t *uncompressed_buffer_multiband;
unsigned int uncompressed_buffer_multiband_alloc;
unsigned int mask_size;
uint8_t *mask_buffer;
@ -86,9 +89,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} LERCState;
#define LState(tif) ((LERCState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetLERCState(tif) ((LERCState *)(tif)->tif_data)
#define LERCDecoderState(tif) GetLERCState(tif)
#define LERCEncoderState(tif) GetLERCState(tif)
static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -101,7 +104,7 @@ static int LERCFixupTags(TIFF *tif)
static int LERCSetupDecode(TIFF *tif)
{
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
assert(sp != NULL);
@ -168,7 +171,7 @@ static int GetLercDataType(TIFF *tif)
return -1;
}
static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module)
{
TIFFDirectory *td = &tif->tif_dir;
uint64_t new_size_64;
@ -202,8 +205,9 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
sp->uncompressed_size = new_size;
/* add some margin as we are going to use it also to store deflate/zstd
* compressed data */
new_alloc_64 = 100 + new_size_64 + new_size_64 / 3;
* compressed data. We also need extra margin when writing very small
* rasters with one mask per band. */
new_alloc_64 = 256 + new_size_64 + new_size_64 / 3;
#ifdef ZSTD_SUPPORT
{
size_t zstd_max = ZSTD_compressBound((size_t)new_size_64);
@ -243,11 +247,17 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
GetLercDataType(tif) == 1) ||
(td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64)))
{
unsigned int mask_size = sp->segment_width * sp->segment_height;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG)
{
/* We may need one mask per band */
mask_size *= td->td_samplesperpixel;
}
#endif
if (sp->mask_size < mask_size)
{
void *mask_buffer =
@ -277,9 +287,9 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
static const char module[] = "LERCPreDecode";
lerc_status lerc_ret;
TIFFDirectory *td = &tif->tif_dir;
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
int lerc_data_type;
unsigned int infoArray[8];
unsigned int infoArray[9];
unsigned nomask_bands = td->td_samplesperpixel;
int ndims;
int use_mask = 0;
@ -295,7 +305,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
if (lerc_data_type < 0)
return 0;
if (!SetupUncompressedBuffer(tif, sp, module))
if (!SetupBuffers(tif, sp, module))
return 0;
if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE)
@ -400,7 +410,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
}
lerc_ret =
lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 8, 0);
lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 9, 0);
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_getBlobInfo() failed");
@ -418,18 +428,16 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
use_mask = 1;
nomask_bands--;
}
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64))
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
{
use_mask = 1;
}
ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1;
/* Info returned in infoArray is { version, dataType, nDim, nCols,
nRows, nBands, nValidPixels, blobSize } */
/* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols,
nRows, nBands, nValidPixels, blobSize,
and starting with liblerc 3.0 nRequestedMasks } */
if (infoArray[0] != (unsigned)sp->lerc_version)
{
TIFFWarningExtR(tif, module,
@ -442,12 +450,29 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
infoArray[1], lerc_data_type);
return 0;
}
if (infoArray[2] != (unsigned)ndims)
const unsigned nFoundDims = infoArray[2];
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1)
{
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d",
infoArray[2], ndims);
if (nFoundDims != 1 && nFoundDims != (unsigned)ndims)
{
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: 1 or %d",
nFoundDims, ndims);
return 0;
}
}
else
#endif
if (nFoundDims != (unsigned)ndims)
{
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d",
nFoundDims, ndims);
return 0;
}
if (infoArray[3] != sp->segment_width)
{
TIFFErrorExtR(tif, module, "Unexpected nCols: %d. Expected: %du",
@ -460,12 +485,38 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
infoArray[4], sp->segment_height);
return 0;
}
if (infoArray[5] != 1)
const unsigned nFoundBands = infoArray[5];
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1 && nFoundDims == 1)
{
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
infoArray[5], 1);
#if !LERC_AT_LEAST_VERSION(3, 0, 0)
if (nFoundBands == td->td_samplesperpixel)
{
TIFFErrorExtR(
tif, module,
"Unexpected nBands: %d. This file may have been generated with "
"a liblerc version >= 3.0, with one mask per band, and is not "
"supported by this older version of liblerc",
nFoundBands);
return 0;
}
#endif
if (nFoundBands != td->td_samplesperpixel)
{
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
nFoundBands, td->td_samplesperpixel);
return 0;
}
}
else if (nFoundBands != 1)
{
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
nFoundBands, 1);
return 0;
}
if (infoArray[7] != lerc_data_size)
{
TIFFErrorExtR(tif, module, "Unexpected blobSize: %d. Expected: %u",
@ -473,13 +524,75 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
return 0;
}
lerc_ret = lerc_decode(lerc_data, lerc_data_size,
int nRequestedMasks = use_mask ? 1 : 0;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0,
const int nFoundMasks = infoArray[8];
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1 && nFoundDims == 1)
{
if (nFoundMasks != 0 && nFoundMasks != td->td_samplesperpixel)
{
TIFFErrorExtR(tif, module,
"Unexpected nFoundMasks: %d. Expected: 0 or %d",
nFoundMasks, td->td_samplesperpixel);
return 0;
}
nRequestedMasks = nFoundMasks;
}
else
{
if (nFoundMasks != 0 && nFoundMasks != 1)
{
TIFFErrorExtR(tif, module,
"Unexpected nFoundMasks: %d. Expected: 0 or 1",
nFoundMasks);
return 0;
}
}
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && nFoundMasks == 0)
{
nRequestedMasks = 0;
use_mask = 0;
}
#endif
use_mask ? sp->mask_buffer : NULL, ndims,
sp->segment_width, sp->segment_height, 1,
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (nRequestedMasks > 1)
{
unsigned int num_bytes_needed =
nb_pixels * td->td_samplesperpixel * (td->td_bitspersample / 8);
if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
{
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
sp->uncompressed_buffer_multiband =
_TIFFmallocExt(tif, num_bytes_needed);
if (!sp->uncompressed_buffer_multiband)
{
sp->uncompressed_buffer_multiband_alloc = 0;
return 0;
}
sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
}
lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks,
sp->mask_buffer, nFoundDims, sp->segment_width,
sp->segment_height, nFoundBands, lerc_data_type,
sp->uncompressed_buffer_multiband);
}
else
#endif
{
lerc_ret =
lerc_decode(lerc_data, lerc_data_size,
#if LERC_AT_LEAST_VERSION(3, 0, 0)
nRequestedMasks,
#endif
use_mask ? sp->mask_buffer : NULL, nFoundDims,
sp->segment_width, sp->segment_height, nFoundBands,
lerc_data_type, sp->uncompressed_buffer);
}
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_decode() failed");
@ -515,7 +628,6 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
}
else if (use_mask && td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
{
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
unsigned i;
#if WORDS_BIGENDIAN
const unsigned char nan_bytes[] = {0x7f, 0xc0, 0, 0};
@ -525,6 +637,9 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
float nan_float32;
memcpy(&nan_float32, nan_bytes, 4);
if (td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1)
{
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
@ -543,6 +658,84 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
}
}
}
else if (nRequestedMasks == 1)
{
assert(nFoundDims == td->td_samplesperpixel);
assert(nFoundBands == 1);
unsigned k = 0;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i] == 0)
((float *)sp->uncompressed_buffer)[k] = nan_float32;
++k;
}
}
}
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i] == 0)
((double *)sp->uncompressed_buffer)[k] =
nan_float64;
++k;
}
}
}
}
#if LERC_AT_LEAST_VERSION(3, 0, 0)
else
{
assert(nRequestedMasks == td->td_samplesperpixel);
assert(nFoundDims == 1);
assert(nFoundBands == td->td_samplesperpixel);
unsigned k = 0;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i + j * nb_pixels] == 0)
((float *)sp->uncompressed_buffer)[k] = nan_float32;
else
((float *)sp->uncompressed_buffer)[k] =
((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels];
++k;
}
}
}
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i + j * nb_pixels] == 0)
((double *)sp->uncompressed_buffer)[k] =
nan_float64;
else
((double *)sp->uncompressed_buffer)[k] =
((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels];
++k;
}
}
}
}
#endif
}
return 1;
}
@ -553,7 +746,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "LERCDecode";
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -561,6 +754,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->uncompressed_buffer == 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Uncompressed buffer not allocated");
return 0;
}
@ -568,6 +762,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if ((uint64_t)sp->uncompressed_offset + (uint64_t)occ >
sp->uncompressed_size)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Too many bytes read");
return 0;
}
@ -580,7 +775,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int LERCSetupEncode(TIFF *tif)
{
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -599,7 +794,7 @@ static int LERCSetupEncode(TIFF *tif)
static int LERCPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "LERCPreEncode";
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
int lerc_data_type;
(void)s;
@ -611,7 +806,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s)
if (lerc_data_type < 0)
return 0;
if (!SetupUncompressedBuffer(tif, sp, module))
if (!SetupBuffers(tif, sp, module))
return 0;
return 1;
@ -623,7 +818,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s)
static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "LERCEncode";
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -649,8 +844,7 @@ static int LERCPostEncode(TIFF *tif)
{
lerc_status lerc_ret;
static const char module[] = "LERCPostEncode";
LERCState *sp = EncoderState(tif);
unsigned int numBytes = 0;
LERCState *sp = LERCEncoderState(tif);
unsigned int numBytesWritten = 0;
TIFFDirectory *td = &tif->tif_dir;
int use_mask = 0;
@ -662,6 +856,9 @@ static int LERCPostEncode(TIFF *tif)
return 0;
}
int mask_count = 1;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
/* Extract alpha mask (if containing only 0 and 255 values, */
/* and compact array of regular bands */
if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
@ -673,7 +870,6 @@ static int LERCPostEncode(TIFF *tif)
const unsigned src_stride =
td->td_samplesperpixel * (td->td_bitspersample / 8);
unsigned i = 0;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
use_mask = 1;
for (i = 0; i < nb_pixels; i++)
@ -710,14 +906,39 @@ static int LERCPostEncode(TIFF *tif)
}
}
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
dst_nbands == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64))
{
/* Check for NaN values */
unsigned i;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
if (td->td_bitspersample == 32)
{
if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
{
unsigned k = 0;
for (i = 0; i < nb_pixels; i++)
{
int count_nan = 0;
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const float val = ((float *)sp->uncompressed_buffer)[k];
++k;
if (val != val)
{
++count_nan;
}
}
if (count_nan > 0)
{
use_mask = 1;
if (count_nan < td->td_samplesperpixel)
{
mask_count = td->td_samplesperpixel;
break;
}
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
@ -729,6 +950,36 @@ static int LERCPostEncode(TIFF *tif)
}
}
}
}
else
{
if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
{
unsigned k = 0;
for (i = 0; i < nb_pixels; i++)
{
int count_nan = 0;
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const double val =
((double *)sp->uncompressed_buffer)[k];
++k;
if (val != val)
{
++count_nan;
}
}
if (count_nan > 0)
{
use_mask = 1;
if (count_nan < td->td_samplesperpixel)
{
mask_count = td->td_samplesperpixel;
break;
}
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
@ -741,8 +992,91 @@ static int LERCPostEncode(TIFF *tif)
}
}
}
}
if (use_mask)
{
if (mask_count > 1)
{
#if LERC_AT_LEAST_VERSION(3, 0, 0)
unsigned int num_bytes_needed =
nb_pixels * dst_nbands * (td->td_bitspersample / 8);
if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
{
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
sp->uncompressed_buffer_multiband =
_TIFFmallocExt(tif, num_bytes_needed);
if (!sp->uncompressed_buffer_multiband)
{
sp->uncompressed_buffer_multiband_alloc = 0;
return 0;
}
sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
}
unsigned k = 0;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const float val =
((float *)sp->uncompressed_buffer)[k];
((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val;
++k;
sp->mask_buffer[i + j * nb_pixels] =
(val == val) ? 255 : 0;
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const double val =
((double *)sp->uncompressed_buffer)[k];
((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val;
++k;
sp->mask_buffer[i + j * nb_pixels] =
(val == val) ? 255 : 0;
}
}
}
#else
TIFFErrorExtR(tif, module,
"lerc_encode() would need to create one mask per "
"sample, but this requires liblerc >= 3.0");
return 0;
#endif
}
else if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
dst_nbands > 1)
{
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
const float val =
((float *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
const double val =
((double *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
}
else
{
if (td->td_bitspersample == 32)
{
@ -756,48 +1090,47 @@ static int LERCPostEncode(TIFF *tif)
{
for (i = 0; i < nb_pixels; i++)
{
const double val = ((double *)sp->uncompressed_buffer)[i];
const double val =
((double *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
}
}
#if 0
lerc_ret = lerc_computeCompressedSize(
sp->uncompressed_buffer,
sp->lerc_version,
GetLercDataType(tif),
td->td_planarconfig == PLANARCONFIG_CONTIG ?
dst_nbands : 1,
sp->segment_width,
sp->segment_height,
1,
use_mask ? sp->mask_buffer : NULL,
sp->maxzerror,
&numBytes);
if( lerc_ret != 0 )
{
TIFFErrorExtR(tif, module,
"lerc_computeCompressedSize() failed");
return 0;
}
#else
numBytes = sp->uncompressed_alloc;
unsigned int estimated_compressed_size = sp->uncompressed_alloc;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (mask_count > 1)
{
estimated_compressed_size += nb_pixels * mask_count / 8;
}
#endif
if (sp->compressed_size < numBytes)
if (sp->compressed_size < estimated_compressed_size)
{
_TIFFfreeExt(tif, sp->compressed_buffer);
sp->compressed_buffer = _TIFFmallocExt(tif, numBytes);
sp->compressed_buffer = _TIFFmallocExt(tif, estimated_compressed_size);
if (!sp->compressed_buffer)
{
sp->compressed_size = 0;
return 0;
}
sp->compressed_size = numBytes;
sp->compressed_size = estimated_compressed_size;
}
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (mask_count > 1)
{
lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer_multiband, sp->lerc_version,
GetLercDataType(tif), 1, sp->segment_width, sp->segment_height,
dst_nbands, dst_nbands, sp->mask_buffer, sp->maxzerror,
sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
}
else
#endif
{
lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif),
td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1,
@ -805,14 +1138,15 @@ static int LERCPostEncode(TIFF *tif)
#if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0,
#endif
use_mask ? sp->mask_buffer : NULL, sp->maxzerror, sp->compressed_buffer,
sp->compressed_size, &numBytesWritten);
use_mask ? sp->mask_buffer : NULL, sp->maxzerror,
sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
}
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_encode() failed");
return 0;
}
assert(numBytesWritten < numBytes);
assert(numBytesWritten < estimated_compressed_size);
if (sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE)
{
@ -950,7 +1284,7 @@ static int LERCPostEncode(TIFF *tif)
static void LERCCleanup(TIFF *tif)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
assert(sp != 0);
@ -958,6 +1292,7 @@ static void LERCCleanup(TIFF *tif)
tif->tif_tagmethods.vsetfield = sp->vsetparent;
_TIFFfreeExt(tif, sp->uncompressed_buffer);
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
_TIFFfreeExt(tif, sp->compressed_buffer);
_TIFFfreeExt(tif, sp->mask_buffer);
@ -995,7 +1330,7 @@ static const TIFFField LERCFields[] = {
static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
int ret;
va_list ap;
va_start(ap, tag);
@ -1007,7 +1342,7 @@ static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...)
static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "LERCVSetField";
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
switch (tag)
{
@ -1115,7 +1450,7 @@ static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
switch (tag)
{
@ -1163,7 +1498,7 @@ int TIFFInitLERC(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, 1, sizeof(LERCState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetLERCState(tif);
/*
* Override parent get/set field methods.

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

@ -44,6 +44,8 @@
typedef struct
{
TIFFPredictorState predict;
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
lzma_stream stream;
lzma_filter filters[LZMA_FILTERS_MAX + 1];
lzma_options_delta opt_delta; /* delta filter options */
@ -58,9 +60,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} LZMAState;
#define LState(tif) ((LZMAState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetLZMAState(tif) ((LZMAState *)(tif)->tif_data)
#define LZMADecoderState(tif) GetLZMAState(tif)
#define LZMAEncoderState(tif) GetLZMAState(tif)
static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -106,7 +108,7 @@ static int LZMAFixupTags(TIFF *tif)
static int LZMASetupDecode(TIFF *tif)
{
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
assert(sp != NULL);
@ -127,7 +129,7 @@ static int LZMASetupDecode(TIFF *tif)
static int LZMAPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZMAPreDecode";
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
lzma_ret ret;
(void)s;
@ -156,18 +158,31 @@ static int LZMAPreDecode(TIFF *tif, uint16_t s)
LZMAStrerror(ret));
return 0;
}
sp->read_error = 0;
return 1;
}
static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "LZMADecode";
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
(void)s;
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"LZMADecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (size_t)tif->tif_rawcc;
@ -175,6 +190,9 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
sp->stream.avail_out = (size_t)occ;
if ((tmsize_t)sp->stream.avail_out != occ)
{
// read_error not set here as this is a usage issue that can be
// recovered in a following call.
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Liblzma cannot deal with buffers this size");
return 0;
@ -198,6 +216,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0);
if (r != LZMA_OK)
{
sp->read_error = 1;
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Error initializing the stream decoder, %s",
LZMAStrerror(r));
@ -217,6 +237,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} while (sp->stream.avail_out > 0);
if (sp->stream.avail_out != 0)
{
sp->read_error = 1;
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32
" (short %" TIFF_SIZE_FORMAT " bytes)",
@ -232,7 +254,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int LZMASetupEncode(TIFF *tif)
{
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -251,7 +273,7 @@ static int LZMASetupEncode(TIFF *tif)
static int LZMAPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZMAPreEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
lzma_ret ret;
(void)s;
@ -283,7 +305,7 @@ static int LZMAPreEncode(TIFF *tif, uint16_t s)
static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "LZMAEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_ENCODE);
@ -329,7 +351,7 @@ static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int LZMAPostEncode(TIFF *tif)
{
static const char module[] = "LZMAPostEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
lzma_ret ret;
sp->stream.avail_in = 0;
@ -365,7 +387,7 @@ static int LZMAPostEncode(TIFF *tif)
static void LZMACleanup(TIFF *tif)
{
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
assert(sp != 0);
@ -388,7 +410,7 @@ static void LZMACleanup(TIFF *tif)
static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "LZMAVSetField";
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
switch (tag)
{
@ -414,7 +436,7 @@ static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int LZMAVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
switch (tag)
{
@ -457,7 +479,7 @@ int TIFFInitLZMA(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZMAState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetLZMAState(tif);
memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
/*

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

@ -207,37 +207,21 @@ static const TIFFField ojpegFields[] = {
#include <setjmp.h>
#endif
/* 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
/* 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"
#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
typedef struct jpeg_common_struct jpeg_common_struct;
typedef struct jpeg_decompress_struct jpeg_decompress_struct;
typedef struct jpeg_source_mgr jpeg_source_mgr;
typedef enum
{
@ -771,6 +755,9 @@ static int OJPEGPreDecode(TIFF *tif, uint16_t s)
if (OJPEGWriteHeaderInfo(tif) == 0)
return (0);
}
sp->subsampling_convert_state = 0;
while (sp->write_curstrile < m)
{
if (sp->libjpeg_jpeg_query_style == 0)
@ -856,12 +843,14 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
(void)s;
if (!sp->decoder_ok)
{
memset(buf, 0, (size_t)cc);
TIFFErrorExtR(tif, module,
"Cannot decode: decoder not correctly initialized");
return 0;
}
if (sp->libjpeg_session_active == 0)
{
memset(buf, 0, (size_t)cc);
/* This should normally not happen, except that it does when */
/* using TIFFReadScanline() which calls OJPEGPostDecode() for */
/* each scanline, which assumes that a whole strile was read */
@ -875,18 +864,25 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
}
if (sp->error_in_raw_data_decoding)
{
memset(buf, 0, (size_t)cc);
return 0;
}
if (sp->libjpeg_jpeg_query_style == 0)
{
if (OJPEGDecodeRaw(tif, buf, cc) == 0)
{
memset(buf, 0, (size_t)cc);
return (0);
}
}
else
{
if (OJPEGDecodeScanlines(tif, buf, cc) == 0)
{
memset(buf, 0, (size_t)cc);
return (0);
}
}
return (1);
}

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 (tif != NULL && tif->tif_max_single_mem_alloc > 0)
{
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 * 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)
@ -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,8 +974,12 @@ 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,
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);
@ -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,8 +1566,13 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
if (TIFFIsTiled(tif))
{
if (!TIFFStartTile(tif, strile) ||
!(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize,
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,15 +1584,28 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
uint32_t stripsperplane;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
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) ||
!(*tif->tif_decodestrip)(tif, (uint8_t *)outbuf, outsize,
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)
{
(*tif->tif_postdecode)(tif, (uint8_t *)outbuf, outsize);

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)
{
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 @@
* Windows Common RunTime Library.
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tif_config.h"
#ifdef HAVE_SYS_TYPES_H
@ -79,6 +83,8 @@ static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size)
size_t io_size = bytes_total - bytes_read;
if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */
/* coverity[overflow_sink] */
count = read(fdh.fd, buf_offset, (TIFFIOSize_t)io_size);
if (count <= 0)
break;
@ -106,6 +112,8 @@ static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size)
size_t io_size = bytes_total - bytes_written;
if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */
/* coverity[overflow_sink] */
count = write(fdh.fd, buf_offset, (TIFFIOSize_t)io_size);
if (count <= 0)
break;
@ -258,7 +266,7 @@ TIFF *TIFFOpenExt(const char *name, const char *mode, TIFFOpenOptions *opts)
return tif;
}
#ifdef __WIN32__
#ifdef _WIN32
#include <windows.h>
/*
* Open a TIFF file with a Unicode filename, for read/writing.

View File

@ -47,6 +47,8 @@ typedef struct
{
uint16_t nSamples; /* number of samples per pixel */
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
int lossless; /* lossy/lossless compression */
int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas
with alpha = 0 will be preserved */
@ -133,6 +135,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
if (sp->psDecoder == NULL)
{
TIFFDirectory *td = &tif->tif_dir;
@ -158,12 +170,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
: (uint32_t)tif->tif_rawcc,
&webp_width, &webp_height))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPGetInfo() failed");
return 0;
}
if ((uint32_t)webp_width != segment_width ||
(uint32_t)webp_height != segment_height)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(
tif, module, "WebP blob dimension is %dx%d. Expected %ux%u",
webp_width, webp_height, segment_width, segment_height);
@ -174,6 +190,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
return 0;
}
@ -189,6 +207,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (!bWebPGetFeaturesOK)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
return 0;
}
@ -202,6 +222,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
*/
!(webp_bands == 3 && sp->nSamples == 4))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"WebP blob band count is %d. Expected %d", webp_bands,
sp->nSamples);
@ -228,6 +250,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (!sp->pBuffer)
{
TIFFErrorExtR(tif, module, "Cannot allocate buffer");
memset(op, 0, (size_t)occ);
sp->read_error = 1;
return 0;
}
sp->buffer_size = buffer_size;
@ -257,6 +281,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->psDecoder == NULL)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder.");
return 0;
}
@ -264,6 +290,10 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (occ % sp->sDecBuffer.u.RGBA.stride)
{
// read_error not set here as this is a usage issue that can be
// recovered in a following call.
memset(op, 0, (size_t)occ);
/* Do not set read_error as could potentially be recovered */
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return 0;
}
@ -284,6 +314,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
TIFFErrorExtR(tif, module, "Unrecognized error.");
}
memset(op, 0, (size_t)occ);
sp->read_error = 1;
return 0;
}
else
@ -303,6 +335,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
if (current_y != numberOfExpectedLines)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"Unable to decode WebP data: less lines than "
"expected.");
@ -332,6 +366,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
}
else
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "Unable to decode WebP data.");
return 0;
}
@ -451,6 +487,8 @@ static int TWebPPreDecode(TIFF *tif, uint16_t s)
sp->psDecoder = NULL;
}
sp->read_error = 0;
return 1;
}

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

@ -54,9 +54,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} ZSTDState;
#define LState(tif) ((ZSTDState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetZSTDState(tif) ((ZSTDState *)(tif)->tif_data)
#define ZSTDDecoderState(tif) GetZSTDState(tif)
#define ZSTDEncoderState(tif) GetZSTDState(tif)
static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -69,7 +69,7 @@ static int ZSTDFixupTags(TIFF *tif)
static int ZSTDSetupDecode(TIFF *tif)
{
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
assert(sp != NULL);
@ -91,7 +91,7 @@ static int ZSTDSetupDecode(TIFF *tif)
static int ZSTDPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "ZSTDPreDecode";
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
size_t zstd_ret;
(void)s;
@ -124,7 +124,7 @@ static int ZSTDPreDecode(TIFF *tif, uint16_t s)
static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "ZSTDDecode";
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
ZSTD_inBuffer in_buffer;
ZSTD_outBuffer out_buffer;
size_t zstd_ret;
@ -146,6 +146,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, &in_buffer);
if (ZSTD_isError(zstd_ret))
{
memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos);
TIFFErrorExtR(tif, module, "Error in ZSTD_decompressStream(): %s",
ZSTD_getErrorName(zstd_ret));
return 0;
@ -155,6 +156,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (out_buffer.pos < (size_t)occ)
{
memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %lu (short %lu bytes)",
(unsigned long)tif->tif_row,
@ -170,7 +172,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int ZSTDSetupEncode(TIFF *tif)
{
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -190,7 +192,7 @@ static int ZSTDSetupEncode(TIFF *tif)
static int ZSTDPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "ZSTDPreEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
size_t zstd_ret;
(void)s;
@ -229,7 +231,7 @@ static int ZSTDPreEncode(TIFF *tif, uint16_t s)
static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "ZSTDEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
ZSTD_inBuffer in_buffer;
size_t zstd_ret;
@ -271,7 +273,7 @@ static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int ZSTDPostEncode(TIFF *tif)
{
static const char module[] = "ZSTDPostEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
size_t zstd_ret;
do
@ -297,7 +299,7 @@ static int ZSTDPostEncode(TIFF *tif)
static void ZSTDCleanup(TIFF *tif)
{
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
assert(sp != 0);
@ -325,7 +327,7 @@ static void ZSTDCleanup(TIFF *tif)
static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "ZSTDVSetField";
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
switch (tag)
{
@ -347,7 +349,7 @@ static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int ZSTDVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
switch (tag)
{
@ -389,7 +391,7 @@ int TIFFInitZSTD(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(ZSTDState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetZSTDState(tif);
/*
* Override parent get/set field methods.

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;
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 */
@ -234,6 +256,8 @@ struct tiff
TIFFErrorHandlerExtR tif_warnhandler;
void *tif_warnhandler_user_data;
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);