Merge pull request #29838 from Xingchen1224:libtiff-4.7.2-upgrade

3rdparty/libtiff: Upgrade libtiff to 4.7.2 - #29838

[Feature Request] Upgrade libtiff to 4.7.2 (https://libtiff.gitlab.io/libtiff/releases/v4.7.2.html)

### 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:
Xingchen
2026-09-03 19:29:33 +08:00
committed by GitHub
parent 1209808c70
commit 5b526645b6
43 changed files with 5352 additions and 1700 deletions

View File

@@ -359,7 +359,7 @@ endif()
set(LIBTIFF_MAJOR_VERSION "4") set(LIBTIFF_MAJOR_VERSION "4")
set(LIBTIFF_MINOR_VERSION "7") set(LIBTIFF_MINOR_VERSION "7")
set(LIBTIFF_MICRO_VERSION "1") set(LIBTIFF_MICRO_VERSION "2")
set(LIBTIFF_VERSION "${LIBTIFF_MAJOR_VERSION}.${LIBTIFF_MINOR_VERSION}.${LIBTIFF_MICRO_VERSION}") set(LIBTIFF_VERSION "${LIBTIFF_MAJOR_VERSION}.${LIBTIFF_MINOR_VERSION}.${LIBTIFF_MICRO_VERSION}")
file(READ "RELEASE-DATE" LIBTIFF_RELEASE_DATE content) file(READ "RELEASE-DATE" LIBTIFF_RELEASE_DATE content)

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
20250911 20260627

View File

@@ -56,6 +56,21 @@ uint64_t _TIFFMultiply64(TIFF *tif, uint64_t first, uint64_t second,
return first * second; return first * second;
} }
uint64_t _TIFFAdd64(TIFF *tif, uint64_t first, uint64_t second,
const char *where)
{
if (first > UINT64_MAX - second)
{
if (tif != NULL && where != NULL)
{
TIFFErrorExtR(tif, where, "Integer overflow in %s", where);
}
return 0;
}
return first + second;
}
tmsize_t _TIFFMultiplySSize(TIFF *tif, tmsize_t first, tmsize_t second, tmsize_t _TIFFMultiplySSize(TIFF *tif, tmsize_t first, tmsize_t second,
const char *where) const char *where)
{ {
@@ -81,6 +96,30 @@ tmsize_t _TIFFMultiplySSize(TIFF *tif, tmsize_t first, tmsize_t second,
return first * second; return first * second;
} }
tmsize_t _TIFFAddSSize(TIFF *tif, tmsize_t first, tmsize_t second,
const char *where)
{
if (first < 0 || second < 0)
{
if (tif != NULL && where != NULL)
{
TIFFErrorExtR(tif, where,
"Invalid argument to _TIFFAddSSize() in %s", where);
}
return 0;
}
if (first > TIFF_TMSIZE_T_MAX - second)
{
if (tif != NULL && where != NULL)
{
TIFFErrorExtR(tif, where, "Integer overflow in %s", where);
}
return 0;
}
return first + second;
}
tmsize_t _TIFFCastUInt64ToSSize(TIFF *tif, uint64_t val, const char *module) tmsize_t _TIFFCastUInt64ToSSize(TIFF *tif, uint64_t val, const char *module)
{ {
if (val > (uint64_t)TIFF_TMSIZE_T_MAX) if (val > (uint64_t)TIFF_TMSIZE_T_MAX)
@@ -94,6 +133,55 @@ tmsize_t _TIFFCastUInt64ToSSize(TIFF *tif, uint64_t val, const char *module)
return (tmsize_t)val; return (tmsize_t)val;
} }
uint32_t _TIFFCastUInt64ToUInt32(TIFF *tif, uint64_t val, const char *module)
{
if (val > UINT32_MAX)
{
if (tif != NULL && module != NULL)
{
TIFFErrorExtR(tif, module, "Integer overflow");
}
return 0;
}
return (uint32_t)val;
}
tmsize_t _TIFFComputeRowOffset(TIFF *tif, tmsize_t rowstride, uint32_t row,
const char *where)
{
if (row == 0)
return 0;
return _TIFFMultiplySSize(tif, rowstride, (tmsize_t)row, where);
}
uint64_t _TIFFComputeBitOffset(TIFF *tif, uint32_t col, uint16_t spp,
uint16_t bps, const char *where)
{
uint64_t samples = _TIFFMultiply64(tif, col, spp, where);
if (samples == 0 && col != 0)
return 0;
return _TIFFMultiply64(tif, samples, bps, where);
}
/*
* Returns 0 on overflow or invalid zero-sized row inputs. Callers that
* intentionally allow empty rows should not use this helper directly.
*/
uint64_t _TIFFComputeRowSize64(TIFF *tif, uint32_t width, uint16_t spp,
uint16_t bps, const char *where)
{
uint64_t samples = _TIFFMultiply64(tif, width, spp, where);
uint64_t bits;
if (samples == 0)
return 0;
bits = _TIFFMultiply64(tif, samples, bps, where);
if (bits == 0)
return 0;
return TIFFhowmany8_64(bits);
}
void *_TIFFCheckRealloc(TIFF *tif, void *buffer, tmsize_t nmemb, void *_TIFFCheckRealloc(TIFF *tif, void *buffer, tmsize_t nmemb,
tmsize_t elem_size, const char *what) tmsize_t elem_size, const char *what)
{ {
@@ -137,8 +225,8 @@ static int TIFFDefaultTransferFunction(TIFF *tif, TIFFDirectory *td)
if (td->td_bitspersample > 24) if (td->td_bitspersample > 24)
return 0; return 0;
n = ((tmsize_t)1) << td->td_bitspersample; n = (tmsize_t)(1ULL << td->td_bitspersample);
nbytes = n * sizeof(uint16_t); nbytes = (tmsize_t)((uint64_t)n * sizeof(uint16_t));
tf[0] = (uint16_t *)_TIFFmallocExt(tif, nbytes); tf[0] = (uint16_t *)_TIFFmallocExt(tif, nbytes);
if (tf[0] == NULL) if (tf[0] == NULL)
return 0; return 0;
@@ -186,10 +274,10 @@ static int TIFFDefaultRefBlackWhite(TIFF *tif, TIFFDirectory *td)
* YCbCr (Class Y) images must have the ReferenceBlackWhite * YCbCr (Class Y) images must have the ReferenceBlackWhite
* tag set. Fix the broken images, which lacks that tag. * tag set. Fix the broken images, which lacks that tag.
*/ */
td->td_refblackwhite[0] = 0.0F; td->td_refblackwhite[0] = 0.0f;
td->td_refblackwhite[1] = td->td_refblackwhite[3] = td->td_refblackwhite[1] = td->td_refblackwhite[3] =
td->td_refblackwhite[5] = 255.0F; td->td_refblackwhite[5] = 255.0f;
td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0f;
} }
else else
{ {
@@ -199,8 +287,11 @@ static int TIFFDefaultRefBlackWhite(TIFF *tif, TIFFDirectory *td)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
td->td_refblackwhite[2 * i + 0] = 0; td->td_refblackwhite[2 * i + 0] = 0;
td->td_refblackwhite[2 * i + 1] = if (td->td_bitspersample < 64)
(float)((1L << td->td_bitspersample) - 1L); td->td_refblackwhite[2 * i + 1] =
(float)((1ULL << td->td_bitspersample) - 1ULL);
else
td->td_refblackwhite[2 * i + 1] = (float)UINT64_MAX;
} }
} }
return 1; return 1;
@@ -258,8 +349,8 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap)
* 65535 even if td_bitspersamle is > 16 */ * 65535 even if td_bitspersamle is > 16 */
if (td->td_bitspersample <= 16) if (td->td_bitspersample <= 16)
{ {
maxsamplevalue = (1 << td->td_bitspersample) - maxsamplevalue = (uint16_t)((1U << td->td_bitspersample) -
1; /* 2**(BitsPerSample) - 1 */ 1); /* 2**(BitsPerSample) - 1 */
} }
else else
{ {
@@ -295,7 +386,11 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap)
} }
case TIFFTAG_DOTRANGE: case TIFFTAG_DOTRANGE:
*va_arg(ap, uint16_t *) = 0; *va_arg(ap, uint16_t *) = 0;
*va_arg(ap, uint16_t *) = (1 << td->td_bitspersample) - 1; if (td->td_bitspersample <= 16)
*va_arg(ap, uint16_t *) =
(uint16_t)((1U << td->td_bitspersample) - 1);
else
*va_arg(ap, uint16_t *) = 65535;
return (1); return (1);
case TIFFTAG_INKSET: case TIFFTAG_INKSET:
*va_arg(ap, uint16_t *) = INKSET_CMYK; *va_arg(ap, uint16_t *) = INKSET_CMYK;
@@ -309,14 +404,14 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap)
return (1); return (1);
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
*va_arg(ap, uint16_t *) = *va_arg(ap, uint16_t *) =
(td->td_extrasamples == 1 && (td->td_extrasamples == 1 && td->td_sampleinfo &&
td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
return (1); return (1);
case TIFFTAG_TILEDEPTH: case TIFFTAG_TILEDEPTH:
*va_arg(ap, uint32_t *) = td->td_tiledepth; *va_arg(ap, uint32_t *) = td->td_tiledepth;
return (1); return (1);
case TIFFTAG_DATATYPE: case TIFFTAG_DATATYPE:
*va_arg(ap, uint16_t *) = td->td_sampleformat - 1; *va_arg(ap, uint16_t *) = (uint16_t)(td->td_sampleformat - 1);
return (1); return (1);
case TIFFTAG_SAMPLEFORMAT: case TIFFTAG_SAMPLEFORMAT:
*va_arg(ap, uint16_t *) = td->td_sampleformat; *va_arg(ap, uint16_t *) = td->td_sampleformat;
@@ -369,6 +464,8 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap)
return (0); return (0);
*va_arg(ap, const float **) = td->td_refblackwhite; *va_arg(ap, const float **) = td->td_refblackwhite;
return (1); return (1);
default:
break;
} }
return 0; return 0;
} }
@@ -390,9 +487,9 @@ int TIFFGetFieldDefaulted(TIFF *tif, uint32_t tag, ...)
float _TIFFClampDoubleToFloat(double val) float _TIFFClampDoubleToFloat(double val)
{ {
if (val > FLT_MAX) if (val > (double)FLT_MAX)
return FLT_MAX; return FLT_MAX;
if (val < -FLT_MAX) if (val < -(double)FLT_MAX)
return -FLT_MAX; return -FLT_MAX;
return (float)val; return (float)val;
} }
@@ -401,7 +498,7 @@ uint32_t _TIFFClampDoubleToUInt32(double val)
{ {
if (val < 0) if (val < 0)
return 0; return 0;
if (val > 0xFFFFFFFFU || val != val) if (val > 0xFFFFFFFFU || isnan(val))
return 0xFFFFFFFFU; return 0xFFFFFFFFU;
return (uint32_t)val; return (uint32_t)val;
} }

View File

@@ -88,7 +88,7 @@ void TIFFCleanup(TIFF *tif)
*/ */
TIFFFieldIsAnonymous(fld)) TIFFFieldIsAnonymous(fld))
{ {
_TIFFfreeExt(tif, fld->field_name); _TIFFfreeExt(tif, (void *)fld->field_name);
_TIFFfreeExt(tif, fld); _TIFFfreeExt(tif, fld);
} }
} }
@@ -121,7 +121,7 @@ void TIFFCleanup(TIFF *tif)
} }
/************************************************************************/ /************************************************************************/
/* _TIFFCleanupIFDOffsetAndNumberMaps() */ /* _TIFFCleanupIFDOffsetAndNumberMaps() */
/************************************************************************/ /************************************************************************/
void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif) void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif)
@@ -139,7 +139,7 @@ void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif)
} }
/************************************************************************/ /************************************************************************/
/* TIFFClose() */ /* TIFFClose() */
/************************************************************************/ /************************************************************************/
/** /**

View File

@@ -55,34 +55,34 @@ void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, int32_t b,
void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
int32_t b, float *X, float *Y, float *Z) int32_t b, float *X, float *Y, float *Z)
{ {
float L = (float)l * 100.0F / 65535.0F; float L = (float)l * 100.0f / 65535.0f;
float cby, tmp; float cby, tmp;
if (L < 8.856F) if (L < 8.856f)
{ {
*Y = (L * cielab->Y0) / 903.292F; *Y = (L * cielab->Y0) / 903.292f;
cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; cby = 7.787f * (*Y / cielab->Y0) + 16.0f / 116.0f;
} }
else else
{ {
cby = (L + 16.0F) / 116.0F; cby = (L + 16.0f) / 116.0f;
*Y = cielab->Y0 * cby * cby * cby; *Y = cielab->Y0 * cby * cby * cby;
} }
tmp = (float)a / 256.0F / 500.0F + cby; tmp = (float)a / 256.0f / 500.0f + cby;
if (tmp < 0.2069F) if (tmp < 0.2069f)
*X = cielab->X0 * (tmp - 0.13793F) / 7.787F; *X = cielab->X0 * (tmp - 0.13793f) / 7.787f;
else else
*X = cielab->X0 * tmp * tmp * tmp; *X = cielab->X0 * tmp * tmp * tmp;
tmp = cby - (float)b / 256.0F / 200.0F; tmp = cby - (float)b / 256.0f / 200.0f;
if (tmp < 0.2069F) if (tmp < 0.2069f)
*Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; *Z = cielab->Z0 * (tmp - 0.13793f) / 7.787f;
else else
*Z = cielab->Z0 * tmp * tmp * tmp; *Z = cielab->Z0 * tmp * tmp * tmp;
} }
#define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5) : ((R)-0.5))) #define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5f) : ((R) - 0.5f)))
/* /*
* Convert color value from the XYZ space to RGB. * Convert color value from the XYZ space to RGB.
*/ */
@@ -143,32 +143,32 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
_TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
/* Red */ /* Red */
dfGamma = 1.0 / cielab->display.d_gammaR; dfGamma = 1.0 / (double)cielab->display.d_gammaR;
cielab->rstep = cielab->rstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
for (i = 0; i <= (size_t)cielab->range; i++) for (i = 0; i <= (size_t)cielab->range; i++)
{ {
cielab->Yr2r[i] = cielab->display.d_Vrwr * cielab->Yr2r[i] = (float)cielab->display.d_Vrwr *
((float)pow((double)i / cielab->range, dfGamma)); ((float)pow((double)i / cielab->range, dfGamma));
} }
/* Green */ /* Green */
dfGamma = 1.0 / cielab->display.d_gammaG; dfGamma = 1.0 / (double)cielab->display.d_gammaG;
cielab->gstep = cielab->gstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
for (i = 0; i <= (size_t)cielab->range; i++) for (i = 0; i <= (size_t)cielab->range; i++)
{ {
cielab->Yg2g[i] = cielab->display.d_Vrwg * cielab->Yg2g[i] = (float)cielab->display.d_Vrwg *
((float)pow((double)i / cielab->range, dfGamma)); ((float)pow((double)i / cielab->range, dfGamma));
} }
/* Blue */ /* Blue */
dfGamma = 1.0 / cielab->display.d_gammaB; dfGamma = 1.0 / (double)cielab->display.d_gammaB;
cielab->bstep = cielab->bstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
for (i = 0; i <= (size_t)cielab->range; i++) for (i = 0; i <= (size_t)cielab->range; i++)
{ {
cielab->Yb2b[i] = cielab->display.d_Vrwb * cielab->Yb2b[i] = (float)cielab->display.d_Vrwb *
((float)pow((double)i / cielab->range, dfGamma)); ((float)pow((double)i / cielab->range, dfGamma));
} }
@@ -186,11 +186,11 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
* see below for more information on how it works. * see below for more information on how it works.
*/ */
#define SHIFT 16 #define SHIFT 16
#define FIX(x) ((int32_t)((x) * (1L << SHIFT) + 0.5)) #define FIX(x) ((int32_t)((double)(x) * (1L << SHIFT) + 0.5))
#define ONE_HALF ((int32_t)(1 << (SHIFT - 1))) #define ONE_HALF ((int32_t)(1 << (SHIFT - 1)))
#define Code2V(c, RB, RW, CR) \ #define Code2V(c, RB, RW, CR) \
((((c) - (int32_t)(RB)) * (float)(CR)) / \ (((float)((c) - (int32_t)(RB)) * (float)(CR)) / \
(float)(((RW) - (RB) != 0) ? ((RW) - (RB)) : 1)) ((!TIFF_FLOAT_EQ((RW), (RB))) ? ((RW) - (RB)) : 1.0f))
/* !((f)>=(min)) written that way to deal with NaN */ /* !((f)>=(min)) written that way to deal with NaN */
#define CLAMP(f, min, max) \ #define CLAMP(f, min, max) \
((!((f) >= (min))) ? (min) : (f) > (max) ? (max) : (f)) ((!((f) >= (min))) ? (min) : (f) > (max) ? (max) : (f))
@@ -207,12 +207,12 @@ void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32_t Y, int32_t Cb, int32_t Cr,
Cr = CLAMP(Cr, 0, 255); Cr = CLAMP(Cr, 0, 255);
i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
*r = CLAMP(i, 0, 255); *r = (uint32_t)CLAMP(i, 0, 255);
i = ycbcr->Y_tab[Y] + i = ycbcr->Y_tab[Y] +
(int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); ((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
*g = CLAMP(i, 0, 255); *g = (uint32_t)CLAMP(i, 0, 255);
i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
*b = CLAMP(i, 0, 255); *b = (uint32_t)CLAMP(i, 0, 255);
} }
/* Clamp function for sanitization purposes. Normally clamping should not */ /* Clamp function for sanitization purposes. Normally clamping should not */
@@ -258,8 +258,7 @@ int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
#define LumaBlue luma[2] #define LumaBlue luma[2]
clamptab = clamptab =
(TIFFRGBValue *)((uint8_t *)ycbcr + (uint8_t *)ycbcr + TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long));
TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)));
_TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
ycbcr->clamptab = (clamptab += 256); ycbcr->clamptab = (clamptab += 256);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@@ -273,13 +272,13 @@ int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
{ {
float f1 = 2 - 2 * LumaRed; float f1 = 2 - 2 * LumaRed;
int32_t D1 = FIX(CLAMP(f1, 0.0F, 2.0F)); int32_t D1 = FIX(CLAMP(f1, 0.0f, 2.0f));
float f2 = LumaRed * f1 / LumaGreen; float f2 = LumaRed * f1 / LumaGreen;
int32_t D2 = -FIX(CLAMP(f2, 0.0F, 2.0F)); int32_t D2 = -FIX(CLAMP(f2, 0.0f, 2.0f));
float f3 = 2 - 2 * LumaBlue; float f3 = 2 - 2 * LumaBlue;
int32_t D3 = FIX(CLAMP(f3, 0.0F, 2.0F)); int32_t D3 = FIX(CLAMP(f3, 0.0f, 2.0f));
float f4 = LumaBlue * f3 / LumaGreen; float f4 = LumaBlue * f3 / LumaGreen;
int32_t D4 = -FIX(CLAMP(f4, 0.0F, 2.0F)); int32_t D4 = -FIX(CLAMP(f4, 0.0f, 2.0f));
int x; int x;
#undef LumaBlue #undef LumaBlue
@@ -295,12 +294,12 @@ int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
*/ */
for (i = 0, x = -128; i < 256; i++, x++) for (i = 0, x = -128; i < 256; i++, x++)
{ {
int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F, int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0f,
refBlackWhite[5] - 128.0F, 127), refBlackWhite[5] - 128.0f, 127),
-128.0F * 32, 128.0F * 32); -128.0f * 32, 128.0f * 32);
int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F, int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0f,
refBlackWhite[3] - 128.0F, 127), refBlackWhite[3] - 128.0f, 127),
-128.0F * 32, 128.0F * 32); -128.0f * 32, 128.0f * 32);
ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT); ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT);
ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT); ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT);
@@ -308,7 +307,7 @@ int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF; ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF;
ycbcr->Y_tab[i] = (int32_t)CLAMPw( ycbcr->Y_tab[i] = (int32_t)CLAMPw(
Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255), Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
-128.0F * 32, 128.0F * 32); -128.0f * 32, 128.0f * 32);
} }
} }

View File

@@ -139,6 +139,18 @@ static int _TIFFtrue(TIFF *tif)
} }
static void _TIFFvoid(TIFF *tif) { (void)tif; } static void _TIFFvoid(TIFF *tif) { (void)tif; }
static uint64_t _TIFFDefaultGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
return 0; /* unknown */
}
static uint64_t _TIFFGetMaxCompressionRatioOne(TIFF *tif)
{
(void)tif;
return 1; /* no compression */
}
void _TIFFSetDefaultCompressionState(TIFF *tif) void _TIFFSetDefaultCompressionState(TIFF *tif)
{ {
tif->tif_fixuptags = _TIFFNoFixupTags; tif->tif_fixuptags = _TIFFNoFixupTags;
@@ -160,6 +172,7 @@ void _TIFFSetDefaultCompressionState(TIFF *tif)
tif->tif_cleanup = _TIFFvoid; tif->tif_cleanup = _TIFFvoid;
tif->tif_defstripsize = _TIFFDefaultStripSize; tif->tif_defstripsize = _TIFFDefaultStripSize;
tif->tif_deftilesize = _TIFFDefaultTileSize; tif->tif_deftilesize = _TIFFDefaultTileSize;
tif->tif_getmaxcompressionratio = _TIFFDefaultGetMaxCompressionRatio;
tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW); tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW);
} }
@@ -168,6 +181,8 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme)
const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme); const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme);
_TIFFSetDefaultCompressionState(tif); _TIFFSetDefaultCompressionState(tif);
if (scheme == COMPRESSION_NONE)
tif->tif_getmaxcompressionratio = _TIFFGetMaxCompressionRatioOne;
/* /*
* Don't treat an unknown compression scheme as an error. * Don't treat an unknown compression scheme as an error.
* This permits applications to open files with data that * This permits applications to open files with data that
@@ -177,6 +192,13 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme)
return (c ? (*c->init)(tif, scheme) : 1); return (c ? (*c->init)(tif, scheme) : 1);
} }
uint64_t TIFFGetMaxCompressionRatio(TIFF *tif)
{
if (tif->tif_getmaxcompressionratio)
return tif->tif_getmaxcompressionratio(tif);
return 0;
}
/* /*
* Other compression schemes may be registered. Registered * Other compression schemes may be registered. Registered
* schemes can also override the builtin versions provided * schemes can also override the builtin versions provided
@@ -200,7 +222,7 @@ const TIFFCodec *TIFFFindCODEC(uint16_t scheme)
for (c = _TIFFBuiltinCODECS; c->name; c++) for (c = _TIFFBuiltinCODECS; c->name; c++)
if (c->scheme == scheme) if (c->scheme == scheme)
return (c); return (c);
return ((const TIFFCodec *)0); return NULL;
} }
TIFFCodec *TIFFRegisterCODEC(uint16_t scheme, const char *name, TIFFCodec *TIFFRegisterCODEC(uint16_t scheme, const char *name,
@@ -212,9 +234,11 @@ TIFFCodec *TIFFRegisterCODEC(uint16_t scheme, const char *name,
if (cd != NULL) if (cd != NULL)
{ {
char *codec_name;
cd->info = (TIFFCodec *)((uint8_t *)cd + sizeof(codec_t)); cd->info = (TIFFCodec *)((uint8_t *)cd + sizeof(codec_t));
cd->info->name = (char *)((uint8_t *)cd->info + sizeof(TIFFCodec)); codec_name = (char *)((uint8_t *)cd->info + sizeof(TIFFCodec));
strcpy(cd->info->name, name); strcpy(codec_name, name);
cd->info->name = codec_name;
cd->info->scheme = scheme; cd->info->scheme = scheme;
cd->info->init = init; cd->info->init = init;
cd->next = registeredCODECS; cd->next = registeredCODECS;
@@ -247,7 +271,7 @@ void TIFFUnRegisterCODEC(TIFFCodec *c)
} }
/************************************************************************/ /************************************************************************/
/* TIFFGetConfisuredCODECs() */ /* TIFFGetConfiguredCODECs() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -258,7 +282,7 @@ void TIFFUnRegisterCODEC(TIFFCodec *c)
* or NULL if function failed. * or NULL if function failed.
*/ */
TIFFCodec *TIFFGetConfiguredCODECs() TIFFCodec *TIFFGetConfiguredCODECs(void)
{ {
int i = 1; int i = 1;
codec_t *cd; codec_t *cd;
@@ -268,8 +292,8 @@ TIFFCodec *TIFFGetConfiguredCODECs()
for (cd = registeredCODECS; cd; cd = cd->next) for (cd = registeredCODECS; cd; cd = cd->next)
{ {
new_codecs = new_codecs = (TIFFCodec *)_TIFFreallocExt(
(TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec)); NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
if (!new_codecs) if (!new_codecs)
{ {
_TIFFfreeExt(NULL, codecs); _TIFFfreeExt(NULL, codecs);
@@ -283,21 +307,21 @@ TIFFCodec *TIFFGetConfiguredCODECs()
{ {
if (TIFFIsCODECConfigured(c->scheme)) if (TIFFIsCODECConfigured(c->scheme))
{ {
new_codecs = (TIFFCodec *)_TIFFreallocExt(NULL, codecs, new_codecs = (TIFFCodec *)_TIFFreallocExt(
i * sizeof(TIFFCodec)); NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
if (!new_codecs) if (!new_codecs)
{ {
_TIFFfreeExt(NULL, codecs); _TIFFfreeExt(NULL, codecs);
return NULL; return NULL;
} }
codecs = new_codecs; codecs = new_codecs;
_TIFFmemcpy(codecs + i - 1, (const void *)c, sizeof(TIFFCodec)); _TIFFmemcpy(codecs + i - 1, c, sizeof(TIFFCodec));
i++; i++;
} }
} }
new_codecs = new_codecs = (TIFFCodec *)_TIFFreallocExt(
(TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec)); NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
if (!new_codecs) if (!new_codecs)
{ {
_TIFFfreeExt(NULL, codecs); _TIFFfreeExt(NULL, codecs);

View File

@@ -31,6 +31,7 @@
#include "tiffiop.h" #include "tiffiop.h"
#include <float.h> /*--: for Rational2Double */ #include <float.h> /*--: for Rational2Double */
#include <limits.h> #include <limits.h>
#include <math.h>
/* /*
* These are used in the backwards compatibility code... * These are used in the backwards compatibility code...
@@ -50,7 +51,8 @@ static void setByteArray(TIFF *tif, void **vpp, const void *vp, size_t nmemb,
} }
if (vp) if (vp)
{ {
tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL); tmsize_t bytes = _TIFFMultiplySSize(NULL, (tmsize_t)nmemb,
(tmsize_t)elem_size, NULL);
if (bytes) if (bytes)
*vpp = (void *)_TIFFmallocExt(tif, bytes); *vpp = (void *)_TIFFmallocExt(tif, bytes);
if (*vpp) if (*vpp)
@@ -121,7 +123,8 @@ static void setDoubleArrayOneValue(TIFF *tif, double **vpp, double value,
{ {
if (*vpp) if (*vpp)
_TIFFfreeExt(tif, *vpp); _TIFFfreeExt(tif, *vpp);
*vpp = _TIFFmallocExt(tif, nmemb * sizeof(double)); *vpp = (double *)_TIFFmallocExt(tif,
(tmsize_t)nmemb * (tmsize_t)sizeof(double));
if (*vpp) if (*vpp)
{ {
while (nmemb--) while (nmemb--)
@@ -294,7 +297,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
/* /*
* Setup new compression routine state. * Setup new compression routine state.
*/ */
if ((status = TIFFSetCompressionScheme(tif, v)) != 0) if ((status = TIFFSetCompressionScheme(tif, (int)v)) != 0)
td->td_compression = (uint16_t)v; td->td_compression = (uint16_t)v;
else else
status = 0; status = 0;
@@ -402,13 +405,13 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
break; break;
case TIFFTAG_XRESOLUTION: case TIFFTAG_XRESOLUTION:
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if (dblval != dblval || dblval < 0) if (isnan(dblval) || dblval < 0)
goto badvaluedouble; goto badvaluedouble;
td->td_xresolution = _TIFFClampDoubleToFloat(dblval); td->td_xresolution = _TIFFClampDoubleToFloat(dblval);
break; break;
case TIFFTAG_YRESOLUTION: case TIFFTAG_YRESOLUTION:
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if (dblval != dblval || dblval < 0) if (isnan(dblval) || dblval < 0)
goto badvaluedouble; goto badvaluedouble;
td->td_yresolution = _TIFFClampDoubleToFloat(dblval); td->td_yresolution = _TIFFClampDoubleToFloat(dblval);
break; break;
@@ -439,7 +442,12 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap); td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap);
break; break;
case TIFFTAG_COLORMAP: case TIFFTAG_COLORMAP:
v32 = (uint32_t)(1L << td->td_bitspersample); if (td->td_bitspersample >= 32)
{
v = td->td_bitspersample;
goto badvalue;
}
v32 = 1U << td->td_bitspersample;
_TIFFsetShortArrayExt(tif, &td->td_colormap[0], _TIFFsetShortArrayExt(tif, &td->td_colormap[0],
va_arg(ap, uint16_t *), v32); va_arg(ap, uint16_t *), v32);
_TIFFsetShortArrayExt(tif, &td->td_colormap[1], _TIFFsetShortArrayExt(tif, &td->td_colormap[1],
@@ -557,11 +565,17 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
case TIFFTAG_TRANSFERFUNCTION: case TIFFTAG_TRANSFERFUNCTION:
{ {
uint32_t i; uint32_t i;
uint32_t count;
if (td->td_bitspersample >= 32)
{
v = td->td_bitspersample;
goto badvalue;
}
count = 1U << td->td_bitspersample;
v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
for (i = 0; i < v; i++) for (i = 0; i < v; i++)
_TIFFsetShortArrayExt(tif, &td->td_transferfunction[i], _TIFFsetShortArrayExt(tif, &td->td_transferfunction[i],
va_arg(ap, uint16_t *), va_arg(ap, uint16_t *), count);
1U << td->td_bitspersample);
break; break;
} }
case TIFFTAG_REFERENCEBLACKWHITE: case TIFFTAG_REFERENCEBLACKWHITE:
@@ -579,7 +593,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
if (ninksinstring > 0) if (ninksinstring > 0)
{ {
_TIFFsetNString(tif, &td->td_inknames, s, v); _TIFFsetNString(tif, &td->td_inknames, s, v);
td->td_inknameslen = v; td->td_inknameslen = (int)v;
/* Set NumberOfInks to the value ninksinstring */ /* Set NumberOfInks to the value ninksinstring */
if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS)) if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
{ {
@@ -725,7 +739,8 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
new_customValues = (TIFFTagValue *)_TIFFreallocExt( new_customValues = (TIFFTagValue *)_TIFFreallocExt(
tif, td->td_customValues, tif, td->td_customValues,
sizeof(TIFFTagValue) * (td->td_customValueCount + 1)); (tmsize_t)(sizeof(TIFFTagValue) *
(size_t)(td->td_customValueCount + 1)));
if (!new_customValues) if (!new_customValues)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -754,7 +769,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
if (tv_size == 0) if (tv_size == 0)
{ {
status = 0; status = 0;
TIFFErrorExtR(tif, module, "%s: Bad field type %d for \"%s\"", TIFFErrorExtR(tif, module, "%s: Bad field type %u for \"%s\"",
tif->tif_name, fip->field_type, fip->field_name); tif->tif_name, fip->field_type, fip->field_name);
goto end; goto end;
} }
@@ -784,7 +799,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
} }
ma = (uint32_t)len; ma = (uint32_t)len;
} }
tv->count = ma; tv->count = (int)ma;
setByteArray(tif, &tv->value, mb, ma, 1); setByteArray(tif, &tv->value, mb, ma, 1);
} }
else else
@@ -792,9 +807,9 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
if (fip->field_passcount) if (fip->field_passcount)
{ {
if (fip->field_writecount == TIFF_VARIABLE2) if (fip->field_writecount == TIFF_VARIABLE2)
tv->count = (uint32_t)va_arg(ap, uint32_t); tv->count = (int)va_arg(ap, uint32_t);
else else
tv->count = (int)va_arg(ap, int); tv->count = va_arg(ap, int);
} }
else if (fip->field_writecount == TIFF_VARIABLE || else if (fip->field_writecount == TIFF_VARIABLE ||
fip->field_writecount == TIFF_VARIABLE2) fip->field_writecount == TIFF_VARIABLE2)
@@ -808,7 +823,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"%s: Null count for \"%s\" (type " "%s: Null count for \"%s\" (type "
"%d, writecount %d, passcount %d)", "%u, writecount %d, passcount %d)",
tif->tif_name, fip->field_name, tif->tif_name, fip->field_name,
fip->field_type, fip->field_writecount, fip->field_type, fip->field_writecount,
fip->field_passcount); fip->field_passcount);
@@ -845,11 +860,12 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
* 4 or 8 according to fip->set_get_field_type! */ * 4 or 8 according to fip->set_get_field_type! */
_TIFFmemcpy(tv->value, va_arg(ap, void *), _TIFFmemcpy(tv->value, va_arg(ap, void *),
tv->count * tv_size); tv->count * tv_size);
/* Test here for too big values for LONG8, SLONG8 in /* Test here for too big values for LONG8, IFD8, SLONG8 in
* ClassicTIFF and delete custom field from custom list */ * ClassicTIFF and delete custom field from custom list */
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
{ {
if (tv->info->field_type == TIFF_LONG8) if (tv->info->field_type == TIFF_LONG8 ||
tv->info->field_type == TIFF_IFD8)
{ {
uint64_t *pui64 = (uint64_t *)tv->value; uint64_t *pui64 = (uint64_t *)tv->value;
for (int i = 0; i < tv->count; i++) for (int i = 0; i < tv->count; i++)
@@ -858,12 +874,15 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
{ {
TIFFErrorExtR( TIFFErrorExtR(
tif, module, tif, module,
"%s: Bad LONG8 value %" PRIu64 "%s: Bad %s value %" PRIu64
" at %d. array position for \"%s\" tag " " at %d. array position for \"%s\" tag "
"%d in ClassicTIFF. Tag won't be " "%u in ClassicTIFF. Tag won't be "
"written to file", "written to file",
tif->tif_name, pui64[i], i, tif->tif_name,
fip->field_name, tag); (tv->info->field_type == TIFF_LONG8
? "LONG8"
: "IFD8"),
pui64[i], i, fip->field_name, tag);
goto badvalueifd8long8; goto badvalueifd8long8;
} }
} }
@@ -880,7 +899,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
tif, module, tif, module,
"%s: Bad SLONG8 value %" PRIi64 "%s: Bad SLONG8 value %" PRIi64
" at %d. array position for \"%s\" tag " " at %d. array position for \"%s\" tag "
"%d in ClassicTIFF. Tag won't be " "%u in ClassicTIFF. Tag won't be "
"written to file", "written to file",
tif->tif_name, pi64[i], i, tif->tif_name, pi64[i], i,
fip->field_name, tag); fip->field_name, tag);
@@ -948,7 +967,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
TIFFErrorExtR( TIFFErrorExtR(
tif, module, tif, module,
"%s: Bad LONG8 or IFD8 value %" PRIu64 "%s: Bad LONG8 or IFD8 value %" PRIu64
" for \"%s\" tag %d in ClassicTIFF. Tag " " for \"%s\" tag %u in ClassicTIFF. Tag "
"won't be written to file", "won't be written to file",
tif->tif_name, v2, fip->field_name, tag); tif->tif_name, v2, fip->field_name, tag);
goto badvalueifd8long8; goto badvalueifd8long8;
@@ -967,7 +986,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
TIFFErrorExtR( TIFFErrorExtR(
tif, module, tif, module,
"%s: Bad SLONG8 value %" PRIi64 "%s: Bad SLONG8 value %" PRIi64
" for \"%s\" tag %d in ClassicTIFF. Tag " " for \"%s\" tag %u in ClassicTIFF. Tag "
"won't be written to file", "won't be written to file",
tif->tif_name, v2, fip->field_name, tag); tif->tif_name, v2, fip->field_name, tag);
goto badvalueifd8long8; goto badvalueifd8long8;
@@ -1018,6 +1037,8 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
_TIFFmemcpy(val, &v2, tv_size); _TIFFmemcpy(val, &v2, tv_size);
} }
break; break;
case TIFF_NOTYPE:
case TIFF_ASCII:
default: default:
_TIFFmemset(val, 0, tv_size); _TIFFmemset(val, 0, tv_size);
status = 0; status = 0;
@@ -1345,7 +1366,7 @@ static int _TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
*va_arg(ap, uint16_t *) = *va_arg(ap, uint16_t *) =
(td->td_extrasamples == 1 && (td->td_extrasamples == 1 && td->td_sampleinfo &&
td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
break; break;
case TIFFTAG_EXTRASAMPLES: case TIFFTAG_EXTRASAMPLES:
@@ -1376,6 +1397,8 @@ static int _TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
case SAMPLEFORMAT_VOID: case SAMPLEFORMAT_VOID:
*va_arg(ap, uint16_t *) = DATATYPE_VOID; *va_arg(ap, uint16_t *) = DATATYPE_VOID;
break; break;
default:
break;
} }
break; break;
case TIFFTAG_SAMPLEFORMAT: case TIFFTAG_SAMPLEFORMAT:
@@ -1562,6 +1585,8 @@ static int _TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
*va_arg(ap, double *) = *(double *)val; *va_arg(ap, double *) = *(double *)val;
ret_val = 1; ret_val = 1;
break; break;
case TIFF_NOTYPE:
case TIFF_ASCII:
default: default:
ret_val = 0; ret_val = 0;
break; break;
@@ -1613,6 +1638,21 @@ int TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
} \ } \
} }
/*
* Reset tif->tif_dir structure to zero and
* initialize some IFD strile counter and index parameters.
*/
void _TIFFResetTifDirAndInitStrileCounters(TIFFDirectory *td)
{
_TIFFmemset(td, 0, sizeof(*td));
td->td_curstrip = NOSTRIP; /* invalid strip = NOSTRIP */
td->td_row = (uint32_t)-1; /* read/write pre-increment */
td->td_col = (uint32_t)-1; /* read/write pre-increment */
td->td_scanlinesize = 0; /* initialize to zero */
td->td_curtile = NOTILE; /* invalid tile = NOTILE */
td->td_tilesize = (tmsize_t)-1; /* invalidate tilezize */
}
/* /*
* Release storage associated with a directory. * Release storage associated with a directory.
*/ */
@@ -1664,6 +1704,7 @@ void TIFFFreeDirectory(TIFF *tif)
tif->tif_dir.td_dirdatasize_Noffsets = 0; tif->tif_dir.td_dirdatasize_Noffsets = 0;
} }
tif->tif_dir.td_iswrittentofile = FALSE; tif->tif_dir.td_iswrittentofile = FALSE;
/* Note: tif->tif_dir structure is set to zero in TIFFDefaultDirectory() */
} }
#undef CleanupField #undef CleanupField
@@ -1694,10 +1735,7 @@ int TIFFCreateDirectory(TIFF *tif)
tif->tif_diroff = 0; tif->tif_diroff = 0;
tif->tif_nextdiroff = 0; tif->tif_nextdiroff = 0;
tif->tif_curoff = 0; tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_dir.td_iswrittentofile = FALSE; tif->tif_dir.td_iswrittentofile = FALSE;
return 0; return 0;
} }
@@ -1717,15 +1755,12 @@ int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
tif->tif_diroff = 0; tif->tif_diroff = 0;
tif->tif_nextdiroff = 0; tif->tif_nextdiroff = 0;
tif->tif_curoff = 0; tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
/* invalidate directory index */ /* invalidate directory index */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
/* invalidate IFD loop lists */ /* invalidate IFD loop lists */
_TIFFCleanupIFDOffsetAndNumberMaps(tif); _TIFFCleanupIFDOffsetAndNumberMaps(tif);
/* To be able to return from SubIFD or custom-IFD to main-IFD */ /* To be able to return from SubIFD or custom-IFD to main-IFD */
tif->tif_setdirectory_force_absolute = TRUE; tif->tif_setdirectory_force_absolute = TRUE;
return 0; return 0;
} }
@@ -1751,13 +1786,14 @@ int TIFFCreateGPSDirectory(TIFF *tif)
*/ */
int TIFFDefaultDirectory(TIFF *tif) int TIFFDefaultDirectory(TIFF *tif)
{ {
register TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
const TIFFFieldArray *tiffFieldArray; const TIFFFieldArray *tiffFieldArray;
tiffFieldArray = _TIFFGetFields(); tiffFieldArray = _TIFFGetFields();
_TIFFSetupFields(tif, tiffFieldArray); _TIFFSetupFields(tif, tiffFieldArray);
/* Reset tif->tif_dir structure to zero and
_TIFFmemset(td, 0, sizeof(*td)); * initialize some IFD strile counter and index parameters. */
_TIFFResetTifDirAndInitStrileCounters(td);
td->td_fillorder = FILLORDER_MSB2LSB; td->td_fillorder = FILLORDER_MSB2LSB;
td->td_bitspersample = 1; td->td_bitspersample = 1;
td->td_threshholding = THRESHHOLD_BILEVEL; td->td_threshholding = THRESHHOLD_BILEVEL;
@@ -1860,10 +1896,8 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
tmsize_t poffa, poffb, poffc, poffd; tmsize_t poffa, poffb, poffc, poffd;
uint16_t dircount; uint16_t dircount;
uint32_t nextdir32; uint32_t nextdir32;
poffa = (tmsize_t)poff; if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint16_t) ||
poffb = poffa + sizeof(uint16_t); poff > (uint64_t)tif->tif_size - sizeof(uint16_t))
if (((uint64_t)poffa != poff) || (poffb < poffa) ||
(poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count", "%s:%d: %s: Error fetching directory count",
@@ -1871,13 +1905,20 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
*nextdiroff = 0; *nextdiroff = 0;
return (0); return (0);
} }
poffa = (tmsize_t)poff;
poffb = poffa + (tmsize_t)sizeof(uint16_t);
_TIFFmemcpy(&dircount, tif->tif_base + poffa, sizeof(uint16_t)); _TIFFmemcpy(&dircount, tif->tif_base + poffa, sizeof(uint16_t));
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&dircount); TIFFSwabShort(&dircount);
if (poffb >
TIFF_TMSIZE_T_MAX - dircount * 12 - (tmsize_t)sizeof(uint32_t))
{
TIFFErrorExtR(tif, module, "Error fetching directory link");
return (0);
}
poffc = poffb + dircount * 12; poffc = poffb + dircount * 12;
poffd = poffc + sizeof(uint32_t); poffd = poffc + (tmsize_t)sizeof(uint32_t);
if ((poffc < poffb) || (poffc < dircount * 12) || (poffd < poffc) || if (poffd > tif->tif_size)
(poffd < (tmsize_t)sizeof(uint32_t)) || (poffd > tif->tif_size))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
return (0); return (0);
@@ -1893,7 +1934,6 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
{ {
tmsize_t poffa, poffb, poffc, poffd; tmsize_t poffa, poffb, poffc, poffd;
uint64_t dircount64; uint64_t dircount64;
uint16_t dircount16;
if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t)) if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -1902,7 +1942,7 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
return (0); return (0);
} }
poffa = (tmsize_t)poff; poffa = (tmsize_t)poff;
poffb = poffa + sizeof(uint64_t); poffb = poffa + (tmsize_t)sizeof(uint64_t);
if (poffb > tif->tif_size) if (poffb > tif->tif_size)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -1919,15 +1959,14 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
"Sanity check on directory count failed"); "Sanity check on directory count failed");
return (0); return (0);
} }
dircount16 = (uint16_t)dircount64; if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount64 * 20) -
if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount16 * 20) -
(tmsize_t)sizeof(uint64_t)) (tmsize_t)sizeof(uint64_t))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
return (0); return (0);
} }
poffc = poffb + dircount16 * 20; poffc = poffb + (tmsize_t)(dircount64 * 20);
poffd = poffc + sizeof(uint64_t); poffd = poffc + (tmsize_t)sizeof(uint64_t);
if (poffd > tif->tif_size) if (poffd > tif->tif_size)
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -1957,9 +1996,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&dircount); TIFFSwabShort(&dircount);
if (off != NULL) if (off != NULL)
*off = TIFFSeekFile(tif, dircount * 12, SEEK_CUR); *off = TIFFSeekFile(tif, dircount * 12U, SEEK_CUR);
else else
(void)TIFFSeekFile(tif, dircount * 12, SEEK_CUR); (void)TIFFSeekFile(tif, dircount * 12U, SEEK_CUR);
if (!ReadOK(tif, &nextdir32, sizeof(uint32_t))) if (!ReadOK(tif, &nextdir32, sizeof(uint32_t)))
{ {
TIFFErrorExtR(tif, module, "%s: Error fetching directory link", TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
@@ -1973,7 +2012,6 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
else else
{ {
uint64_t dircount64; uint64_t dircount64;
uint16_t dircount16;
if (!SeekOK(tif, *nextdiroff) || if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount64, sizeof(uint64_t))) !ReadOK(tif, &dircount64, sizeof(uint64_t)))
{ {
@@ -1991,11 +2029,10 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
__FILE__, __LINE__, tif->tif_name); __FILE__, __LINE__, tif->tif_name);
return (0); return (0);
} }
dircount16 = (uint16_t)dircount64;
if (off != NULL) if (off != NULL)
*off = TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR); *off = TIFFSeekFile(tif, dircount64 * 20, SEEK_CUR);
else else
(void)TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR); (void)TIFFSeekFile(tif, dircount64 * 20, SEEK_CUR);
if (!ReadOK(tif, nextdiroff, sizeof(uint64_t))) if (!ReadOK(tif, nextdiroff, sizeof(uint64_t)))
{ {
TIFFErrorExtR(tif, module, "%s: Error fetching directory link", TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
@@ -2354,8 +2391,6 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
tif->tif_nextdiroff = 0; /* next write must be at end */ tif->tif_nextdiroff = 0; /* next write must be at end */
tif->tif_lastdiroff = 0; /* will be updated on next link */ tif->tif_lastdiroff = 0; /* will be updated on next link */
tif->tif_curoff = 0; tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
if (tif->tif_curdircount > 0) if (tif->tif_curdircount > 0)
tif->tif_curdircount--; tif->tif_curdircount--;

View File

@@ -104,6 +104,16 @@ typedef struct
uint16_t td_halftonehints[2]; uint16_t td_halftonehints[2];
uint16_t td_extrasamples; uint16_t td_extrasamples;
uint16_t *td_sampleinfo; uint16_t *td_sampleinfo;
/* strip support */
uint32_t td_row; /* current scanline */
uint32_t td_curstrip; /* current strip for read/write */
tmsize_t td_scanlinesize; /* # of bytes in a scanline */
#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
/* tiling support */
uint32_t td_col; /* current column (offset by row too) */
uint32_t td_curtile; /* current tile for read/write */
tmsize_t td_tilesize; /* # of bytes in a tile */
#define NOTILE ((uint32_t)(-1)) /* undefined state */
/* even though the name is misleading, td_stripsperimage is the number /* even though the name is misleading, td_stripsperimage is the number
* of striles (=strips or tiles) per plane, and td_nstrips the total * of striles (=strips or tiles) per plane, and td_nstrips the total
* number of striles */ * number of striles */
@@ -164,6 +174,8 @@ typedef struct
entries. */ entries. */
} TIFFDirectory; } TIFFDirectory;
extern void _TIFFResetTifDirAndInitStrileCounters(TIFFDirectory *td);
/* /*
* Field flags used to indicate fields that have been set in a directory, and * Field flags used to indicate fields that have been set in a directory, and
* to reference fields when manipulating a directory. * to reference fields when manipulating a directory.
@@ -231,7 +243,7 @@ typedef struct
#define FIELD_LAST (32 * FIELDSET_ITEMS - 1) #define FIELD_LAST (32 * FIELDSET_ITEMS - 1)
#define BITn(n) (((uint32_t)1L) << ((n)&0x1f)) #define BITn(n) (1U << ((n) & 0x1f))
#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n) / 32]) #define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n) / 32])
#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) #define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field))
#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) #define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field))
@@ -340,7 +352,7 @@ extern "C"
unsigned short field_bit; /* bit in fieldsset bit vector */ unsigned short field_bit; /* bit in fieldsset bit vector */
unsigned char field_oktochange; /* if true, can change while writing */ unsigned char field_oktochange; /* if true, can change while writing */
unsigned char field_passcount; /* if true, pass dir count on set */ unsigned char field_passcount; /* if true, pass dir count on set */
char *field_name; /* ASCII name */ const char *field_name; /* ASCII name */
TIFFFieldArray *field_subfields; /* if field points to child ifds, child TIFFFieldArray *field_subfields; /* if field points to child ifds, child
ifd field definition array */ ifd field definition array */
}; };

View File

@@ -40,17 +40,47 @@
* values accordingly. * values accordingly.
*/ */
/* const object should be initialized */ /* Forward declarations - definition follows after field arrays.
#ifdef _MSC_VER * Note: In C, we can forward declare static const objects and define them
* later. In C++, we need extern for the declaration, then define without
* extern. Since these are only used within this file via pointers, we use a
* workaround that works in both C and C++: declare as extern here, define as
* static later, but actually we need a different approach for C++
* compatibility.
*
* For C/C++ compatibility, we define a simple struct that holds the pointer
* and initialize it after the arrays are defined.
*/
#ifdef __cplusplus
/* C++ doesn't allow forward declaration of const objects, so we use extern */
extern const TIFFFieldArray tiffFieldArray;
extern const TIFFFieldArray exifFieldArray;
extern const TIFFFieldArray gpsFieldArray;
#else
/* C allows forward declaration of const objects, but C++ doesn't.
* We disable the C++-compat warning for this section since these circular
* dependencies are unavoidable with static initialization. */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++-compat"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++-compat"
#elif defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4132) #pragma warning(disable : 4132)
#endif #endif
static const TIFFFieldArray tiffFieldArray; static const TIFFFieldArray tiffFieldArray;
static const TIFFFieldArray exifFieldArray; static const TIFFFieldArray exifFieldArray;
static const TIFFFieldArray gpsFieldArray; static const TIFFFieldArray gpsFieldArray;
#ifdef _MSC_VER #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#endif
/*--: Rational2Double: -- /*--: Rational2Double: --
* The Rational2Double upgraded libtiff functionality allows the definition and * The Rational2Double upgraded libtiff functionality allows the definition and
* achievement of true double-precision accuracy for TIFF tags of RATIONAL type * achievement of true double-precision accuracy for TIFF tags of RATIONAL type
@@ -152,9 +182,9 @@ static const TIFFField tiffFields[] = {
/*--: EXIFIFD and GPSIFD specified as TIFF_LONG by Aware-Systems and not TIFF_IFD8 as in original LibTiff. However, for IFD-like tags, /*--: EXIFIFD and GPSIFD specified as TIFF_LONG by Aware-Systems and not TIFF_IFD8 as in original LibTiff. However, for IFD-like tags,
* libtiff uses the data type TIFF_IFD8 in tiffFields[]-tag definition combined with a special handling procedure in order to write either * libtiff uses the data type TIFF_IFD8 in tiffFields[]-tag definition combined with a special handling procedure in order to write either
* a 32-bit value and the TIFF_IFD type-id into ClassicTIFF files or a 64-bit value and the TIFF_IFD8 type-id into BigTIFF files. */ * a 32-bit value and the TIFF_IFD type-id into ClassicTIFF files or a 64-bit value and the TIFF_IFD8 type-id into BigTIFF files. */
{TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, FIELD_CUSTOM, 1, 0, "EXIFIFDOffset", (TIFFFieldArray *)&exifFieldArray}, {TIFFTAG_EXIFIFD, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64, FIELD_CUSTOM, 1, 0, "EXIFIFDOffset", (TIFFFieldArray *)&exifFieldArray},
{TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, FIELD_CUSTOM, 1, 1, "ICC Profile", NULL}, {TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, FIELD_CUSTOM, 1, 1, "ICC Profile", NULL},
{TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, FIELD_CUSTOM, 1, 0, "GPSIFDOffset", (TIFFFieldArray *)&gpsFieldArray}, {TIFFTAG_GPSIFD, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64, FIELD_CUSTOM, 1, 0, "GPSIFDOffset", (TIFFFieldArray *)&gpsFieldArray},
{TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL}, {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL},
{TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL}, {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL},
{TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL}, {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL},
@@ -479,12 +509,36 @@ static const TIFFField gpsFields[] = {
{GPSTAG_GPSHPOSITIONINGERROR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, FIELD_CUSTOM, 1, 0, "HorizontalPositioningError", NULL}}; {GPSTAG_GPSHPOSITIONINGERROR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, FIELD_CUSTOM, 1, 0, "HorizontalPositioningError", NULL}};
/* clang-format on */ /* was off for better readability of tag comments */ /* clang-format on */ /* was off for better readability of tag comments */
#ifdef __cplusplus
/* In C++, the forward declaration used extern, so definitions must not be
* static */
const TIFFFieldArray tiffFieldArray = {
tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields};
const TIFFFieldArray exifFieldArray = {tfiatExif, 0, TIFFArrayCount(exifFields),
(TIFFField *)exifFields};
const TIFFFieldArray gpsFieldArray = {tfiatGps, 0, TIFFArrayCount(gpsFields),
(TIFFField *)gpsFields};
#else
/* Suppress C++-compat warning for the definitions as well */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++-compat"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++-compat"
#endif
static const TIFFFieldArray tiffFieldArray = { static const TIFFFieldArray tiffFieldArray = {
tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields}; tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields};
static const TIFFFieldArray exifFieldArray = { static const TIFFFieldArray exifFieldArray = {
tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField *)exifFields}; tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField *)exifFields};
static const TIFFFieldArray gpsFieldArray = { static const TIFFFieldArray gpsFieldArray = {
tfiatGps, 0, TIFFArrayCount(gpsFields), (TIFFField *)gpsFields}; tfiatGps, 0, TIFFArrayCount(gpsFields), (TIFFField *)gpsFields};
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif
/* /*
* We have our own local lfind() equivalent to avoid subtle differences * We have our own local lfind() equivalent to avoid subtle differences
@@ -523,7 +577,7 @@ void _TIFFSetupFields(TIFF *tif, const TIFFFieldArray *fieldarray)
{ {
if (fld->field_bit == FIELD_CUSTOM && TIFFFieldIsAnonymous(fld)) if (fld->field_bit == FIELD_CUSTOM && TIFFFieldIsAnonymous(fld))
{ {
_TIFFfreeExt(tif, fld->field_name); _TIFFfreeExt(tif, (void *)fld->field_name);
/* caution: tif_fields[i] must not be the beginning of a /* caution: tif_fields[i] must not be the beginning of a
* fields-array. Otherwise the following tags are also freed * fields-array. Otherwise the following tags are also freed
* with the first free(). * with the first free().
@@ -579,22 +633,26 @@ int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32_t n)
tif->tif_foundfield = NULL; tif->tif_foundfield = NULL;
TIFFField **tif_newfields = NULL;
if (tif->tif_fields && tif->tif_nfields > 0) if (tif->tif_fields && tif->tif_nfields > 0)
{ {
tif->tif_fields = (TIFFField **)_TIFFCheckRealloc( tif_newfields = (TIFFField **)_TIFFCheckRealloc(
tif, tif->tif_fields, (tif->tif_nfields + n), sizeof(TIFFField *), tif, tif->tif_fields, (tmsize_t)tif->tif_nfields + n,
reason); (tmsize_t)sizeof(TIFFField *), reason);
} }
else else
{ {
tif->tif_fields = tif_newfields =
(TIFFField **)_TIFFCheckMalloc(tif, n, sizeof(TIFFField *), reason); (TIFFField **)_TIFFCheckMalloc(tif, n, sizeof(TIFFField *), reason);
} }
if (!tif->tif_fields) if (!tif_newfields)
{ {
tif->tif_nfields = 0;
TIFFErrorExtR(tif, module, "Failed to allocate fields array"); TIFFErrorExtR(tif, module, "Failed to allocate fields array");
return 0; return 0;
} }
tif->tif_fields = tif_newfields;
/* tp = tif->tif_fields + tif->tif_nfields; */ /* tp = tif->tif_fields + tif->tif_nfields; */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@@ -612,7 +670,7 @@ int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32_t n)
/* Sort the field info by tag number */ /* Sort the field info by tag number */
qsort(tif->tif_fields, tif->tif_nfields, sizeof(TIFFField *), tagCompare); qsort(tif->tif_fields, tif->tif_nfields, sizeof(TIFFField *), tagCompare);
return n; return (int)n;
} }
void _TIFFPrintFieldInfo(TIFF *tif, FILE *fd) void _TIFFPrintFieldInfo(TIFF *tif, FILE *fd)
@@ -623,7 +681,7 @@ void _TIFFPrintFieldInfo(TIFF *tif, FILE *fd)
for (i = 0; i < tif->tif_nfields; i++) for (i = 0; i < tif->tif_nfields; i++)
{ {
const TIFFField *fip = tif->tif_fields[i]; const TIFFField *fip = tif->tif_fields[i];
fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n", fprintf(fd, "field[%2d] %5lu, %2d, %2d, %u, %2d, %5s, %5s, %s\n",
(int)i, (unsigned long)fip->field_tag, fip->field_readcount, (int)i, (unsigned long)fip->field_tag, fip->field_readcount,
fip->field_writecount, fip->field_type, fip->field_bit, fip->field_writecount, fip->field_type, fip->field_bit,
fip->field_oktochange ? "TRUE" : "FALSE", fip->field_oktochange ? "TRUE" : "FALSE",
@@ -787,6 +845,34 @@ int TIFFFieldSetGetCountSize(const TIFFField *fip)
case TIFF_SETGET_C32_DOUBLE: case TIFF_SETGET_C32_DOUBLE:
case TIFF_SETGET_C32_IFD8: case TIFF_SETGET_C32_IFD8:
return 4; return 4;
case TIFF_SETGET_UNDEFINED:
case TIFF_SETGET_ASCII:
case TIFF_SETGET_UINT8:
case TIFF_SETGET_SINT8:
case TIFF_SETGET_UINT16:
case TIFF_SETGET_SINT16:
case TIFF_SETGET_UINT32:
case TIFF_SETGET_SINT32:
case TIFF_SETGET_UINT64:
case TIFF_SETGET_SINT64:
case TIFF_SETGET_FLOAT:
case TIFF_SETGET_DOUBLE:
case TIFF_SETGET_IFD8:
case TIFF_SETGET_INT:
case TIFF_SETGET_UINT16_PAIR:
case TIFF_SETGET_C0_ASCII:
case TIFF_SETGET_C0_UINT8:
case TIFF_SETGET_C0_SINT8:
case TIFF_SETGET_C0_UINT16:
case TIFF_SETGET_C0_SINT16:
case TIFF_SETGET_C0_UINT32:
case TIFF_SETGET_C0_SINT32:
case TIFF_SETGET_C0_UINT64:
case TIFF_SETGET_C0_SINT64:
case TIFF_SETGET_C0_FLOAT:
case TIFF_SETGET_C0_DOUBLE:
case TIFF_SETGET_C0_IFD8:
case TIFF_SETGET_OTHER:
default: default:
return 0; return 0;
} }
@@ -794,7 +880,8 @@ int TIFFFieldSetGetCountSize(const TIFFField *fip)
const TIFFField *TIFFFindField(TIFF *tif, uint32_t tag, TIFFDataType dt) const TIFFField *TIFFFindField(TIFF *tif, uint32_t tag, TIFFDataType dt)
{ {
TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, NULL, NULL}; TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, TIFF_SETGET_UNDEFINED,
0, 0, 0, NULL, NULL};
TIFFField *pkey = &key; TIFFField *pkey = &key;
const TIFFField **ret; const TIFFField **ret;
if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag && if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
@@ -818,7 +905,8 @@ const TIFFField *TIFFFindField(TIFF *tif, uint32_t tag, TIFFDataType dt)
static const TIFFField *_TIFFFindFieldByName(TIFF *tif, const char *field_name, static const TIFFField *_TIFFFindFieldByName(TIFF *tif, const char *field_name,
TIFFDataType dt) TIFFDataType dt)
{ {
TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, NULL, NULL}; TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, TIFF_SETGET_UNDEFINED,
0, 0, 0, NULL, NULL};
TIFFField *pkey = &key; TIFFField *pkey = &key;
const TIFFField **ret; const TIFFField **ret;
if (tif->tif_foundfield && if (tif->tif_foundfield &&
@@ -876,7 +964,10 @@ int TIFFFieldReadCount(const TIFFField *fip) { return fip->field_readcount; }
int TIFFFieldWriteCount(const TIFFField *fip) { return fip->field_writecount; } int TIFFFieldWriteCount(const TIFFField *fip) { return fip->field_writecount; }
int TIFFFieldIsAnonymous(const TIFFField *fip) { return fip->field_anonymous; } int TIFFFieldIsAnonymous(const TIFFField *fip)
{
return (int)fip->field_anonymous;
}
const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag, const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag,
TIFFDataType dt) TIFFDataType dt)
@@ -954,6 +1045,7 @@ TIFFField *_TIFFCreateAnonField(TIFF *tif, uint32_t tag,
case TIFF_SLONG8: case TIFF_SLONG8:
fld->set_get_field_type = TIFF_SETGET_C32_SINT64; fld->set_get_field_type = TIFF_SETGET_C32_SINT64;
break; break;
case TIFF_NOTYPE:
default: default:
fld->set_get_field_type = TIFF_SETGET_UNDEFINED; fld->set_get_field_type = TIFF_SETGET_UNDEFINED;
break; break;
@@ -961,8 +1053,8 @@ TIFFField *_TIFFCreateAnonField(TIFF *tif, uint32_t tag,
fld->field_bit = FIELD_CUSTOM; fld->field_bit = FIELD_CUSTOM;
fld->field_oktochange = TRUE; fld->field_oktochange = TRUE;
fld->field_passcount = TRUE; fld->field_passcount = TRUE;
fld->field_name = (char *)_TIFFmallocExt(tif, 32); char *field_name_buf = (char *)_TIFFmallocExt(tif, 32);
if (fld->field_name == NULL) if (field_name_buf == NULL)
{ {
_TIFFfreeExt(tif, fld); _TIFFfreeExt(tif, fld);
return NULL; return NULL;
@@ -975,7 +1067,8 @@ TIFFField *_TIFFCreateAnonField(TIFF *tif, uint32_t tag,
* Update: * Update:
* This special sign is replaced by fld->field_anonymous flag. * This special sign is replaced by fld->field_anonymous flag.
*/ */
(void)snprintf(fld->field_name, 32, "Tag %d", (int)tag); (void)snprintf(field_name_buf, 32, "Tag %d", (int)tag);
fld->field_name = field_name_buf;
return fld; return fld;
} }
@@ -1025,6 +1118,7 @@ static TIFFSetGetFieldType _TIFFSetGetType(TIFFDataType type, short count,
return TIFF_SETGET_UINT64; return TIFF_SETGET_UINT64;
case TIFF_SLONG8: case TIFF_SLONG8:
return TIFF_SETGET_SINT64; return TIFF_SETGET_SINT64;
case TIFF_NOTYPE:
default: default:
return TIFF_SETGET_UNDEFINED; return TIFF_SETGET_UNDEFINED;
} }
@@ -1062,6 +1156,7 @@ static TIFFSetGetFieldType _TIFFSetGetType(TIFFDataType type, short count,
return TIFF_SETGET_C0_UINT64; return TIFF_SETGET_C0_UINT64;
case TIFF_SLONG8: case TIFF_SLONG8:
return TIFF_SETGET_C0_SINT64; return TIFF_SETGET_C0_SINT64;
case TIFF_NOTYPE:
default: default:
return TIFF_SETGET_UNDEFINED; return TIFF_SETGET_UNDEFINED;
} }
@@ -1099,6 +1194,7 @@ static TIFFSetGetFieldType _TIFFSetGetType(TIFFDataType type, short count,
return TIFF_SETGET_C16_UINT64; return TIFF_SETGET_C16_UINT64;
case TIFF_SLONG8: case TIFF_SLONG8:
return TIFF_SETGET_C16_SINT64; return TIFF_SETGET_C16_SINT64;
case TIFF_NOTYPE:
default: default:
return TIFF_SETGET_UNDEFINED; return TIFF_SETGET_UNDEFINED;
} }
@@ -1136,6 +1232,7 @@ static TIFFSetGetFieldType _TIFFSetGetType(TIFFDataType type, short count,
return TIFF_SETGET_C32_UINT64; return TIFF_SETGET_C32_UINT64;
case TIFF_SLONG8: case TIFF_SLONG8:
return TIFF_SETGET_C32_SINT64; return TIFF_SETGET_C32_SINT64;
case TIFF_NOTYPE:
default: default:
return TIFF_SETGET_UNDEFINED; return TIFF_SETGET_UNDEFINED;
} }
@@ -1152,22 +1249,25 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
size_t nfields; size_t nfields;
uint32_t i; uint32_t i;
TIFFFieldArray *tif_newfieldscompat = NULL;
if (tif->tif_nfieldscompat > 0) if (tif->tif_nfieldscompat > 0)
{ {
tif->tif_fieldscompat = (TIFFFieldArray *)_TIFFCheckRealloc( tif_newfieldscompat = (TIFFFieldArray *)_TIFFCheckRealloc(
tif, tif->tif_fieldscompat, tif->tif_nfieldscompat + 1, tif, tif->tif_fieldscompat, (tmsize_t)tif->tif_nfieldscompat + 1,
sizeof(TIFFFieldArray), reason); (tmsize_t)sizeof(TIFFFieldArray), reason);
} }
else else
{ {
tif->tif_fieldscompat = (TIFFFieldArray *)_TIFFCheckMalloc( tif_newfieldscompat = (TIFFFieldArray *)_TIFFCheckMalloc(
tif, 1, sizeof(TIFFFieldArray), reason); tif, 1, sizeof(TIFFFieldArray), reason);
} }
if (!tif->tif_fieldscompat) if (!tif_newfieldscompat)
{ {
TIFFErrorExtR(tif, module, "Failed to allocate fields array"); TIFFErrorExtR(tif, module, "Failed to allocate fields array");
return -1; return -1;
} }
tif->tif_fieldscompat = tif_newfieldscompat;
nfields = tif->tif_nfieldscompat++; nfields = tif->tif_nfieldscompat++;
tif->tif_fieldscompat[nfields].type = tfiatOther; tif->tif_fieldscompat[nfields].type = tfiatOther;
@@ -1309,6 +1409,8 @@ int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag)
case TIFFTAG_JPEGPROC: case TIFFTAG_JPEGPROC:
case TIFFTAG_JPEGRESTARTINTERVAL: case TIFFTAG_JPEGRESTARTINTERVAL:
return 1; return 1;
default:
break;
} }
break; break;
case COMPRESSION_CCITTRLE: case COMPRESSION_CCITTRLE:
@@ -1329,6 +1431,8 @@ int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag)
if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
return 1; return 1;
break; break;
default:
break;
} }
break; break;
case COMPRESSION_JBIG: case COMPRESSION_JBIG:
@@ -1359,6 +1463,8 @@ int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag)
if (tag == TIFFTAG_LERC_PARAMETERS) if (tag == TIFFTAG_LERC_PARAMETERS)
return 1; return 1;
break; break;
default:
break;
} }
return 0; return 0;
} }

View File

@@ -597,7 +597,7 @@ TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value)
err = TIFFReadDirEntryCheckRangeSshortShort(m); err = TIFFReadDirEntryCheckRangeSshortShort(m);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
return (err); return (err);
*value = (uint16_t)m; *value = (int16_t)m;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
case TIFF_SSHORT: case TIFF_SSHORT:
@@ -695,6 +695,7 @@ TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value)
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
case TIFF_LONG: case TIFF_LONG:
case TIFF_IFD:
TIFFReadDirEntryCheckedLong(tif, direntry, value); TIFFReadDirEntryCheckedLong(tif, direntry, value);
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
case TIFF_SLONG: case TIFF_SLONG:
@@ -708,6 +709,7 @@ TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value)
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_IFD8:
{ {
uint64_t m; uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m); err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
@@ -857,6 +859,7 @@ TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
case TIFF_LONG: case TIFF_LONG:
case TIFF_IFD:
{ {
uint32_t m; uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m); TIFFReadDirEntryCheckedLong(tif, direntry, &m);
@@ -874,6 +877,7 @@ TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_IFD8:
err = TIFFReadDirEntryCheckedLong8(tif, direntry, value); err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
return (err); return (err);
case TIFF_SLONG8: case TIFF_SLONG8:
@@ -1058,7 +1062,7 @@ TIFFReadDirEntryFloat(TIFF *tif, TIFFDirEntry *direntry, float *value)
err = TIFFReadDirEntryCheckedDouble(tif, direntry, &m); err = TIFFReadDirEntryCheckedDouble(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
return (err); return (err);
if ((m > FLT_MAX) || (m < -FLT_MAX)) if ((m > (double)FLT_MAX) || (m < -(double)FLT_MAX))
return (TIFFReadDirEntryErrRange); return (TIFFReadDirEntryErrRange);
*value = (float)m; *value = (float)m;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
@@ -1237,6 +1241,8 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(TIFF *tif,
*pdest = new_dest; *pdest = new_dest;
bytes_read = TIFFReadFile(tif, (char *)*pdest + already_read, to_read); bytes_read = TIFFReadFile(tif, (char *)*pdest + already_read, to_read);
if (bytes_read < 0)
return TIFFReadDirEntryErrIo;
already_read += bytes_read; already_read += bytes_read;
if (bytes_read != to_read) if (bytes_read != to_read)
{ {
@@ -1260,7 +1266,7 @@ TIFFReadDirEntryArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
void *data; void *data;
uint64_t target_count64; uint64_t target_count64;
int original_datasize_clamped; int original_datasize_clamped;
typesize = TIFFDataWidth(direntry->tdir_type); typesize = TIFFDataWidth((TIFFDataType)direntry->tdir_type);
target_count64 = target_count64 =
(direntry->tdir_count > maxcount) ? maxcount : direntry->tdir_count; (direntry->tdir_count > maxcount) ? maxcount : direntry->tdir_count;
@@ -1284,13 +1290,13 @@ TIFFReadDirEntryArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
* in either the current data type or the dest data type. This also * in either the current data type or the dest data type. This also
* avoids problems with overflow of tmsize_t on 32bit systems. * avoids problems with overflow of tmsize_t on 32bit systems.
*/ */
if ((uint64_t)(MAX_SIZE_TAG_DATA / typesize) < target_count64) if ((uint64_t)(MAX_SIZE_TAG_DATA / (unsigned int)typesize) < target_count64)
return (TIFFReadDirEntryErrSizesan); return (TIFFReadDirEntryErrSizesan);
if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64) if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64)
return (TIFFReadDirEntryErrSizesan); return (TIFFReadDirEntryErrSizesan);
*count = (uint32_t)target_count64; *count = (uint32_t)target_count64;
datasize = (*count) * typesize; datasize = (uint32_t)(*count) * (unsigned int)typesize;
assert((tmsize_t)datasize > 0); assert((tmsize_t)datasize > 0);
if (datasize > 100 * 1024 * 1024) if (datasize > 100 * 1024 * 1024)
@@ -1440,6 +1446,8 @@ TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value)
*value = (uint8_t *)origdata; *value = (uint8_t *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
default:
break;
} }
data = (uint8_t *)_TIFFmallocExt(tif, count); data = (uint8_t *)_TIFFmallocExt(tif, count);
if (data == 0) if (data == 0)
@@ -1557,6 +1565,8 @@ TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -1620,6 +1630,8 @@ TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value)
case TIFF_SBYTE: case TIFF_SBYTE:
*value = (int8_t *)origdata; *value = (int8_t *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (int8_t *)_TIFFmallocExt(tif, count); data = (int8_t *)_TIFFmallocExt(tif, count);
if (data == 0) if (data == 0)
@@ -1737,6 +1749,8 @@ TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -1802,6 +1816,8 @@ TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value)
*value = (uint16_t *)origdata; *value = (uint16_t *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
default:
break;
} }
data = (uint16_t *)_TIFFmallocExt(tif, count * 2); data = (uint16_t *)_TIFFmallocExt(tif, count * 2);
if (data == 0) if (data == 0)
@@ -1910,6 +1926,8 @@ TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -1975,6 +1993,8 @@ TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value)
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfShort((uint16_t *)(*value), count); TIFFSwabArrayOfShort((uint16_t *)(*value), count);
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (int16_t *)_TIFFmallocExt(tif, count * 2); data = (int16_t *)_TIFFmallocExt(tif, count * 2);
if (data == 0) if (data == 0)
@@ -2078,6 +2098,8 @@ TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -2106,6 +2128,8 @@ TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
case TIFF_SLONG: case TIFF_SLONG:
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_SLONG8: case TIFF_SLONG8:
case TIFF_IFD:
case TIFF_IFD8:
break; break;
default: default:
return (TIFFReadDirEntryErrType); return (TIFFReadDirEntryErrType);
@@ -2119,6 +2143,7 @@ TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
switch (direntry->tdir_type) switch (direntry->tdir_type)
{ {
case TIFF_LONG: case TIFF_LONG:
case TIFF_IFD:
*value = (uint32_t *)origdata; *value = (uint32_t *)origdata;
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(*value, count); TIFFSwabArrayOfLong(*value, count);
@@ -2143,6 +2168,8 @@ TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
*value = (uint32_t *)origdata; *value = (uint32_t *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
default:
break;
} }
data = (uint32_t *)_TIFFmallocExt(tif, count * 4); data = (uint32_t *)_TIFFmallocExt(tif, count * 4);
if (data == 0) if (data == 0)
@@ -2213,6 +2240,7 @@ TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
} }
break; break;
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_IFD8:
{ {
uint64_t *ma; uint64_t *ma;
uint32_t *mb; uint32_t *mb;
@@ -2248,6 +2276,8 @@ TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -2313,6 +2343,8 @@ TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value)
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong((uint32_t *)(*value), count); TIFFSwabArrayOfLong((uint32_t *)(*value), count);
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (int32_t *)_TIFFmallocExt(tif, count * 4); data = (int32_t *)_TIFFmallocExt(tif, count * 4);
if (data == 0) if (data == 0)
@@ -2410,6 +2442,8 @@ TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -2439,6 +2473,8 @@ TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
case TIFF_SLONG: case TIFF_SLONG:
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_SLONG8: case TIFF_SLONG8:
case TIFF_IFD:
case TIFF_IFD8:
break; break;
default: default:
return (TIFFReadDirEntryErrType); return (TIFFReadDirEntryErrType);
@@ -2453,6 +2489,7 @@ TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
switch (direntry->tdir_type) switch (direntry->tdir_type)
{ {
case TIFF_LONG8: case TIFF_LONG8:
case TIFF_IFD8:
*value = (uint64_t *)origdata; *value = (uint64_t *)origdata;
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8(*value, count); TIFFSwabArrayOfLong8(*value, count);
@@ -2477,6 +2514,8 @@ TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
*value = (uint64_t *)origdata; *value = (uint64_t *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
} }
default:
break;
} }
data = (uint64_t *)_TIFFmallocExt(tif, count * 8); data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
if (data == 0) if (data == 0)
@@ -2547,6 +2586,7 @@ TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
} }
break; break;
case TIFF_LONG: case TIFF_LONG:
case TIFF_IFD:
{ {
uint32_t *ma; uint32_t *ma;
uint64_t *mb; uint64_t *mb;
@@ -2579,6 +2619,8 @@ TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk) if (err != TIFFReadDirEntryErrOk)
@@ -2651,6 +2693,8 @@ TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **value)
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8((uint64_t *)(*value), count); TIFFSwabArrayOfLong8((uint64_t *)(*value), count);
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (int64_t *)_TIFFmallocExt(tif, count * 8); data = (int64_t *)_TIFFmallocExt(tif, count * 8);
if (data == 0) if (data == 0)
@@ -2742,6 +2786,8 @@ TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
*value = data; *value = data;
@@ -2787,8 +2833,11 @@ TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value)
TIFFCvtIEEEFloatToNative(tif, count, (float *)origdata); TIFFCvtIEEEFloatToNative(tif, count, (float *)origdata);
*value = (float *)origdata; *value = (float *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (float *)_TIFFmallocExt(tif, count * sizeof(float)); data =
(float *)_TIFFmallocExt(tif, (tmsize_t)((size_t)count * sizeof(float)));
if (data == 0) if (data == 0)
{ {
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
@@ -2970,14 +3019,16 @@ TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value)
for (n = 0; n < count; n++) for (n = 0; n < count; n++)
{ {
double val = *ma++; double val = *ma++;
if (val > FLT_MAX) if (val > (double)FLT_MAX)
val = FLT_MAX; val = (double)FLT_MAX;
else if (val < -FLT_MAX) else if (val < -(double)FLT_MAX)
val = -FLT_MAX; val = -(double)FLT_MAX;
*mb++ = (float)val; *mb++ = (float)val;
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
*value = data; *value = data;
@@ -3023,8 +3074,11 @@ TIFFReadDirEntryDoubleArray(TIFF *tif, TIFFDirEntry *direntry, double **value)
TIFFCvtIEEEDoubleToNative(tif, count, (double *)origdata); TIFFCvtIEEEDoubleToNative(tif, count, (double *)origdata);
*value = (double *)origdata; *value = (double *)origdata;
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (double *)_TIFFmallocExt(tif, count * sizeof(double)); data = (double *)_TIFFmallocExt(tif,
(tmsize_t)((size_t)count * sizeof(double)));
if (data == 0) if (data == 0)
{ {
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
@@ -3207,6 +3261,8 @@ TIFFReadDirEntryDoubleArray(TIFF *tif, TIFFDirEntry *direntry, double **value)
*mb++ = (double)(*ma++); *mb++ = (double)(*ma++);
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
*value = data; *value = data;
@@ -3244,6 +3300,8 @@ TIFFReadDirEntryIfd8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value)
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8(*value, count); TIFFSwabArrayOfLong8(*value, count);
return (TIFFReadDirEntryErrOk); return (TIFFReadDirEntryErrOk);
default:
break;
} }
data = (uint64_t *)_TIFFmallocExt(tif, count * 8); data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
if (data == 0) if (data == 0)
@@ -3269,6 +3327,8 @@ TIFFReadDirEntryIfd8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value)
} }
} }
break; break;
default:
break;
} }
_TIFFfreeExt(tif, origdata); _TIFFfreeExt(tif, origdata);
*value = data; *value = data;
@@ -3283,13 +3343,42 @@ TIFFReadDirEntryPersampleShort(TIFF *tif, TIFFDirEntry *direntry,
uint16_t *m; uint16_t *m;
uint16_t *na; uint16_t *na;
uint16_t nb; uint16_t nb;
if (direntry->tdir_count < (uint64_t)tif->tif_dir.td_samplesperpixel) if (direntry->tdir_count != (uint64_t)tif->tif_dir.td_samplesperpixel)
return (TIFFReadDirEntryErrCount); {
const TIFFField *fip = TIFFFieldWithTag(tif, direntry->tdir_tag);
if (direntry->tdir_count == 0)
{
return TIFFReadDirEntryErrCount;
}
else if (direntry->tdir_count <
(uint64_t)tif->tif_dir.td_samplesperpixel)
{
TIFFWarningExtR(
tif, "TIFFReadDirEntryPersampleShort",
"Tag %s entry count is %" PRIu64
" , whereas it should be SamplesPerPixel=%d. Assuming that "
"missing entries are all at the value of the first one",
fip ? fip->field_name : "unknown tagname", direntry->tdir_count,
tif->tif_dir.td_samplesperpixel);
}
else
{
TIFFWarningExtR(tif, "TIFFReadDirEntryPersampleShort",
"Tag %s entry count is %" PRIu64
" , whereas it should be SamplesPerPixel=%d. "
"Ignoring extra entries",
fip ? fip->field_name : "unknown tagname",
direntry->tdir_count,
tif->tif_dir.td_samplesperpixel);
}
}
err = TIFFReadDirEntryShortArray(tif, direntry, &m); err = TIFFReadDirEntryShortArray(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk || m == NULL) if (err != TIFFReadDirEntryErrOk || m == NULL)
return (err); return (err);
na = m; na = m;
nb = tif->tif_dir.td_samplesperpixel; nb = tif->tif_dir.td_samplesperpixel;
if (direntry->tdir_count < nb)
nb = (uint16_t)direntry->tdir_count;
*value = *na++; *value = *na++;
nb--; nb--;
while (nb > 0) while (nb > 0)
@@ -3908,7 +3997,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF *tif, uint64_t offset,
{ {
return TIFFReadDirEntryErrIo; return TIFFReadDirEntryErrIo;
} }
mb = ma + size; mb = (uint64_t)ma + (uint64_t)size;
if (mb > (uint64_t)tif->tif_size) if (mb > (uint64_t)tif->tif_size)
return (TIFFReadDirEntryErrIo); return (TIFFReadDirEntryErrIo);
_TIFFmemcpy(dest, tif->tif_base + ma, size); _TIFFmemcpy(dest, tif->tif_base + ma, size);
@@ -3955,6 +4044,7 @@ static void TIFFReadDirEntryOutputErr(TIFF *tif, enum TIFFReadDirEntryErr err,
TIFFErrorExtR(tif, module, "Out of memory reading of \"%s\"", TIFFErrorExtR(tif, module, "Out of memory reading of \"%s\"",
tagname); tagname);
break; break;
case TIFFReadDirEntryErrOk:
default: default:
assert(0); /* we should never get here */ assert(0); /* we should never get here */
break; break;
@@ -4001,6 +4091,7 @@ static void TIFFReadDirEntryOutputErr(TIFF *tif, enum TIFFReadDirEntryErr err,
"Out of memory reading of \"%s\"; tag ignored", "Out of memory reading of \"%s\"; tag ignored",
tagname); tagname);
break; break;
case TIFFReadDirEntryErrOk:
default: default:
assert(0); /* we should never get here */ assert(0); /* we should never get here */
break; break;
@@ -4086,7 +4177,8 @@ static int ByteCountLooksBad(TIFF *tif)
*/ */
static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp) static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp)
{ {
const uint64_t data_width = TIFFDataWidth(dp->tdir_type); const uint64_t data_width =
(uint64_t)TIFFDataWidth((TIFFDataType)dp->tdir_type);
if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width) if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width)
{ {
TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading", TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
@@ -4173,9 +4265,9 @@ static void CalcFinalIFDdatasizeReading(TIFF *tif, uint16_t dircount)
/* Get offset of end of IFD entry space. */ /* Get offset of end of IFD entry space. */
uint64_t IFDendoffset; uint64_t IFDendoffset;
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
IFDendoffset = tif->tif_diroff + 2 + dircount * 12 + 4; IFDendoffset = tif->tif_diroff + 2 + (uint64_t)dircount * 12 + 4;
else else
IFDendoffset = tif->tif_diroff + 8 + dircount * 20 + 8; IFDendoffset = tif->tif_diroff + 8 + (uint64_t)dircount * 20 + 8;
/* Check which offsets are right behind IFD entries. However, LibTIFF /* Check which offsets are right behind IFD entries. However, LibTIFF
* increments the writing address for every external data to an even offset. * increments the writing address for every external data to an even offset.
@@ -4224,9 +4316,9 @@ static void CalcFinalIFDdatasizeReading(TIFF *tif, uint16_t dircount)
/* Finally, add the size of the IFD tag entries themselves. */ /* Finally, add the size of the IFD tag entries themselves. */
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
tif->tif_dir.td_dirdatasize_read = 2 + dircount * 12 + 4 + size; tif->tif_dir.td_dirdatasize_read = 2U + dircount * 12U + 4U + size;
else else
tif->tif_dir.td_dirdatasize_read = 8 + dircount * 20 + 8 + size; tif->tif_dir.td_dirdatasize_read = 8U + dircount * 20U + 8U + size;
} /*-- CalcFinalIFDdatasizeReading() --*/ } /*-- CalcFinalIFDdatasizeReading() --*/
/* /*
@@ -4298,7 +4390,8 @@ int TIFFReadDirectory(TIFF *tif)
{ {
TIFFDirEntry *na; TIFFDirEntry *na;
uint16_t nb; uint16_t nb;
for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++) for (na = ma + 1, nb = (uint16_t)(mb + 1); nb < dircount;
na++, nb++)
{ {
if (ma->tdir_tag == na->tdir_tag) if (ma->tdir_tag == na->tdir_tag)
{ {
@@ -4312,7 +4405,15 @@ int TIFFReadDirectory(TIFF *tif)
tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */ tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */
tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS; tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS;
/* free any old stuff and reinit */ /* When changing directory, in deferred strile loading mode, we must also
* unset the TIFF_LAZYSTRILELOAD_DONE bit if it was initially set,
* to make sure the strile offset/bytecount are read again (when they fit
* in the tag data area).
*/
tif->tif_flags &= ~TIFF_LAZYSTRILELOAD_DONE;
/* Free any old stuff and reinit i/o and other parameters within
* TIFFDefaultDirectory() since we are starting on a new directory. */
TIFFFreeDirectory(tif); TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif); TIFFDefaultDirectory(tif);
@@ -4325,7 +4426,8 @@ int TIFFReadDirectory(TIFF *tif)
* checking. Note: Counter are reset within TIFFFreeDirectory(). */ * checking. Note: Counter are reset within TIFFFreeDirectory(). */
tif->tif_dir.td_dirdatasize_offsets = tif->tif_dir.td_dirdatasize_offsets =
(TIFFEntryOffsetAndLength *)_TIFFmallocExt( (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
tif, dircount * sizeof(TIFFEntryOffsetAndLength)); tif,
(tmsize_t)((size_t)dircount * sizeof(TIFFEntryOffsetAndLength)));
if (tif->tif_dir.td_dirdatasize_offsets == NULL) if (tif->tif_dir.td_dirdatasize_offsets == NULL)
{ {
TIFFErrorExtR( TIFFErrorExtR(
@@ -4788,8 +4890,8 @@ int TIFFReadDirectory(TIFF *tif)
(void)TIFFFetchNormalTag(tif, dp, TRUE); (void)TIFFFetchNormalTag(tif, dp, TRUE);
break; break;
} /* -- switch (dp->tdir_tag) -- */ } /* -- switch (dp->tdir_tag) -- */
} /* -- if (!dp->tdir_ignore) */ } /* -- if (!dp->tdir_ignore) */
} /* -- for-loop -- */ } /* -- for-loop -- */
/* Evaluate final IFD data size. */ /* Evaluate final IFD data size. */
CalcFinalIFDdatasizeReading(tif, dircount); CalcFinalIFDdatasizeReading(tif, dircount);
@@ -5098,7 +5200,7 @@ int TIFFReadDirectory(TIFF *tif)
tif->tif_dir.td_maxsamplevalue = 0xFFFF; tif->tif_dir.td_maxsamplevalue = 0xFFFF;
else else
tif->tif_dir.td_maxsamplevalue = tif->tif_dir.td_maxsamplevalue =
(uint16_t)((1L << tif->tif_dir.td_bitspersample) - 1); (uint16_t)((1 << tif->tif_dir.td_bitspersample) - 1);
} }
#ifdef STRIPBYTECOUNTSORTED_UNUSED #ifdef STRIPBYTECOUNTSORTED_UNUSED
@@ -5164,16 +5266,10 @@ int TIFFReadDirectory(TIFF *tif)
tif->tif_flags &= ~TIFF_DIRTYSTRIP; tif->tif_flags &= ~TIFF_DIRTYSTRIP;
/* /*
* Reinitialize i/o since we are starting on a new directory. * Reinitialize some further i/o since we are starting on a new directory.
*/ */
tif->tif_row = (uint32_t)-1; tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
tif->tif_curstrip = (uint32_t)-1; if (!tif->tif_dir.td_scanlinesize)
tif->tif_col = (uint32_t)-1;
tif->tif_curtile = (uint32_t)-1;
tif->tif_tilesize = (tmsize_t)-1;
tif->tif_scanlinesize = TIFFScanlineSize(tif);
if (!tif->tif_scanlinesize)
{ {
TIFFErrorExtR(tif, module, "Cannot handle zero scanline size"); TIFFErrorExtR(tif, module, "Cannot handle zero scanline size");
return (0); return (0);
@@ -5181,8 +5277,8 @@ int TIFFReadDirectory(TIFF *tif)
if (isTiled(tif)) if (isTiled(tif))
{ {
tif->tif_tilesize = TIFFTileSize(tif); tif->tif_dir.td_tilesize = TIFFTileSize(tif);
if (!tif->tif_tilesize) if (!tif->tif_dir.td_tilesize)
{ {
TIFFErrorExtR(tif, module, "Cannot handle zero tile size"); TIFFErrorExtR(tif, module, "Cannot handle zero tile size");
return (0); return (0);
@@ -5220,7 +5316,7 @@ static void TIFFReadDirectoryCheckOrder(TIFF *tif, TIFFDirEntry *dir,
"ascending order"); "ascending order");
break; break;
} }
m = o->tdir_tag + 1; m = o->tdir_tag + 1U;
} }
} }
@@ -5268,7 +5364,7 @@ static void TIFFReadDirectoryFindFieldInfo(TIFF *tif, uint16_t tagid,
break; break;
mb--; mb--;
} }
*fii = mb; *fii = (uint32_t)mb;
} }
/* /*
@@ -5308,7 +5404,8 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff,
{ {
TIFFDirEntry *na; TIFFDirEntry *na;
uint16_t nb; uint16_t nb;
for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++) for (na = ma + 1, nb = (uint16_t)(mb + 1); nb < dircount;
na++, nb++)
{ {
if (ma->tdir_tag == na->tdir_tag) if (ma->tdir_tag == na->tdir_tag)
{ {
@@ -5333,7 +5430,8 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff,
* checking. Note: Counter are reset within TIFFFreeDirectory(). */ * checking. Note: Counter are reset within TIFFFreeDirectory(). */
tif->tif_dir.td_dirdatasize_offsets = tif->tif_dir.td_dirdatasize_offsets =
(TIFFEntryOffsetAndLength *)_TIFFmallocExt( (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
tif, dircount * sizeof(TIFFEntryOffsetAndLength)); tif,
(tmsize_t)((size_t)dircount * sizeof(TIFFEntryOffsetAndLength)));
if (tif->tif_dir.td_dirdatasize_offsets == NULL) if (tif->tif_dir.td_dirdatasize_offsets == NULL)
{ {
TIFFErrorExtR( TIFFErrorExtR(
@@ -5515,15 +5613,17 @@ static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir,
uint64_t space; uint64_t space;
uint16_t n; uint16_t n;
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
space = sizeof(TIFFHeaderClassic) + 2 + dircount * 12 + 4; space = sizeof(TIFFHeaderClassic) + 2 +
(unsigned long)dircount * 12 + 4;
else else
space = sizeof(TIFFHeaderBig) + 8 + dircount * 20 + 8; space =
sizeof(TIFFHeaderBig) + 8 + (unsigned long)dircount * 20 + 8;
/* calculate amount of space used by indirect values */ /* calculate amount of space used by indirect values */
for (dp = dir, n = dircount; n > 0; n--, dp++) for (dp = dir, n = dircount; n > 0; n--, dp++)
{ {
uint32_t typewidth; uint32_t typewidth;
uint64_t datasize; uint64_t datasize;
typewidth = TIFFDataWidth((TIFFDataType)dp->tdir_type); typewidth = (uint32_t)TIFFDataWidth((TIFFDataType)dp->tdir_type);
if (typewidth == 0) if (typewidth == 0)
{ {
TIFFErrorExtR( TIFFErrorExtR(
@@ -5786,7 +5886,7 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
{ {
TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset", TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
"Cannot handle more than %u TIFF directories", "Cannot handle more than %u TIFF directories",
TIFF_MAX_DIR_COUNT); (unsigned)TIFF_MAX_DIR_COUNT);
return 0; return 0;
} }
@@ -6048,7 +6148,7 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
"to read TIFF directory"); "to read TIFF directory");
if (origdir == NULL) if (origdir == NULL)
return 0; return 0;
if (!ReadOK(tif, origdir, (tmsize_t)(dircount16 * dirsize))) if (!ReadOK(tif, origdir, (tmsize_t)dircount16 * dirsize))
{ {
TIFFErrorExtR(tif, module, "%.100s: Can not read TIFF directory", TIFFErrorExtR(tif, module, "%.100s: Can not read TIFF directory",
tif->tif_name); tif->tif_name);
@@ -6101,9 +6201,9 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
*/ */
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
{ {
m = off + sizeof(uint16_t); m = (tmsize_t)((uint64_t)off + sizeof(uint16_t));
if ((m < off) || (m < (tmsize_t)sizeof(uint16_t)) || if ((m < off) || ((uint64_t)m < sizeof(uint16_t)) ||
(m > tif->tif_size)) ((uint64_t)m > (uint64_t)tif->tif_size))
{ {
TIFFErrorExtR(tif, module, "Can not read TIFF directory count"); TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
return 0; return 0;
@@ -6112,7 +6212,7 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
{ {
_TIFFmemcpy(&dircount16, tif->tif_base + off, sizeof(uint16_t)); _TIFFmemcpy(&dircount16, tif->tif_base + off, sizeof(uint16_t));
} }
off += sizeof(uint16_t); off = (tmsize_t)((uint64_t)off + sizeof(uint16_t));
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&dircount16); TIFFSwabShort(&dircount16);
if (dircount16 > 4096) if (dircount16 > 4096)
@@ -6127,9 +6227,9 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
else else
{ {
uint64_t dircount64; uint64_t dircount64;
m = off + sizeof(uint64_t); m = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) || if ((m < off) || ((uint64_t)m < sizeof(uint64_t)) ||
(m > tif->tif_size)) ((uint64_t)m > (uint64_t)tif->tif_size))
{ {
TIFFErrorExtR(tif, module, "Can not read TIFF directory count"); TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
return 0; return 0;
@@ -6138,7 +6238,7 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
{ {
_TIFFmemcpy(&dircount64, tif->tif_base + off, sizeof(uint64_t)); _TIFFmemcpy(&dircount64, tif->tif_base + off, sizeof(uint64_t));
} }
off += sizeof(uint64_t); off = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&dircount64); TIFFSwabLong8(&dircount64);
if (dircount64 > 4096) if (dircount64 > 4096)
@@ -6177,7 +6277,7 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
if (origdir == NULL) if (origdir == NULL)
return 0; return 0;
m = off + dircount16 * dirsize; m = off + dircount16 * dirsize;
if ((m < off) || (m < (tmsize_t)(dircount16 * dirsize)) || if ((m < off) || (m < (tmsize_t)dircount16 * (tmsize_t)dirsize) ||
(m > tif->tif_size)) (m > tif->tif_size))
{ {
TIFFErrorExtR(tif, module, "Can not read TIFF directory"); TIFFErrorExtR(tif, module, "Can not read TIFF directory");
@@ -6186,7 +6286,8 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
} }
else else
{ {
_TIFFmemcpy(origdir, tif->tif_base + off, dircount16 * dirsize); _TIFFmemcpy(origdir, tif->tif_base + off,
(tmsize_t)dircount16 * dirsize);
} }
if (nextdiroff) if (nextdiroff)
{ {
@@ -6194,9 +6295,9 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
{ {
uint32_t nextdiroff32; uint32_t nextdiroff32;
m = off + sizeof(uint32_t); m = (tmsize_t)((uint64_t)off + sizeof(uint32_t));
if ((m < off) || (m < (tmsize_t)sizeof(uint32_t)) || if ((m < off) || ((uint64_t)m < sizeof(uint32_t)) ||
(m > tif->tif_size)) ((uint64_t)m > (uint64_t)tif->tif_size))
nextdiroff32 = 0; nextdiroff32 = 0;
else else
_TIFFmemcpy(&nextdiroff32, tif->tif_base + off, _TIFFmemcpy(&nextdiroff32, tif->tif_base + off,
@@ -6207,9 +6308,9 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
} }
else else
{ {
m = off + sizeof(uint64_t); m = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) || if ((m < off) || ((uint64_t)m < sizeof(uint64_t)) ||
(m > tif->tif_size)) ((uint64_t)m > (uint64_t)tif->tif_size))
*nextdiroff = 0; *nextdiroff = 0;
else else
_TIFFmemcpy(nextdiroff, tif->tif_base + off, _TIFFmemcpy(nextdiroff, tif->tif_base + off,
@@ -6355,8 +6456,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
/* TIFFReadDirEntryArrayWithLimit() ensures this can't be /* TIFFReadDirEntryArrayWithLimit() ensures this can't be
* larger than MAX_SIZE_TAG_DATA */ * larger than MAX_SIZE_TAG_DATA */
assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1); assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1);
uint8_t *o = uint8_t *o = (uint8_t *)_TIFFmallocExt(
_TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); tif, (uint32_t)dp->tdir_count + 1);
if (o == NULL) if (o == NULL)
{ {
if (data != NULL) if (data != NULL)
@@ -6498,7 +6599,7 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
{ {
if (!EvaluateIFDdatasizeReading(tif, dp)) if (!EvaluateIFDdatasizeReading(tif, dp))
return 0; return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data)) if (!TIFFSetField(tif, dp->tdir_tag, (double)data))
return (0); return (0);
} }
} }
@@ -6910,6 +7011,41 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
} }
} }
break; break;
case TIFF_SETGET_C0_IFD8:
{
uint64_t *data;
assert(fip->field_readcount >= 1);
assert(fip->field_passcount == 0);
if (dp->tdir_count != (uint64_t)fip->field_readcount)
{
TIFFWarningExtR(tif, module,
"incorrect count for field \"%s\", expected "
"%d, got %" PRIu64,
fip->field_name, (int)fip->field_readcount,
dp->tdir_count);
return (0);
}
else
{
err = TIFFReadDirEntryIfd8Array(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
if (!EvaluateIFDdatasizeReading(tif, dp))
{
if (data != 0)
_TIFFfreeExt(tif, data);
return 0;
}
int m;
m = TIFFSetField(tif, dp->tdir_tag, data);
if (data != 0)
_TIFFfreeExt(tif, data);
if (!m)
return (0);
}
}
}
break;
case TIFF_SETGET_C16_ASCII: case TIFF_SETGET_C16_ASCII:
{ {
uint8_t *data; uint8_t *data;
@@ -6938,8 +7074,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
"byte. Forcing it to be null", "byte. Forcing it to be null",
fip->field_name); fip->field_name);
/* Enlarge buffer and add terminating null. */ /* Enlarge buffer and add terminating null. */
uint8_t *o = uint8_t *o = (uint8_t *)_TIFFmallocExt(
_TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); tif, (uint32_t)dp->tdir_count + 1);
if (o == NULL) if (o == NULL)
{ {
if (data != NULL) if (data != NULL)
@@ -7309,8 +7445,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
"in null byte. Forcing it to be null", "in null byte. Forcing it to be null",
fip->field_name); fip->field_name);
/* Enlarge buffer and add terminating null. */ /* Enlarge buffer and add terminating null. */
uint8_t *o = uint8_t *o = (uint8_t *)_TIFFmallocExt(
_TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); tif, (uint32_t)dp->tdir_count + 1);
if (o == NULL) if (o == NULL)
{ {
if (data != NULL) if (data != NULL)
@@ -7624,6 +7760,11 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover)
} }
} }
break; break;
case TIFF_SETGET_INT:
case TIFF_SETGET_C0_ASCII:
case TIFF_SETGET_OTHER:
assert(0); /* these should not arrive here */
break;
default: default:
assert(0); /* we should never get here */ assert(0); /* we should never get here */
break; break;
@@ -7700,9 +7841,10 @@ static int TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir, uint32_t nstrips,
} }
if (dir->tdir_count) if (dir->tdir_count)
_TIFFmemcpy(resizeddata, data, _TIFFmemcpy(resizeddata, data,
(uint32_t)dir->tdir_count * sizeof(uint64_t)); (tmsize_t)((size_t)dir->tdir_count * sizeof(uint64_t)));
_TIFFmemset(resizeddata + (uint32_t)dir->tdir_count, 0, _TIFFmemset(resizeddata + (uint32_t)dir->tdir_count, 0,
(nstrips - (uint32_t)dir->tdir_count) * sizeof(uint64_t)); (tmsize_t)((size_t)(nstrips - (uint32_t)dir->tdir_count) *
sizeof(uint64_t)));
_TIFFfreeExt(tif, data); _TIFFfreeExt(tif, data);
data = resizeddata; data = resizeddata;
} }
@@ -7866,7 +8008,7 @@ static void allocChoppedUpStripArrays(TIFF *tif, uint32_t nstrips,
*/ */
static void ChopUpSingleUncompressedStrip(TIFF *tif) static void ChopUpSingleUncompressedStrip(TIFF *tif)
{ {
register TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint64_t bytecount; uint64_t bytecount;
uint64_t offset; uint64_t offset;
uint32_t rowblock; uint32_t rowblock;
@@ -7881,7 +8023,7 @@ static void ChopUpSingleUncompressedStrip(TIFF *tif)
/* later ( StripOffsets and StripByteCounts improperly filled) . */ /* later ( StripOffsets and StripByteCounts improperly filled) . */
if (bytecount == 0 && tif->tif_mode != O_RDONLY) if (bytecount == 0 && tif->tif_mode != O_RDONLY)
return; return;
offset = TIFFGetStrileByteCount(tif, 0); offset = TIFFGetStrileOffset(tif, 0);
assert(td->td_planarconfig == PLANARCONFIG_CONTIG); assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
if ((td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif))) if ((td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
rowblock = td->td_ycbcrsubsampling[1]; rowblock = td->td_ycbcrsubsampling[1];
@@ -8032,7 +8174,7 @@ static void TryChopUpUncompressedBigTiff(TIFF *tif)
TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
static uint64_t _TIFFUnsanitizedAddUInt64AndInt(uint64_t a, int b) static uint64_t _TIFFUnsanitizedAddUInt64AndInt(uint64_t a, int b)
{ {
return a + b; return a + (uint64_t)b;
} }
/* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around /* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around
@@ -8111,7 +8253,7 @@ static int _TIFFPartialReadStripArray(TIFF *tif, TIFFDirEntry *dirent,
panVals[strile] = 0; panVals[strile] = 0;
return 0; return 0;
} }
nOffset = nBaseOffset + sizeofval * strile; nOffset = nBaseOffset + (uint64_t)sizeofval * (uint64_t)strile;
nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE; nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE; nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
@@ -8119,7 +8261,7 @@ static int _TIFFPartialReadStripArray(TIFF *tif, TIFFDirEntry *dirent,
nOffsetEndPage += IO_CACHE_PAGE_SIZE; nOffsetEndPage += IO_CACHE_PAGE_SIZE;
#undef IO_CACHE_PAGE_SIZE #undef IO_CACHE_PAGE_SIZE
nLastStripOffset = nBaseOffset + arraySize * sizeofval; nLastStripOffset = nBaseOffset + (uint64_t)arraySize * sizeofval;
if (nLastStripOffset < nOffsetEndPage) if (nLastStripOffset < nOffsetEndPage)
nOffsetEndPage = nLastStripOffset; nOffsetEndPage = nLastStripOffset;
if (nOffsetStartPage >= nOffsetEndPage) if (nOffsetStartPage >= nOffsetEndPage)
@@ -8254,9 +8396,9 @@ static int _TIFFFetchStrileValue(TIFF *tif, uint32_t strile,
} }
#endif #endif
offsetArray = (uint64_t *)(_TIFFreallocExt(tif, td->td_stripoffset_p, offsetArray = (uint64_t *)(_TIFFreallocExt(tif, td->td_stripoffset_p,
nArraySize)); (tmsize_t)nArraySize));
bytecountArray = (uint64_t *)(_TIFFreallocExt( bytecountArray = (uint64_t *)(_TIFFreallocExt(
tif, td->td_stripbytecount_p, nArraySize)); tif, td->td_stripbytecount_p, (tmsize_t)nArraySize));
if (offsetArray) if (offsetArray)
td->td_stripoffset_p = offsetArray; td->td_stripoffset_p = offsetArray;
if (bytecountArray) if (bytecountArray)
@@ -8290,7 +8432,7 @@ static int _TIFFFetchStrileValue(TIFF *tif, uint32_t strile,
if (~((*parray)[strile]) == 0) if (~((*parray)[strile]) == 0)
{ {
if (!_TIFFPartialReadStripArray(tif, dirent, strile, *parray)) if (!_TIFFPartialReadStripArray(tif, dirent, (int)strile, *parray))
{ {
(*parray)[strile] = 0; (*parray)[strile] = 0;
return 0; return 0;
@@ -8308,10 +8450,26 @@ static uint64_t _TIFFGetStrileOffsetOrByteCountValue(TIFF *tif, uint32_t strile,
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (pbErr) if (pbErr)
*pbErr = 0; *pbErr = 0;
/* Avoid the "dirent->tdir_count <= 4" code path for one of
* StripOffsets/StripByteCounts, and the other code path for the other one,
* which will lead to inconsistencies and potential out-of-bounds reads.
*/
if ((td->td_stripoffset_entry.tdir_count <= 4) !=
(td->td_stripbytecount_entry.tdir_count <= 4))
{
TIFFErrorExtR(tif, "_TIFFGetStrileOffsetOrByteCountValue",
"Inconsistent directory count between StripOffsets and "
"StripByteCounts");
if (pbErr)
*pbErr = 1;
return 0;
}
if ((tif->tif_flags & TIFF_DEFERSTRILELOAD) && if ((tif->tif_flags & TIFF_DEFERSTRILELOAD) &&
!(tif->tif_flags & TIFF_CHOPPEDUPARRAYS)) !(tif->tif_flags & TIFF_CHOPPEDUPARRAYS))
{ {
if (!(tif->tif_flags & TIFF_LAZYSTRILELOAD) || if (!(tif->tif_flags & TIFF_LAZYSTRILELOAD_ASKED) ||
/* If the values may fit in the toff_long/toff_long8 member */ /* If the values may fit in the toff_long/toff_long8 member */
/* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */ /* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */
dirent->tdir_count <= 4) dirent->tdir_count <= 4)
@@ -8382,7 +8540,7 @@ int _TIFFFillStriles(TIFF *tif) { return _TIFFFillStrilesInternal(tif, 1); }
static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount) static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount)
{ {
register TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
int return_value = 1; int return_value = 1;
/* Do not do anything if TIFF_DEFERSTRILELOAD is not set */ /* Do not do anything if TIFF_DEFERSTRILELOAD is not set */
@@ -8390,7 +8548,8 @@ static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount)
(tif->tif_flags & TIFF_CHOPPEDUPARRAYS) != 0) (tif->tif_flags & TIFF_CHOPPEDUPARRAYS) != 0)
return 1; return 1;
if (tif->tif_flags & TIFF_LAZYSTRILELOAD) if ((tif->tif_flags & TIFF_LAZYSTRILELOAD_ASKED) &&
!(tif->tif_flags & TIFF_LAZYSTRILELOAD_DONE))
{ {
/* In case of lazy loading, reload completely the arrays */ /* In case of lazy loading, reload completely the arrays */
_TIFFfreeExt(tif, td->td_stripoffset_p); _TIFFfreeExt(tif, td->td_stripoffset_p);
@@ -8398,7 +8557,7 @@ static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount)
td->td_stripoffset_p = NULL; td->td_stripoffset_p = NULL;
td->td_stripbytecount_p = NULL; td->td_stripbytecount_p = NULL;
td->td_stripoffsetbyteallocsize = 0; td->td_stripoffsetbyteallocsize = 0;
tif->tif_flags &= ~TIFF_LAZYSTRILELOAD; tif->tif_flags |= TIFF_LAZYSTRILELOAD_DONE;
} }
/* If stripoffset array is already loaded, exit with success */ /* If stripoffset array is already loaded, exit with success */

View File

@@ -365,7 +365,7 @@ static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&dircount); TIFFSwabShort(&dircount);
(void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET); (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
if (!ReadOK(tif, &nextnextdir, 4)) if (!ReadOK(tif, &nextnextdir, 4))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -377,7 +377,7 @@ static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
uint32_t m; uint32_t m;
m = 0; m = 0;
(void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U,
SEEK_SET); SEEK_SET);
if (!WriteOK(tif, &m, 4)) if (!WriteOK(tif, &m, 4))
{ {
@@ -417,7 +417,6 @@ static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
while (1) while (1)
{ {
uint64_t dircount64; uint64_t dircount64;
uint16_t dircount;
uint64_t nextnextdir; uint64_t nextnextdir;
if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8)) if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
@@ -435,8 +434,8 @@ static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
"corrupt TIFF"); "corrupt TIFF");
return (0); return (0);
} }
dircount = (uint16_t)dircount64; (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
(void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET); SEEK_SET);
if (!ReadOK(tif, &nextnextdir, 8)) if (!ReadOK(tif, &nextnextdir, 8))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -448,7 +447,7 @@ static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
uint64_t m; uint64_t m;
m = 0; m = 0;
(void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
SEEK_SET); SEEK_SET);
if (!WriteOK(tif, &m, 8)) if (!WriteOK(tif, &m, 8))
{ {
@@ -592,24 +591,24 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
} }
if (TIFFFieldSet(tif, FIELD_RESOLUTION)) if (TIFFFieldSet(tif, FIELD_RESOLUTION))
{ {
if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir, if (!TIFFWriteDirectoryTagRational(
TIFFTAG_XRESOLUTION, tif, &ndir, dir, TIFFTAG_XRESOLUTION,
tif->tif_dir.td_xresolution)) (double)tif->tif_dir.td_xresolution))
goto bad; goto bad;
if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir, if (!TIFFWriteDirectoryTagRational(
TIFFTAG_YRESOLUTION, tif, &ndir, dir, TIFFTAG_YRESOLUTION,
tif->tif_dir.td_yresolution)) (double)tif->tif_dir.td_yresolution))
goto bad; goto bad;
} }
if (TIFFFieldSet(tif, FIELD_POSITION)) if (TIFFFieldSet(tif, FIELD_POSITION))
{ {
if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir, if (!TIFFWriteDirectoryTagRational(
TIFFTAG_XPOSITION, tif, &ndir, dir, TIFFTAG_XPOSITION,
tif->tif_dir.td_xposition)) (double)tif->tif_dir.td_xposition))
goto bad; goto bad;
if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir, if (!TIFFWriteDirectoryTagRational(
TIFFTAG_YPOSITION, tif, &ndir, dir, TIFFTAG_YPOSITION,
tif->tif_dir.td_yposition)) (double)tif->tif_dir.td_yposition))
goto bad; goto bad;
} }
if (TIFFFieldSet(tif, FIELD_SUBFILETYPE)) if (TIFFFieldSet(tif, FIELD_SUBFILETYPE))
@@ -712,6 +711,14 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
} }
if (TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) if (TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
{ {
/* Check td_stripbytecount_p for NULL pointer (bug#749) */
if (tif->tif_dir.td_stripbytecount_p == NULL)
{
TIFFErrorExtR(
tif, module,
"StripByteCount array is not set, pointer is NULL");
goto bad;
}
if (!isTiled(tif)) if (!isTiled(tif))
{ {
if (!TIFFWriteDirectoryTagLongLong8Array( if (!TIFFWriteDirectoryTagLongLong8Array(
@@ -731,6 +738,14 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
} }
if (TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) if (TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
{ {
/* Check td_stripoffset_p for NULL pointer (bug#749) */
if (tif->tif_dir.td_stripoffset_p == NULL)
{
TIFFErrorExtR(
tif, module,
"StripByteOffset array is not set, pointer is NULL");
goto bad;
}
if (!isTiled(tif)) if (!isTiled(tif))
{ {
/* td_stripoffset_p might be NULL in an odd OJPEG case. See /* td_stripoffset_p might be NULL in an odd OJPEG case. See
@@ -851,7 +866,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
if (!TIFFWriteDirectoryTagAscii( if (!TIFFWriteDirectoryTagAscii(
tif, &ndir, dir, TIFFTAG_INKNAMES, tif, &ndir, dir, TIFFTAG_INKNAMES,
tif->tif_dir.td_inknameslen, tif->tif_dir.td_inknames)) (uint32_t)tif->tif_dir.td_inknameslen,
tif->tif_dir.td_inknames))
goto bad; goto bad;
} }
if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS)) if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
@@ -932,10 +948,58 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
TIFFGetField(tif, o->field_tag, &pa, &pb); TIFFGetField(tif, o->field_tag, &pa, &pb);
if (!TIFFWriteDirectoryTagUndefinedArray( if (!TIFFWriteDirectoryTagUndefinedArray(
tif, &ndir, dir, (uint16_t)o->field_tag, tif, &ndir, dir, (uint16_t)o->field_tag,
pa, pb)) pa, (uint8_t *)pb))
goto bad; goto bad;
} }
break; break;
case TIFF_SETGET_UNDEFINED:
case TIFF_SETGET_SINT8:
case TIFF_SETGET_SINT16:
case TIFF_SETGET_SINT32:
case TIFF_SETGET_UINT64:
case TIFF_SETGET_SINT64:
case TIFF_SETGET_FLOAT:
case TIFF_SETGET_DOUBLE:
case TIFF_SETGET_IFD8:
case TIFF_SETGET_INT:
case TIFF_SETGET_UINT16_PAIR:
case TIFF_SETGET_C0_ASCII:
case TIFF_SETGET_C0_UINT8:
case TIFF_SETGET_C0_SINT8:
case TIFF_SETGET_C0_UINT16:
case TIFF_SETGET_C0_SINT16:
case TIFF_SETGET_C0_UINT32:
case TIFF_SETGET_C0_SINT32:
case TIFF_SETGET_C0_UINT64:
case TIFF_SETGET_C0_SINT64:
case TIFF_SETGET_C0_FLOAT:
case TIFF_SETGET_C0_DOUBLE:
case TIFF_SETGET_C0_IFD8:
case TIFF_SETGET_C16_ASCII:
case TIFF_SETGET_C16_UINT8:
case TIFF_SETGET_C16_SINT8:
case TIFF_SETGET_C16_UINT16:
case TIFF_SETGET_C16_SINT16:
case TIFF_SETGET_C16_UINT32:
case TIFF_SETGET_C16_SINT32:
case TIFF_SETGET_C16_UINT64:
case TIFF_SETGET_C16_SINT64:
case TIFF_SETGET_C16_FLOAT:
case TIFF_SETGET_C16_DOUBLE:
case TIFF_SETGET_C16_IFD8:
case TIFF_SETGET_C32_ASCII:
case TIFF_SETGET_C32_SINT8:
case TIFF_SETGET_C32_UINT16:
case TIFF_SETGET_C32_SINT16:
case TIFF_SETGET_C32_UINT32:
case TIFF_SETGET_C32_SINT32:
case TIFF_SETGET_C32_UINT64:
case TIFF_SETGET_C32_SINT64:
case TIFF_SETGET_C32_FLOAT:
case TIFF_SETGET_C32_DOUBLE:
case TIFF_SETGET_C32_IFD8:
case TIFF_SETGET_UINT8:
case TIFF_SETGET_OTHER:
default: default:
TIFFErrorExtR( TIFFErrorExtR(
tif, module, tif, module,
@@ -954,67 +1018,67 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
uint16_t tag = uint16_t tag =
(uint16_t)tif->tif_dir.td_customValues[m].info->field_tag; (uint16_t)tif->tif_dir.td_customValues[m].info->field_tag;
uint32_t count = tif->tif_dir.td_customValues[m].count; uint32_t count = (uint32_t)tif->tif_dir.td_customValues[m].count;
switch (tif->tif_dir.td_customValues[m].info->field_type) switch (tif->tif_dir.td_customValues[m].info->field_type)
{ {
case TIFF_ASCII: case TIFF_ASCII:
if (!TIFFWriteDirectoryTagAscii( if (!TIFFWriteDirectoryTagAscii(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (char *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_UNDEFINED: case TIFF_UNDEFINED:
if (!TIFFWriteDirectoryTagUndefinedArray( if (!TIFFWriteDirectoryTagUndefinedArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint8_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_BYTE: case TIFF_BYTE:
if (!TIFFWriteDirectoryTagByteArray( if (!TIFFWriteDirectoryTagByteArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint8_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_SBYTE: case TIFF_SBYTE:
if (!TIFFWriteDirectoryTagSbyteArray( if (!TIFFWriteDirectoryTagSbyteArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (int8_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_SHORT: case TIFF_SHORT:
if (!TIFFWriteDirectoryTagShortArray( if (!TIFFWriteDirectoryTagShortArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint16_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_SSHORT: case TIFF_SSHORT:
if (!TIFFWriteDirectoryTagSshortArray( if (!TIFFWriteDirectoryTagSshortArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (int16_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_LONG: case TIFF_LONG:
if (!TIFFWriteDirectoryTagLongArray( if (!TIFFWriteDirectoryTagLongArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint32_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_SLONG: case TIFF_SLONG:
if (!TIFFWriteDirectoryTagSlongArray( if (!TIFFWriteDirectoryTagSlongArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (int32_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_LONG8: case TIFF_LONG8:
if (!TIFFWriteDirectoryTagLong8Array( if (!TIFFWriteDirectoryTagLong8Array(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint64_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_SLONG8: case TIFF_SLONG8:
if (!TIFFWriteDirectoryTagSlong8Array( if (!TIFFWriteDirectoryTagSlong8Array(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (int64_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_RATIONAL: case TIFF_RATIONAL:
@@ -1029,7 +1093,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
if (!TIFFWriteDirectoryTagRationalDoubleArray( if (!TIFFWriteDirectoryTagRationalDoubleArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (double *)tif->tif_dir.td_customValues[m]
.value))
goto bad; goto bad;
} }
else else
@@ -1037,7 +1102,7 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
/*-- default should be tv_size == 4 */ /*-- default should be tv_size == 4 */
if (!TIFFWriteDirectoryTagRationalArray( if (!TIFFWriteDirectoryTagRationalArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (float *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
/*-- ToDo: After Testing, this should be removed and /*-- ToDo: After Testing, this should be removed and
* tv_size==4 should be set as default. */ * tv_size==4 should be set as default. */
@@ -1064,7 +1129,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
if (!TIFFWriteDirectoryTagSrationalDoubleArray( if (!TIFFWriteDirectoryTagSrationalDoubleArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (double *)tif->tif_dir.td_customValues[m]
.value))
goto bad; goto bad;
} }
else else
@@ -1072,7 +1138,7 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
/*-- default should be tv_size == 4 */ /*-- default should be tv_size == 4 */
if (!TIFFWriteDirectoryTagSrationalArray( if (!TIFFWriteDirectoryTagSrationalArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (float *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
/*-- ToDo: After Testing, this should be removed and /*-- ToDo: After Testing, this should be removed and
* tv_size==4 should be set as default. */ * tv_size==4 should be set as default. */
@@ -1090,27 +1156,28 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
case TIFF_FLOAT: case TIFF_FLOAT:
if (!TIFFWriteDirectoryTagFloatArray( if (!TIFFWriteDirectoryTagFloatArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (float *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_DOUBLE: case TIFF_DOUBLE:
if (!TIFFWriteDirectoryTagDoubleArray( if (!TIFFWriteDirectoryTagDoubleArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (double *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_IFD: case TIFF_IFD:
if (!TIFFWriteDirectoryTagIfdArray( if (!TIFFWriteDirectoryTagIfdArray(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint32_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_IFD8: case TIFF_IFD8:
if (!TIFFWriteDirectoryTagIfdIfd8Array( if (!TIFFWriteDirectoryTagIfdIfd8Array(
tif, &ndir, dir, tag, count, tif, &ndir, dir, tag, count,
tif->tif_dir.td_customValues[m].value)) (uint64_t *)tif->tif_dir.td_customValues[m].value))
goto bad; goto bad;
break; break;
case TIFF_NOTYPE:
default: default:
assert(0); /* we should never get here */ assert(0); /* we should never get here */
break; break;
@@ -1128,7 +1195,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
tif->tif_dir.td_dirdatasize_write += 8 + ndir * 20 + 8; tif->tif_dir.td_dirdatasize_write += 8 + ndir * 20 + 8;
/* Setup a new directory within first pass. */ /* Setup a new directory within first pass. */
dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry)); dir = (TIFFDirEntry *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)ndir * sizeof(TIFFDirEntry)));
if (dir == NULL) if (dir == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1238,7 +1306,7 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
uint8_t *n; uint8_t *n;
uint32_t nTmp; uint32_t nTmp;
TIFFDirEntry *o; TIFFDirEntry *o;
n = dirmem; n = (uint8_t *)dirmem;
*(uint16_t *)n = (uint16_t)ndir; *(uint16_t *)n = (uint16_t)ndir;
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)n); TIFFSwabShort((uint16_t *)n);
@@ -1274,7 +1342,7 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
{ {
uint8_t *n; uint8_t *n;
TIFFDirEntry *o; TIFFDirEntry *o;
n = dirmem; n = (uint8_t *)dirmem;
*(uint64_t *)n = ndir; *(uint64_t *)n = ndir;
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)n); TIFFSwabLong8((uint64_t *)n);
@@ -1405,7 +1473,7 @@ static int8_t TIFFClampDoubleToInt8(double val)
{ {
if (val > 127) if (val > 127)
return 127; return 127;
if (val < -128 || val != val) if (val < -128 || isnan(val))
return -128; return -128;
return (int8_t)val; return (int8_t)val;
} }
@@ -1414,7 +1482,7 @@ static int16_t TIFFClampDoubleToInt16(double val)
{ {
if (val > 32767) if (val > 32767)
return 32767; return 32767;
if (val < -32768 || val != val) if (val < -32768 || isnan(val))
return -32768; return -32768;
return (int16_t)val; return (int16_t)val;
} }
@@ -1423,7 +1491,7 @@ static int32_t TIFFClampDoubleToInt32(double val)
{ {
if (val > 0x7FFFFFFF) if (val > 0x7FFFFFFF)
return 0x7FFFFFFF; return 0x7FFFFFFF;
if (val < -0x7FFFFFFF - 1 || val != val) if (val < -0x7FFFFFFF - 1 || isnan(val))
return -0x7FFFFFFF - 1; return -0x7FFFFFFF - 1;
return (int32_t)val; return (int32_t)val;
} }
@@ -1432,7 +1500,7 @@ static uint8_t TIFFClampDoubleToUInt8(double val)
{ {
if (val < 0) if (val < 0)
return 0; return 0;
if (val > 255 || val != val) if (val > 255 || isnan(val))
return 255; return 255;
return (uint8_t)val; return (uint8_t)val;
} }
@@ -1441,7 +1509,7 @@ static uint16_t TIFFClampDoubleToUInt16(double val)
{ {
if (val < 0) if (val < 0)
return 0; return 0;
if (val > 65535 || val != val) if (val > 65535 || isnan(val))
return 65535; return 65535;
return (uint16_t)val; return (uint16_t)val;
} }
@@ -1450,7 +1518,7 @@ static uint32_t TIFFClampDoubleToUInt32(double val)
{ {
if (val < 0) if (val < 0)
return 0; return 0;
if (val > 0xFFFFFFFFU || val != val) if (val > 0xFFFFFFFFU || isnan(val))
return 0xFFFFFFFFU; return 0xFFFFFFFFU;
return (uint32_t)val; return (uint32_t)val;
} }
@@ -1464,7 +1532,7 @@ static int TIFFWriteDirectoryTagSampleformatArray(TIFF *tif, uint32_t *ndir,
void *conv; void *conv;
uint32_t i; uint32_t i;
int ok; int ok;
conv = _TIFFmallocExt(tif, count * sizeof(double)); conv = _TIFFmallocExt(tif, (tmsize_t)((size_t)count * sizeof(double)));
if (conv == NULL) if (conv == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1603,7 +1671,9 @@ static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir,
return (TIFFWriteDirectoryTagCheckedShortArray( return (TIFFWriteDirectoryTagCheckedShortArray(
tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, NULL)); tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, NULL));
} }
m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t)); m = (uint16_t *)_TIFFmallocExt(
tif,
(tmsize_t)((size_t)tif->tif_dir.td_samplesperpixel * sizeof(uint16_t)));
if (m == NULL) if (m == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1664,14 +1734,6 @@ static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
uint32_t *q; uint32_t *q;
int o; int o;
/* is this just a counting pass? */
if (dir == NULL)
{
/* only evaluate IFD data size and inc. ndir */
return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
count, value));
}
/* We always write Long8 for BigTIFF, no checking needed. */ /* We always write Long8 for BigTIFF, no checking needed. */
if (tif->tif_flags & TIFF_BIGTIFF) if (tif->tif_flags & TIFF_BIGTIFF)
return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag, return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
@@ -1681,7 +1743,8 @@ static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
** For classic tiff we want to verify everything is in range for long ** For classic tiff we want to verify everything is in range for long
** and convert to long format. ** and convert to long format.
*/ */
p = _TIFFmallocExt(tif, count * sizeof(uint32_t)); p = (uint32_t *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
if (p == NULL) if (p == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1725,13 +1788,6 @@ static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
int32_t *q; int32_t *q;
int o; int o;
/* is this just a counting pass? */
if (dir == NULL)
{
/* only evaluate IFD data size and inc. ndir */
return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
count, value));
}
/* We always write SLong8 for BigTIFF, no checking needed. */ /* We always write SLong8 for BigTIFF, no checking needed. */
if (tif->tif_flags & TIFF_BIGTIFF) if (tif->tif_flags & TIFF_BIGTIFF)
return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag, return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
@@ -1741,7 +1797,8 @@ static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
** For classic tiff we want to verify everything is in range for signed-long ** For classic tiff we want to verify everything is in range for signed-long
** and convert to signed-long format. ** and convert to signed-long format.
*/ */
p = _TIFFmallocExt(tif, count * sizeof(uint32_t)); p = (int32_t *)_TIFFmallocExt(tif,
(tmsize_t)((size_t)count * sizeof(uint32_t)));
if (p == NULL) if (p == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1960,7 +2017,8 @@ static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
** and convert to long format. ** and convert to long format.
*/ */
uint32_t *p = _TIFFmallocExt(tif, count * sizeof(uint32_t)); uint32_t *p = (uint32_t *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
uint32_t *q; uint32_t *q;
uint64_t *ma; uint64_t *ma;
uint32_t mb; uint32_t mb;
@@ -1990,7 +2048,8 @@ static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
} }
else else
{ {
uint16_t *p = _TIFFmallocExt(tif, count * sizeof(uint16_t)); uint16_t *p = (uint16_t *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)count * sizeof(uint16_t)));
uint16_t *q; uint16_t *q;
uint64_t *ma; uint64_t *ma;
uint32_t mb; uint32_t mb;
@@ -2050,7 +2109,8 @@ static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir,
** and convert to long format. ** and convert to long format.
*/ */
p = _TIFFmallocExt(tif, count * sizeof(uint32_t)); p = (uint32_t *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
if (p == NULL) if (p == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2101,26 +2161,45 @@ static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
{ {
static const char module[] = "TIFFWriteDirectoryTagColormap"; static const char module[] = "TIFFWriteDirectoryTagColormap";
uint32_t m; uint32_t m;
uint32_t count;
uint64_t count64;
tmsize_t total_values;
tmsize_t plane_bytes;
uint16_t *n; uint16_t *n;
int o; int o;
m = (1 << tif->tif_dir.td_bitspersample); if (tif->tif_dir.td_bitspersample >= 32)
{
TIFFErrorExtR(tif, module, "BitsPerSample too large for Colormap");
return (0);
}
m = 1U << tif->tif_dir.td_bitspersample;
count64 = _TIFFMultiply64(tif, 3U, m, module);
if (count64 == 0)
return (0);
count = _TIFFCastUInt64ToUInt32(tif, count64, module);
total_values = _TIFFCastUInt64ToSSize(tif, count64, module);
plane_bytes = _TIFFCastUInt64ToSSize(
tif, _TIFFMultiply64(tif, m, sizeof(uint16_t), module), module);
if (count == 0 || total_values == 0 || plane_bytes == 0)
return (0);
if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
{ {
EvaluateIFDdatasizeWrite(tif, 3 * m, sizeof(uint16_t), ndir); EvaluateIFDdatasizeWrite(tif, count, sizeof(uint16_t), ndir);
return 1; return 1;
} }
n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t)); n = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t),
module);
if (n == NULL) if (n == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
return (0); return (0);
} }
_TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], m * sizeof(uint16_t)); _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], plane_bytes);
_TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], m * sizeof(uint16_t)); _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], plane_bytes);
_TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], m * sizeof(uint16_t)); _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], plane_bytes);
o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP, o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP,
3 * m, n); count, n);
_TIFFfreeExt(tif, n); _TIFFfreeExt(tif, n);
return (o); return (o);
} }
@@ -2130,13 +2209,27 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
{ {
static const char module[] = "TIFFWriteDirectoryTagTransferfunction"; static const char module[] = "TIFFWriteDirectoryTagTransferfunction";
uint32_t m; uint32_t m;
uint32_t count;
uint64_t count64;
tmsize_t total_values;
tmsize_t plane_bytes;
uint16_t n; uint16_t n;
uint16_t *o; uint16_t *o;
int p; int p;
/* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with /* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with
* (1 << BitsPerSample) * uint16_t values. * 2**BitsPerSample uint16_t values.
*/ */
m = (1 << tif->tif_dir.td_bitspersample); if (tif->tif_dir.td_bitspersample >= 32)
{
TIFFErrorExtR(tif, module,
"BitsPerSample too large for TransferFunction");
return (0);
}
m = 1U << tif->tif_dir.td_bitspersample;
plane_bytes = _TIFFCastUInt64ToSSize(
tif, _TIFFMultiply64(tif, m, sizeof(uint16_t), module), module);
if (plane_bytes == 0)
return (0);
/* clang-format off */ /* clang-format off */
n = (tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples) > 1 ? 3 : 1; n = (tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples) > 1 ? 3 : 1;
/* clang-format on */ /* clang-format on */
@@ -2161,35 +2254,39 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
if (n == 3) if (n == 3)
{ {
if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
tif->tif_dir.td_transferfunction[2], tif->tif_dir.td_transferfunction[2], plane_bytes) &&
m * sizeof(uint16_t)) &&
!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
tif->tif_dir.td_transferfunction[1], tif->tif_dir.td_transferfunction[1], plane_bytes))
m * sizeof(uint16_t)))
n = 1; n = 1;
} }
count64 = _TIFFMultiply64(tif, n, m, module);
if (count64 == 0)
return (0);
count = _TIFFCastUInt64ToUInt32(tif, count64, module);
total_values = _TIFFCastUInt64ToSSize(tif, count64, module);
if (count == 0 || total_values == 0)
return (0);
if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
{ {
EvaluateIFDdatasizeWrite(tif, n * m, 2, ndir); EvaluateIFDdatasizeWrite(tif, count, 2, ndir);
return 1; return 1;
} }
o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t)); o = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t),
module);
if (o == NULL) if (o == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
return (0); return (0);
} }
_TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0], _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0], plane_bytes);
m * sizeof(uint16_t));
if (n > 1) if (n > 1)
_TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1], _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1], plane_bytes);
m * sizeof(uint16_t));
if (n > 2) if (n > 2)
_TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2], _TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2],
m * sizeof(uint16_t)); plane_bytes);
p = TIFFWriteDirectoryTagCheckedShortArray( p = TIFFWriteDirectoryTagCheckedShortArray(
tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, n * m, o); tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, count, o);
_TIFFfreeExt(tif, o); _TIFFfreeExt(tif, o);
return (p); return (p);
} }
@@ -2209,7 +2306,9 @@ static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir,
uint64_t *pa; uint64_t *pa;
uint32_t *pb; uint32_t *pb;
uint16_t p; uint16_t p;
o = _TIFFmallocExt(tif, tif->tif_dir.td_nsubifd * sizeof(uint32_t)); o = (uint32_t *)_TIFFmallocExt(
tif,
(tmsize_t)((size_t)tif->tif_dir.td_nsubifd * sizeof(uint32_t)));
if (o == NULL) if (o == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2494,7 +2593,7 @@ static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir,
TIFFErrorExtR(tif, module, "Negative value is illegal"); TIFFErrorExtR(tif, module, "Negative value is illegal");
return 0; return 0;
} }
else if (value != value) else if (isnan(value))
{ {
TIFFErrorExtR(tif, module, "Not-a-number value is illegal"); TIFFErrorExtR(tif, module, "Not-a-number value is illegal");
return 0; return 0;
@@ -2537,7 +2636,8 @@ static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir); EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
return 1; return 1;
} }
m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t)); m = (uint32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(uint32_t),
"for rational array");
if (m == NULL) if (m == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2545,7 +2645,7 @@ static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
} }
for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++) for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
{ {
DoubleToRational(*na, &nb[0], &nb[1]); DoubleToRational((double)*na, &nb[0], &nb[1]);
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(m, count * 2); TIFFSwabArrayOfLong(m, count * 2);
@@ -2573,7 +2673,8 @@ static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir); EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
return 1; return 1;
} }
m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t)); m = (int32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(int32_t),
"for srational array");
if (m == NULL) if (m == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2581,7 +2682,7 @@ static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
} }
for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++) for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
{ {
DoubleToSrational(*na, &nb[0], &nb[1]); DoubleToSrational((double)*na, &nb[0], &nb[1]);
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong((uint32_t *)m, count * 2); TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
@@ -2610,7 +2711,8 @@ TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir); EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
return 1; return 1;
} }
m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t)); m = (uint32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(uint32_t),
"for rational double array");
if (m == NULL) if (m == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2618,7 +2720,7 @@ TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
} }
for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++) for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
{ {
DoubleToRational(*na, &nb[0], &nb[1]); DoubleToRational((double)*na, &nb[0], &nb[1]);
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(m, count * 2); TIFFSwabArrayOfLong(m, count * 2);
@@ -2645,7 +2747,8 @@ static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir); EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
return 1; return 1;
} }
m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t)); m = (int32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(int32_t),
"for srational double array");
if (m == NULL) if (m == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2653,7 +2756,7 @@ static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
} }
for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++) for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
{ {
DoubleToSrational(*na, &nb[0], &nb[1]); DoubleToSrational((double)*na, &nb[0], &nb[1]);
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong((uint32_t *)m, count * 2); TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
@@ -2744,7 +2847,8 @@ static void ToRationalEuclideanGCD(double value, int blnUseSignedRange,
*the double-value of it reaches an integer number without fractional part. *the double-value of it reaches an integer number without fractional part.
*/ */
bigDenom = 1; bigDenom = 1;
while ((value != floor(value)) && (value < fMax) && (bigDenom < nMax)) while ((!TIFF_DOUBLE_EQ(value, floor(value))) && (value < fMax) &&
(bigDenom < nMax))
{ {
bigDenom <<= 1; bigDenom <<= 1;
value *= 2; value *= 2;
@@ -2836,7 +2940,7 @@ static void DoubleToRational(double value, uint32_t *num, uint32_t *denom)
return; return;
} }
/*-- Check for easy integer numbers -- */ /*-- Check for easy integer numbers -- */
if (value == (uint32_t)(value)) if (TIFF_DOUBLE_EQ(value, (double)(uint32_t)value))
{ {
*num = (uint32_t)value; *num = (uint32_t)value;
*denom = 1; *denom = 1;
@@ -2911,7 +3015,7 @@ static void DoubleToSrational(double value, int32_t *num, int32_t *denom)
return; return;
} }
/*-- Check for easy numbers -- */ /*-- Check for easy numbers -- */
if (value == (int32_t)(value)) if (TIFF_DOUBLE_EQ(value, (double)(int32_t)value))
{ {
*num = (int32_t)(neg * value); *num = (int32_t)(neg * value);
*denom = 1; *denom = 1;
@@ -3231,6 +3335,14 @@ static int TIFFLinkDirectory(TIFF *tif)
uint16_t dircount; uint16_t dircount;
uint32_t nextnextdir; uint32_t nextnextdir;
/* Update IDF loop list and check for IFD loop.
* ndir is IFD ID plus one. */
if (!_TIFFCheckDirNumberAndOffset(tif, ndir - 1, nextdir))
{
TIFFErrorExtR(tif, module, "Error IFD loop detected");
return 0; /* bad offset (IFD looping or more than
TIFF_MAX_DIR_COUNT IFDs) */
}
if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2)) if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory count"); TIFFErrorExtR(tif, module, "Error fetching directory count");
@@ -3238,7 +3350,7 @@ static int TIFFLinkDirectory(TIFF *tif)
} }
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&dircount); TIFFSwabShort(&dircount);
(void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET); (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
if (!ReadOK(tif, &nextnextdir, 4)) if (!ReadOK(tif, &nextnextdir, 4))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -3248,7 +3360,7 @@ static int TIFFLinkDirectory(TIFF *tif)
TIFFSwabLong(&nextnextdir); TIFFSwabLong(&nextnextdir);
if (nextnextdir == 0) if (nextnextdir == 0)
{ {
(void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET); (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
if (!WriteOK(tif, &m, 4)) if (!WriteOK(tif, &m, 4))
{ {
TIFFErrorExtR(tif, module, "Error writing directory link"); TIFFErrorExtR(tif, module, "Error writing directory link");
@@ -3306,9 +3418,15 @@ static int TIFFLinkDirectory(TIFF *tif)
while (1) while (1)
{ {
uint64_t dircount64; uint64_t dircount64;
uint16_t dircount;
uint64_t nextnextdir; uint64_t nextnextdir;
/* Update IDF loop list and check for IFD loop. */
if (!_TIFFCheckDirNumberAndOffset(tif, ndir - 1, nextdir))
{
TIFFErrorExtR(tif, module, "Error IFD loop detected");
return 0; /* bad offset (IFD looping or more than
TIFF_MAX_DIR_COUNT IFDs) */
}
if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8)) if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory count"); TIFFErrorExtR(tif, module, "Error fetching directory count");
@@ -3323,8 +3441,7 @@ static int TIFFLinkDirectory(TIFF *tif)
"likely corrupt TIFF"); "likely corrupt TIFF");
return (0); return (0);
} }
dircount = (uint16_t)dircount64; (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20, SEEK_SET);
(void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
if (!ReadOK(tif, &nextnextdir, 8)) if (!ReadOK(tif, &nextnextdir, 8))
{ {
TIFFErrorExtR(tif, module, "Error fetching directory link"); TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -3334,7 +3451,8 @@ static int TIFFLinkDirectory(TIFF *tif)
TIFFSwabLong8(&nextnextdir); TIFFSwabLong8(&nextnextdir);
if (nextnextdir == 0) if (nextnextdir == 0)
{ {
(void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET); (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
SEEK_SET);
if (!WriteOK(tif, &m, 8)) if (!WriteOK(tif, &m, 8))
{ {
TIFFErrorExtR(tif, module, "Error writing directory link"); TIFFErrorExtR(tif, module, "Error writing directory link");
@@ -3475,7 +3593,7 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
if (entry_tag == tag) if (entry_tag == tag)
break; break;
read_offset += dirsize; read_offset += (uint64_t)dirsize;
} }
if (entry_tag != tag) if (entry_tag != tag)
@@ -3584,13 +3702,13 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
if (in_datatype == TIFF_LONG8 && if (in_datatype == TIFF_LONG8 &&
(entry_type == TIFF_SHORT || entry_type == TIFF_LONG || (entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
entry_type == TIFF_LONG8)) entry_type == TIFF_LONG8))
datatype = entry_type; datatype = (TIFFDataType)entry_type;
else if (in_datatype == TIFF_SLONG8 && else if (in_datatype == TIFF_SLONG8 &&
(entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8)) (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8))
datatype = entry_type; datatype = (TIFFDataType)entry_type;
else if (in_datatype == TIFF_IFD8 && else if (in_datatype == TIFF_IFD8 &&
(entry_type == TIFF_IFD || entry_type == TIFF_IFD8)) (entry_type == TIFF_IFD || entry_type == TIFF_IFD8))
datatype = entry_type; datatype = (TIFFDataType)entry_type;
else else
datatype = in_datatype; datatype = in_datatype;
} }
@@ -3605,7 +3723,8 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
return 0; return 0;
if (datatype == in_datatype) if (datatype == in_datatype)
memcpy(buf_to_write, data, count * TIFFDataWidth(datatype)); memcpy(buf_to_write, data,
(size_t)count * (size_t)TIFFDataWidth(datatype));
else if (datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8) else if (datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8)
{ {
tmsize_t i; tmsize_t i;
@@ -3698,8 +3817,8 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0) tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0)
{ {
tif->tif_dir.td_stripoffset_entry.tdir_type = datatype; tif->tif_dir.td_stripoffset_entry.tdir_type = (uint16_t)datatype;
tif->tif_dir.td_stripoffset_entry.tdir_count = count; tif->tif_dir.td_stripoffset_entry.tdir_count = (uint64_t)count;
} }
else if ((tag == TIFFTAG_TILEBYTECOUNTS || else if ((tag == TIFFTAG_TILEBYTECOUNTS ||
tag == TIFFTAG_STRIPBYTECOUNTS) && tag == TIFFTAG_STRIPBYTECOUNTS) &&
@@ -3707,8 +3826,8 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0) tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)
{ {
tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype; tif->tif_dir.td_stripbytecount_entry.tdir_type = (uint16_t)datatype;
tif->tif_dir.td_stripbytecount_entry.tdir_count = count; tif->tif_dir.td_stripbytecount_entry.tdir_count = (uint64_t)count;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@@ -3756,13 +3875,14 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
if (count * TIFFDataWidth(datatype) == 4) if (count * TIFFDataWidth(datatype) == 4)
{ {
uint32_t value; uint32_t value;
memcpy(&value, buf_to_write, count * TIFFDataWidth(datatype)); memcpy(&value, buf_to_write,
(size_t)count * (size_t)TIFFDataWidth(datatype));
entry_offset = value; entry_offset = value;
} }
else else
{ {
memcpy(&entry_offset, buf_to_write, memcpy(&entry_offset, buf_to_write,
count * TIFFDataWidth(datatype)); (size_t)count * (size_t)TIFFDataWidth(datatype));
} }
} }
@@ -3772,7 +3892,7 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Adjust the directory entry. */ /* Adjust the directory entry. */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
entry_type = datatype; entry_type = (uint16_t)datatype;
entry_count = (uint64_t)count; entry_count = (uint64_t)count;
memcpy(direntry_raw + 2, &entry_type, sizeof(uint16_t)); memcpy(direntry_raw + 2, &entry_type, sizeof(uint16_t));
if (tif->tif_flags & TIFF_SWAB) if (tif->tif_flags & TIFF_SWAB)

View File

@@ -80,7 +80,7 @@ static int DumpModeDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
"Not enough data for scanline %" PRIu32 "Not enough data for scanline %" PRIu32
", expected a request for at most %" TIFF_SSIZE_FORMAT ", expected a request for at most %" TIFF_SSIZE_FORMAT
" bytes, got a request for %" TIFF_SSIZE_FORMAT " bytes", " bytes, got a request for %" TIFF_SSIZE_FORMAT " bytes",
tif->tif_row, tif->tif_rawcc, cc); tif->tif_dir.td_row, tif->tif_rawcc, cc);
return (0); return (0);
} }
/* /*
@@ -99,8 +99,23 @@ static int DumpModeDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
*/ */
static int DumpModeSeek(TIFF *tif, uint32_t nrows) static int DumpModeSeek(TIFF *tif, uint32_t nrows)
{ {
tif->tif_rawcp += nrows * tif->tif_scanlinesize; tmsize_t seek_size;
tif->tif_rawcc -= nrows * tif->tif_scanlinesize; if (nrows > 0 &&
tif->tif_dir.td_scanlinesize > (tmsize_t)(TIFF_TMSIZE_T_MAX / nrows))
{
TIFFErrorExtR(tif, "DumpModeSeek",
"Integer overflow computing seek size");
return (0);
}
seek_size = (tmsize_t)nrows * tif->tif_dir.td_scanlinesize;
if (seek_size > tif->tif_rawcc)
{
TIFFErrorExtR(tif, "DumpModeSeek",
"Seek beyond end of raw data buffer");
return (0);
}
tif->tif_rawcp += seek_size;
tif->tif_rawcc -= seek_size;
return (1); return (1);
} }

View File

@@ -123,7 +123,7 @@ typedef struct
static const char module[] = mod; \ static const char module[] = mod; \
Fax3CodecState *sp = DecoderState(tif); \ Fax3CodecState *sp = DecoderState(tif); \
int a0; /* reference element */ \ int a0; /* reference element */ \
int lastx = sp->b.rowpixels; /* last element in row */ \ int lastx = (int)sp->b.rowpixels; /* last element in row */ \
uint32_t BitAcc; /* bit accumulator */ \ uint32_t BitAcc; /* bit accumulator */ \
int BitsAvail; /* # valid bits in BitAcc */ \ int BitsAvail; /* # valid bits in BitAcc */ \
int RunLength; /* length of current run */ \ int RunLength; /* length of current run */ \
@@ -209,61 +209,68 @@ static int Fax3PreDecode(TIFF *tif, uint16_t s)
static void Fax3Unexpected(const char *module, TIFF *tif, uint32_t line, static void Fax3Unexpected(const char *module, TIFF *tif, uint32_t line,
uint32_t a0) uint32_t a0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(
"Bad code word at line %" PRIu32 " of %s %" PRIu32 tif, module,
" (x %" PRIu32 ")", "Bad code word at line %" PRIu32 " of %s %" PRIu32 " (x %" PRIu32 ")",
line, isTiled(tif) ? "tile" : "strip", line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0); (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
a0);
} }
#define unexpected(table, a0) \ #define unexpected(table, a0) \
do \ do \
{ \ { \
Fax3Unexpected(module, tif, sp->line, a0); \ Fax3Unexpected(module, tif, (uint32_t)sp->line, (uint32_t)(a0)); \
++sp->unexpectedReachedCount; \ ++sp->unexpectedReachedCount; \
} while (0) } while (0)
static void Fax3Extension(const char *module, TIFF *tif, uint32_t line, static void Fax3Extension(const char *module, TIFF *tif, uint32_t line,
uint32_t a0) uint32_t a0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(
"Uncompressed data (not supported) at line %" PRIu32 tif, module,
" of %s %" PRIu32 " (x %" PRIu32 ")", "Uncompressed data (not supported) at line %" PRIu32 " of %s %" PRIu32
line, isTiled(tif) ? "tile" : "strip", " (x %" PRIu32 ")",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0); line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
a0);
} }
#define extension(a0) Fax3Extension(module, tif, sp->line, a0) #define extension(a0) \
Fax3Extension(module, tif, (uint32_t)sp->line, (uint32_t)(a0))
static void Fax3BadLength(const char *module, TIFF *tif, uint32_t line, static void Fax3BadLength(const char *module, TIFF *tif, uint32_t line,
uint32_t a0, uint32_t lastx) uint32_t a0, uint32_t lastx)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(
"%s at line %" PRIu32 " of %s %" PRIu32 " (got %" PRIu32 tif, module,
", expected %" PRIu32 ")", "%s at line %" PRIu32 " of %s %" PRIu32 " (got %" PRIu32
a0 < lastx ? "Premature EOL" : "Line length mismatch", line, ", expected %" PRIu32 ")",
isTiled(tif) ? "tile" : "strip", a0 < lastx ? "Premature EOL" : "Line length mismatch", line,
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0, isTiled(tif) ? "tile" : "strip",
lastx); (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip), a0,
lastx);
} }
#define badlength(a0, lastx) \ #define badlength(a0, lastx) \
do \ do \
{ \ { \
Fax3BadLength(module, tif, sp->line, a0, lastx); \ Fax3BadLength(module, tif, (uint32_t)sp->line, (uint32_t)(a0), \
(uint32_t)(lastx)); \
++sp->eolReachedCount; \ ++sp->eolReachedCount; \
} while (0) } while (0)
static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line, static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line,
uint32_t a0) uint32_t a0)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(
"Premature EOF at line %" PRIu32 " of %s %" PRIu32 tif, module,
" (x %" PRIu32 ")", "Premature EOF at line %" PRIu32 " of %s %" PRIu32 " (x %" PRIu32 ")",
line, isTiled(tif) ? "tile" : "strip", line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0); (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
a0);
} }
#define prematureEOF(a0) \ #define prematureEOF(a0) \
do \ do \
{ \ { \
Fax3PrematureEOF(module, tif, sp->line, a0); \ Fax3PrematureEOF(module, tif, (uint32_t)sp->line, (uint32_t)(a0)); \
++sp->eofReachedCount; \ ++sp->eofReachedCount; \
} while (0) } while (0)
@@ -275,16 +282,15 @@ static void Fax3TryG3WithoutEOL(const char *module, TIFF *tif, uint32_t line,
"Try to decode (read) fax Group 3 data without EOL at line %" PRIu32 "Try to decode (read) fax Group 3 data without EOL at line %" PRIu32
" of %s %" PRIu32 " (x %" PRIu32 "). Please check result", " of %s %" PRIu32 " (x %" PRIu32 "). Please check result",
line, isTiled(tif) ? "tile" : "strip", line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0); (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
a0);
} }
#define tryG3WithoutEOL(a0) \ #define tryG3WithoutEOL(a0) \
do \ do \
{ \ { \
Fax3TryG3WithoutEOL(module, tif, sp->line, a0); \ Fax3TryG3WithoutEOL(module, tif, (uint32_t)sp->line, (uint32_t)(a0)); \
} while (0) } while (0)
#define Nop
static int CheckReachedCounters(TIFF *tif, const char *module, static int CheckReachedCounters(TIFF *tif, const char *module,
Fax3CodecState *sp) Fax3CodecState *sp)
{ {
@@ -344,12 +350,12 @@ RETRY_WITHOUT_EOL_1D:
pa = thisrun; pa = thisrun;
#ifdef FAX3_DEBUG #ifdef FAX3_DEBUG
printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail); printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
printf("-------------------- %" PRIu32 "\n", tif->tif_row); printf("-------------------- %" PRIu32 "\n", tif->tif_dir.td_row);
fflush(stdout); fflush(stdout);
#endif #endif
SYNC_EOL(EOF1D, RETRY_WITHOUT_EOL_1D); SYNC_EOL(EOF1D, RETRY_WITHOUT_EOL_1D);
EXPAND1D(EOF1Da); EXPAND1D(EOF1Da);
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
buf += sp->b.rowbytes; buf += sp->b.rowbytes;
occ -= sp->b.rowbytes; occ -= sp->b.rowbytes;
sp->line++; sp->line++;
@@ -357,7 +363,7 @@ RETRY_WITHOUT_EOL_1D:
EOF1D: /* premature EOF */ EOF1D: /* premature EOF */
CLEANUP_RUNS(); CLEANUP_RUNS();
EOF1Da: /* premature EOF */ EOF1Da: /* premature EOF */
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
UNCACHE_STATE(tif, sp); UNCACHE_STATE(tif, sp);
return (-1); return (-1);
} }
@@ -404,16 +410,16 @@ RETRY_WITHOUT_EOL_2D:
ClrBits(1); ClrBits(1);
#ifdef FAX3_DEBUG #ifdef FAX3_DEBUG
printf(" %s\n-------------------- %" PRIu32 "\n", is1D ? "1D" : "2D", printf(" %s\n-------------------- %" PRIu32 "\n", is1D ? "1D" : "2D",
tif->tif_row); tif->tif_dir.td_row);
fflush(stdout); fflush(stdout);
#endif #endif
pb = sp->refruns; pb = sp->refruns;
b1 = *pb++; b1 = (int)*pb++;
if (is1D) if (is1D)
EXPAND1D(EOF2Da); EXPAND1D(EOF2Da);
else else
EXPAND2D(EOF2Da); EXPAND2D(EOF2Da);
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
if (pa < thisrun + sp->nruns) if (pa < thisrun + sp->nruns)
{ {
SETVALUE(0); /* imaginary change for reference */ SETVALUE(0); /* imaginary change for reference */
@@ -426,7 +432,7 @@ RETRY_WITHOUT_EOL_2D:
EOF2D: /* premature EOF */ EOF2D: /* premature EOF */
CLEANUP_RUNS(); CLEANUP_RUNS();
EOF2Da: /* premature EOF */ EOF2Da: /* premature EOF */
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
UNCACHE_STATE(tif, sp); UNCACHE_STATE(tif, sp);
return (-1); return (-1);
} }
@@ -479,12 +485,12 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
{ {
if (bx) if (bx)
{ /* align to byte boundary */ { /* align to byte boundary */
*cp++ &= 0xff << (8 - bx); *cp++ &= (unsigned char)(0xff << (8 - bx));
run -= 8 - bx; run -= 8 - bx;
} }
if ((n = run >> 3) != 0) if ((n = (int32_t)(run >> 3)) != 0)
{ /* multiple bytes to fill */ { /* multiple bytes to fill */
if ((n / sizeof(int64_t)) > 1) if (((size_t)n / sizeof(int64_t)) > 1)
{ {
/* /*
* Align to int64_tword boundary and fill. * Align to int64_tword boundary and fill.
@@ -492,8 +498,8 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
for (; n && !isAligned(cp, int64_t); n--) for (; n && !isAligned(cp, int64_t); n--)
*cp++ = 0x00; *cp++ = 0x00;
lp = (int64_t *)cp; lp = (int64_t *)cp;
nw = (int32_t)(n / sizeof(int64_t)); nw = (int32_t)((size_t)n / sizeof(int64_t));
n -= nw * sizeof(int64_t); n -= (int32_t)((size_t)nw * sizeof(int64_t));
do do
{ {
*lp++ = 0L; *lp++ = 0L;
@@ -504,10 +510,10 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
run &= 7; run &= 7;
} }
if (run) if (run)
cp[0] &= 0xff >> run; cp[0] &= (unsigned char)(0xff >> run);
} }
else else
cp[0] &= ~(_fillmasks[run] >> bx); cp[0] &= (unsigned char)~(_fillmasks[run] >> bx);
x += runs[0]; x += runs[0];
} }
run = runs[1]; run = runs[1];
@@ -521,12 +527,12 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
{ {
if (bx) if (bx)
{ /* align to byte boundary */ { /* align to byte boundary */
*cp++ |= 0xff >> bx; *cp++ |= (unsigned char)(0xff >> bx);
run -= 8 - bx; run -= 8 - bx;
} }
if ((n = run >> 3) != 0) if ((n = (int32_t)(run >> 3)) != 0)
{ /* multiple bytes to fill */ { /* multiple bytes to fill */
if ((n / sizeof(int64_t)) > 1) if (((size_t)n / sizeof(int64_t)) > 1)
{ {
/* /*
* Align to int64_t boundary and fill. * Align to int64_t boundary and fill.
@@ -534,8 +540,8 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
for (; n && !isAligned(cp, int64_t); n--) for (; n && !isAligned(cp, int64_t); n--)
*cp++ = 0xff; *cp++ = 0xff;
lp = (int64_t *)cp; lp = (int64_t *)cp;
nw = (int32_t)(n / sizeof(int64_t)); nw = (int32_t)((size_t)n / sizeof(int64_t));
n -= nw * sizeof(int64_t); n -= (int32_t)((size_t)nw * sizeof(int64_t));
do do
{ {
*lp++ = -1L; *lp++ = -1L;
@@ -550,7 +556,7 @@ void _TIFFFax3fillruns(unsigned char *buf, uint32_t *runs, uint32_t *erun,
cp[0] = (unsigned char)((cp[0] | (0xff00 >> run)) & 0xff); cp[0] = (unsigned char)((cp[0] | (0xff00 >> run)) & 0xff);
} }
else else
cp[0] |= _fillmasks[run] >> bx; cp[0] |= (unsigned char)(_fillmasks[run] >> bx);
x += runs[1]; x += runs[1];
} }
} }
@@ -726,12 +732,13 @@ static const int _msbmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f,
{ \ { \
while (length > bit) \ while (length > bit) \
{ \ { \
data |= bits >> (length - bit); \ data |= (int)((unsigned int)bits >> (length - bit)); \
length -= bit; \ length -= bit; \
_FlushBits(tif); \ _FlushBits(tif); \
} \ } \
assert(length < 9); \ assert(length < 9); \
data |= (bits & _msbmask[length]) << (bit - length); \ data |= (int)(((unsigned int)bits & (unsigned int)_msbmask[length]) \
<< (unsigned int)(bit - length)); \
bit -= length; \ bit -= length; \
if (bit == 0) \ if (bit == 0) \
_FlushBits(tif); \ _FlushBits(tif); \
@@ -745,13 +752,13 @@ static const int _msbmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f,
static int Fax3PutBits(TIFF *tif, unsigned int bits, unsigned int length) static int Fax3PutBits(TIFF *tif, unsigned int bits, unsigned int length)
{ {
Fax3CodecState *sp = EncoderState(tif); Fax3CodecState *sp = EncoderState(tif);
unsigned int bit = sp->bit; unsigned int bit = (unsigned int)sp->bit;
int data = sp->data; int data = (int)sp->data;
_PutBits(tif, bits, length); _PutBits(tif, bits, length);
sp->data = data; sp->data = (uint32_t)data;
sp->bit = bit; sp->bit = (int)bit;
return 1; return 1;
} }
@@ -782,8 +789,8 @@ static int Fax3PutBits(TIFF *tif, unsigned int bits, unsigned int length)
static int putspan(TIFF *tif, int32_t span, const tableentry *tab) static int putspan(TIFF *tif, int32_t span, const tableentry *tab)
{ {
Fax3CodecState *sp = EncoderState(tif); Fax3CodecState *sp = EncoderState(tif);
unsigned int bit = sp->bit; unsigned int bit = (unsigned int)sp->bit;
int data = sp->data; int data = (int)sp->data;
unsigned int code, length; unsigned int code, length;
while (span >= 2624) while (span >= 2624)
@@ -816,8 +823,8 @@ static int putspan(TIFF *tif, int32_t span, const tableentry *tab)
#endif #endif
_PutBits(tif, code, length); _PutBits(tif, code, length);
sp->data = data; sp->data = (uint32_t)data;
sp->bit = bit; sp->bit = (int)bit;
return 1; return 1;
} }
@@ -831,8 +838,8 @@ static int putspan(TIFF *tif, int32_t span, const tableentry *tab)
static int Fax3PutEOL(TIFF *tif) static int Fax3PutEOL(TIFF *tif)
{ {
Fax3CodecState *sp = EncoderState(tif); Fax3CodecState *sp = EncoderState(tif);
unsigned int bit = sp->bit; unsigned int bit = (unsigned int)sp->bit;
int data = sp->data; int data = (int)sp->data;
unsigned int code, length, tparm; unsigned int code, length, tparm;
if (sp->b.groupoptions & GROUP3OPT_FILLBITS) if (sp->b.groupoptions & GROUP3OPT_FILLBITS)
@@ -849,7 +856,7 @@ static int Fax3PutEOL(TIFF *tif)
align = sp->bit + (8 - align); align = sp->bit + (8 - align);
else else
align = sp->bit - align; align = sp->bit - align;
tparm = align; tparm = (unsigned int)align;
_PutBits(tif, 0, tparm); _PutBits(tif, 0, tparm);
} }
} }
@@ -862,8 +869,8 @@ static int Fax3PutEOL(TIFF *tif)
} }
_PutBits(tif, code, length); _PutBits(tif, code, length);
sp->data = data; sp->data = (uint32_t)data;
sp->bit = bit; sp->bit = (int)bit;
return 1; return 1;
} }
@@ -991,10 +998,10 @@ static inline int32_t find0span(unsigned char *bp, int32_t bs, int32_t be)
bp++; bp++;
} }
lp = (int64_t *)bp; lp = (int64_t *)bp;
while ((bits >= (int32_t)(8 * sizeof(int64_t))) && (0 == *lp)) while ((bits >= (int32_t)(size_t)(8 * sizeof(int64_t))) && (0 == *lp))
{ {
span += 8 * sizeof(int64_t); span += (int32_t)(size_t)(8 * sizeof(int64_t));
bits -= 8 * sizeof(int64_t); bits -= (int32_t)(size_t)(8 * sizeof(int64_t));
lp++; lp++;
} }
bp = (unsigned char *)lp; bp = (unsigned char *)lp;
@@ -1059,11 +1066,11 @@ static inline int32_t find1span(unsigned char *bp, int32_t bs, int32_t be)
bp++; bp++;
} }
lp = (int64_t *)bp; lp = (int64_t *)bp;
while ((bits >= (int32_t)(8 * sizeof(int64_t))) && while ((bits >= (int32_t)(size_t)(8 * sizeof(int64_t))) &&
(~((uint64_t)0) == (uint64_t)*lp)) (~((uint64_t)0) == (uint64_t)*lp))
{ {
span += 8 * sizeof(int64_t); span += (int32_t)(size_t)(8 * sizeof(int64_t));
bits -= 8 * sizeof(int64_t); bits -= (int32_t)(size_t)(8 * sizeof(int64_t));
lp++; lp++;
} }
bp = (unsigned char *)lp; bp = (unsigned char *)lp;
@@ -1118,16 +1125,16 @@ static int Fax3Encode1DRow(TIFF *tif, unsigned char *bp, uint32_t bits)
for (;;) for (;;)
{ {
span = find0span(bp, bs, bits); /* white span */ span = find0span(bp, (int32_t)bs, (int32_t)bits); /* white span */
if (!putspan(tif, span, TIFFFaxWhiteCodes)) if (!putspan(tif, span, TIFFFaxWhiteCodes))
return 0; return 0;
bs += span; bs += (uint32_t)span;
if (bs >= bits) if (bs >= bits)
break; break;
span = find1span(bp, bs, bits); /* black span */ span = find1span(bp, (int32_t)bs, (int32_t)bits); /* black span */
if (!putspan(tif, span, TIFFFaxBlackCodes)) if (!putspan(tif, span, TIFFFaxBlackCodes))
return 0; return 0;
bs += span; bs += (uint32_t)span;
if (bs >= bits) if (bs >= bits)
break; break;
} }
@@ -1161,15 +1168,20 @@ static const tableentry vcodes[7] = {
static int Fax3Encode2DRow(TIFF *tif, unsigned char *bp, unsigned char *rp, static int Fax3Encode2DRow(TIFF *tif, unsigned char *bp, unsigned char *rp,
uint32_t bits) uint32_t bits)
{ {
#define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix)&7))) & 1) #define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix) & 7))) & 1)
uint32_t a0 = 0; uint32_t a0 = 0;
uint32_t a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0)); uint32_t a1 = (PIXEL(bp, 0) != 0
uint32_t b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0)); ? 0
: (uint32_t)finddiff(bp, (int32_t)0, (int32_t)bits, 0));
uint32_t b1 = (PIXEL(rp, 0) != 0
? 0
: (uint32_t)finddiff(rp, (int32_t)0, (int32_t)bits, 0));
uint32_t a2, b2; uint32_t a2, b2;
for (;;) for (;;)
{ {
b2 = finddiff2(rp, b1, bits, PIXEL(rp, b1)); b2 = (uint32_t)finddiff2(rp, (int32_t)b1, (int32_t)bits,
(int32_t)PIXEL(rp, b1));
if (b2 >= a1) if (b2 >= a1)
{ {
/* Naive computation triggers /* Naive computation triggers
@@ -1182,21 +1194,22 @@ static int Fax3Encode2DRow(TIFF *tif, unsigned char *bp, unsigned char *rp,
: 0x7FFFFFFF; : 0x7FFFFFFF;
if (!(-3 <= d && d <= 3)) if (!(-3 <= d && d <= 3))
{ /* horizontal mode */ { /* horizontal mode */
a2 = finddiff2(bp, a1, bits, PIXEL(bp, a1)); a2 = (uint32_t)finddiff2(bp, (int32_t)a1, (int32_t)bits,
(int32_t)PIXEL(bp, a1));
if (!putcode(tif, &horizcode)) if (!putcode(tif, &horizcode))
return 0; return 0;
if (a0 + a1 == 0 || PIXEL(bp, a0) == 0) if (a0 + a1 == 0 || PIXEL(bp, a0) == 0)
{ {
if (!putspan(tif, a1 - a0, TIFFFaxWhiteCodes)) if (!putspan(tif, (int32_t)(a1 - a0), TIFFFaxWhiteCodes))
return 0; return 0;
if (!putspan(tif, a2 - a1, TIFFFaxBlackCodes)) if (!putspan(tif, (int32_t)(a2 - a1), TIFFFaxBlackCodes))
return 0; return 0;
} }
else else
{ {
if (!putspan(tif, a1 - a0, TIFFFaxBlackCodes)) if (!putspan(tif, (int32_t)(a1 - a0), TIFFFaxBlackCodes))
return 0; return 0;
if (!putspan(tif, a2 - a1, TIFFFaxWhiteCodes)) if (!putspan(tif, (int32_t)(a2 - a1), TIFFFaxWhiteCodes))
return 0; return 0;
} }
a0 = a2; a0 = a2;
@@ -1216,9 +1229,12 @@ static int Fax3Encode2DRow(TIFF *tif, unsigned char *bp, unsigned char *rp,
} }
if (a0 >= bits) if (a0 >= bits)
break; break;
a1 = finddiff(bp, a0, bits, PIXEL(bp, a0)); a1 = (uint32_t)finddiff(bp, (int32_t)a0, (int32_t)bits,
b1 = finddiff(rp, a0, bits, !PIXEL(bp, a0)); (int32_t)PIXEL(bp, a0));
b1 = finddiff(rp, b1, bits, PIXEL(bp, a0)); b1 = (uint32_t)finddiff(rp, (int32_t)a0, (int32_t)bits,
(int32_t)!PIXEL(bp, a0));
b1 = (uint32_t)finddiff(rp, (int32_t)b1, (int32_t)bits,
(int32_t)PIXEL(bp, a0));
} }
return (1); return (1);
#undef PIXEL #undef PIXEL
@@ -1487,6 +1503,8 @@ static void Fax3PrintDir(TIFF *tif, FILE *fd, long flags)
case CLEANFAXDATA_UNCLEAN: case CLEANFAXDATA_UNCLEAN:
fprintf(fd, " uncorrected errors"); fprintf(fd, " uncorrected errors");
break; break;
default:
break;
} }
fprintf(fd, " (%" PRIu16 " = 0x%" PRIx16 ")\n", sp->cleanfaxdata, fprintf(fd, " (%" PRIu16 " = 0x%" PRIx16 ")\n", sp->cleanfaxdata,
sp->cleanfaxdata); sp->cleanfaxdata);
@@ -1500,6 +1518,22 @@ static void Fax3PrintDir(TIFF *tif, FILE *fd, long flags)
(*sp->printdir)(tif, fd, flags); (*sp->printdir)(tif, fd, flags);
} }
static uint64_t Fax3GetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* 1024x1024: 36 */
/* 4096x4096: 100 */
/* 16383x16383: 163 */
/* 65536x65536: 200 */
/* 200000x200000: 208 */
return 250;
}
static int InitCCITTFax3(TIFF *tif) static int InitCCITTFax3(TIFF *tif)
{ {
static const char module[] = "InitCCITTFax3"; static const char module[] = "InitCCITTFax3";
@@ -1564,6 +1598,7 @@ static int InitCCITTFax3(TIFF *tif)
tif->tif_encodetile = Fax3Encode; tif->tif_encodetile = Fax3Encode;
tif->tif_close = Fax3Close; tif->tif_close = Fax3Close;
tif->tif_cleanup = Fax3Cleanup; tif->tif_cleanup = Fax3Cleanup;
tif->tif_getmaxcompressionratio = Fax3GetMaxCompressionRatio;
return (1); return (1);
} }
@@ -1626,10 +1661,10 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
RunLength = 0; RunLength = 0;
pa = thisrun = sp->curruns; pa = thisrun = sp->curruns;
pb = sp->refruns; pb = sp->refruns;
b1 = *pb++; b1 = (int)*pb++;
#ifdef FAX3_DEBUG #ifdef FAX3_DEBUG
printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail); printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
printf("-------------------- %d\n", tif->tif_row); printf("-------------------- %d\n", tif->tif_dir.td_row);
fflush(stdout); fflush(stdout);
#endif #endif
EXPAND2D(EOFG4); EXPAND2D(EOFG4);
@@ -1643,7 +1678,7 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
occ, lastx); occ, lastx);
return -1; return -1;
} }
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
SETVALUE(0); /* imaginary change for reference */ SETVALUE(0); /* imaginary change for reference */
SWAP(uint32_t *, sp->curruns, sp->refruns); SWAP(uint32_t *, sp->curruns, sp->refruns);
buf += sp->b.rowbytes; buf += sp->b.rowbytes;
@@ -1666,7 +1701,7 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
occ, lastx); occ, lastx);
return -1; return -1;
} }
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
UNCACHE_STATE(tif, sp); UNCACHE_STATE(tif, sp);
return (sp->line != start return (sp->line != start
? 1 ? 1
@@ -1713,6 +1748,16 @@ static int Fax4PostEncode(TIFF *tif)
return (1); return (1);
} }
static uint64_t Fax4GetMaxCompressionRatio(TIFF *tif)
{
/* FAX4 can compress up to almost one byte per line, so the compression
* ratio can be up to the tile/strip width.
* See README_for_libtiff_developpers.md for raw data
*/
return isTiled(tif) ? tif->tif_dir.td_tilewidth
: tif->tif_dir.td_imagewidth;
}
int TIFFInitCCITTFax4(TIFF *tif, int scheme) int TIFFInitCCITTFax4(TIFF *tif, int scheme)
{ {
(void)scheme; (void)scheme;
@@ -1735,6 +1780,7 @@ int TIFFInitCCITTFax4(TIFF *tif, int scheme)
tif->tif_encodestrip = Fax4Encode; tif->tif_encodestrip = Fax4Encode;
tif->tif_encodetile = Fax4Encode; tif->tif_encodetile = Fax4Encode;
tif->tif_postencode = Fax4PostEncode; tif->tif_postencode = Fax4PostEncode;
tif->tif_getmaxcompressionratio = Fax4GetMaxCompressionRatio;
/* /*
* Suppress RTC at the end of each strip. * Suppress RTC at the end of each strip.
*/ */
@@ -1773,11 +1819,11 @@ static int Fax3DecodeRLE(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
pa = thisrun; pa = thisrun;
#ifdef FAX3_DEBUG #ifdef FAX3_DEBUG
printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail); printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
printf("-------------------- %" PRIu32 "\n", tif->tif_row); printf("-------------------- %" PRIu32 "\n", tif->tif_dir.td_row);
fflush(stdout); fflush(stdout);
#endif #endif
EXPAND1D(EOFRLE); EXPAND1D(EOFRLE);
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
/* /*
* Cleanup at the end of the row. * Cleanup at the end of the row.
*/ */
@@ -1798,7 +1844,7 @@ static int Fax3DecodeRLE(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
sp->line++; sp->line++;
continue; continue;
EOFRLE: /* premature EOF */ EOFRLE: /* premature EOF */
(*sp->fill)(buf, thisrun, pa, lastx); (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
UNCACHE_STATE(tif, sp); UNCACHE_STATE(tif, sp);
return (-1); return (-1);
} }
@@ -1806,6 +1852,21 @@ static int Fax3DecodeRLE(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
return (1); return (1);
} }
static uint64_t Fax3RLEGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* 1024x1024: 43 */
/* 4096x4096: 128 */
/* 16383x16383: 171 */
/* 65536x65536: 205 */
/* 200000x200000: 211 */
return 250;
}
int TIFFInitCCITTRLE(TIFF *tif, int scheme) int TIFFInitCCITTRLE(TIFF *tif, int scheme)
{ {
(void)scheme; (void)scheme;
@@ -1814,6 +1875,7 @@ int TIFFInitCCITTRLE(TIFF *tif, int scheme)
tif->tif_decoderow = Fax3DecodeRLE; tif->tif_decoderow = Fax3DecodeRLE;
tif->tif_decodestrip = Fax3DecodeRLE; tif->tif_decodestrip = Fax3DecodeRLE;
tif->tif_decodetile = Fax3DecodeRLE; tif->tif_decodetile = Fax3DecodeRLE;
tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
/* /*
* Suppress RTC+EOLs when encoding and byte-align data. * Suppress RTC+EOLs when encoding and byte-align data.
*/ */
@@ -1832,6 +1894,7 @@ int TIFFInitCCITTRLEW(TIFF *tif, int scheme)
tif->tif_decoderow = Fax3DecodeRLE; tif->tif_decoderow = Fax3DecodeRLE;
tif->tif_decodestrip = Fax3DecodeRLE; tif->tif_decodestrip = Fax3DecodeRLE;
tif->tif_decodetile = Fax3DecodeRLE; tif->tif_decodetile = Fax3DecodeRLE;
tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
/* /*
* Suppress RTC+EOLs when encoding and word-align data. * Suppress RTC+EOLs when encoding and word-align data.
*/ */

View File

@@ -267,14 +267,14 @@ static const char *StateNames[] = {
{ \ { \
if (pa >= thisrun + sp->nruns) \ if (pa >= thisrun + sp->nruns) \
{ \ { \
TIFFErrorExtR(tif, module, "Buffer overflow at line %u of %s %u", \ TIFFErrorExtR(tif, module, "Buffer overflow at line %d of %s %u", \
sp->line, isTiled(tif) ? "tile" : "strip", \ sp->line, isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_curstrip); \ : tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
*pa++ = RunLength + (x); \ *pa++ = (uint32_t)((uint32_t)RunLength + (uint32_t)(x)); \
a0 += (x); \ a0 += (int)(uint32_t)(x); \
RunLength = 0; \ RunLength = 0; \
} while (0) } while (0)
#endif #endif
@@ -334,20 +334,20 @@ static const char *StateNames[] = {
{ \ { \
if (RunLength) \ if (RunLength) \
SETVALUE(0); \ SETVALUE(0); \
if (a0 != lastx) \ if (a0 != (int)lastx) \
{ \ { \
badlength(a0, lastx); \ badlength(a0, lastx); \
while (a0 > lastx && pa > thisrun) \ while (a0 > (int)lastx && pa > thisrun) \
a0 -= *--pa; \ a0 -= (int)*--pa; \
if (a0 < lastx) \ if (a0 < (int)lastx) \
{ \ { \
if (a0 < 0) \ if (a0 < 0) \
a0 = 0; \ a0 = 0; \
if ((pa - thisrun) & 1) \ if ((pa - thisrun) & 1) \
SETVALUE(0); \ SETVALUE(0); \
SETVALUE(lastx - a0); \ SETVALUE((uint32_t)((int)lastx - a0)); \
} \ } \
else if (a0 > lastx) \ else if (a0 > (int)lastx) \
{ \ { \
SETVALUE(lastx); \ SETVALUE(lastx); \
SETVALUE(0); \ SETVALUE(0); \
@@ -385,8 +385,9 @@ static const char *StateNames[] = {
goto doneWhite1d; \ goto doneWhite1d; \
case S_MakeUpW: \ case S_MakeUpW: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 = (int)((uint32_t)a0 + TabEnt->Param); \
RunLength += TabEnt->Param; \ RunLength = \
(int)((uint32_t)RunLength + TabEnt->Param); \
break; \ break; \
default: \ default: \
unexpected("WhiteTable", a0); \ unexpected("WhiteTable", a0); \
@@ -394,7 +395,7 @@ static const char *StateNames[] = {
} \ } \
} \ } \
doneWhite1d: \ doneWhite1d: \
if (a0 >= lastx) \ if (a0 >= (int)lastx) \
goto done1d; \ goto done1d; \
for (;;) \ for (;;) \
{ \ { \
@@ -409,8 +410,8 @@ static const char *StateNames[] = {
goto doneBlack1d; \ goto doneBlack1d; \
case S_MakeUpB: \ case S_MakeUpB: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 += (int)TabEnt->Param; \
RunLength += TabEnt->Param; \ RunLength += (int)TabEnt->Param; \
break; \ break; \
default: \ default: \
unexpected("BlackTable", a0); \ unexpected("BlackTable", a0); \
@@ -418,7 +419,7 @@ static const char *StateNames[] = {
} \ } \
} \ } \
doneBlack1d: \ doneBlack1d: \
if (a0 >= lastx) \ if (a0 >= (int)lastx) \
goto done1d; \ goto done1d; \
if (*(pa - 1) == 0 && *(pa - 2) == 0) \ if (*(pa - 1) == 0 && *(pa - 2) == 0) \
pa -= 2; \ pa -= 2; \
@@ -439,17 +440,18 @@ static const char *StateNames[] = {
do \ do \
{ \ { \
if (pa != thisrun) \ if (pa != thisrun) \
while (b1 <= a0 && b1 < lastx) \ while (b1 <= a0 && b1 < (int)lastx) \
{ \ { \
if (pb + 1 >= sp->refruns + sp->nruns) \ if (pb + 1 >= sp->refruns + sp->nruns) \
{ \ { \
TIFFErrorExtR( \ TIFFErrorExtR(tif, module, \
tif, module, "Buffer overflow at line %u of %s %u", \ "Buffer overflow at line %d of %s %u", \
sp->line, isTiled(tif) ? "tile" : "strip", \ sp->line, isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip); \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
b1 += pb[0] + pb[1]; \ b1 += (int)(pb[0] + pb[1]); \
pb += 2; \ pb += 2; \
} \ } \
} while (0) } while (0)
@@ -460,14 +462,15 @@ static const char *StateNames[] = {
#define EXPAND2D(eoflab) \ #define EXPAND2D(eoflab) \
do \ do \
{ \ { \
while (a0 < lastx) \ while (a0 < (int)lastx) \
{ \ { \
if (pa >= thisrun + sp->nruns) \ if (pa >= thisrun + sp->nruns) \
{ \ { \
TIFFErrorExtR( \ TIFFErrorExtR(tif, module, \
tif, module, "Buffer overflow at line %u of %s %u", \ "Buffer overflow at line %d of %s %u", sp->line, \
sp->line, isTiled(tif) ? "tile" : "strip", \ isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip); \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
LOOKUP8(7, TIFFFaxMainTable, eof2d); \ LOOKUP8(7, TIFFFaxMainTable, eof2d); \
@@ -477,18 +480,19 @@ static const char *StateNames[] = {
CHECK_b1; \ CHECK_b1; \
if (pb + 1 >= sp->refruns + sp->nruns) \ if (pb + 1 >= sp->refruns + sp->nruns) \
{ \ { \
TIFFErrorExtR(tif, module, \ TIFFErrorExtR( \
"Buffer overflow at line %u of %s %u", \ tif, module, \
sp->line, \ "Buffer overflow at line %d of %s %u", sp->line, \
isTiled(tif) ? "tile" : "strip", \ isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_curstrip); \ : tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
b1 += *pb++; \ b1 = b1 + (int)*pb++; \
RunLength += b1 - a0; \ RunLength = \
(int)((uint32_t)RunLength + (uint32_t)(b1 - a0)); \
a0 = b1; \ a0 = b1; \
b1 += *pb++; \ b1 = b1 + (int)*pb++; \
break; \ break; \
case S_Horiz: \ case S_Horiz: \
if ((pa - thisrun) & 1) \ if ((pa - thisrun) & 1) \
@@ -503,8 +507,9 @@ static const char *StateNames[] = {
goto doneWhite2da; \ goto doneWhite2da; \
case S_MakeUpB: \ case S_MakeUpB: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 = (int)((uint32_t)a0 + TabEnt->Param); \
RunLength += TabEnt->Param; \ RunLength = (int)((uint32_t)RunLength + \
TabEnt->Param); \
break; \ break; \
default: \ default: \
goto badBlack2d; \ goto badBlack2d; \
@@ -521,8 +526,9 @@ static const char *StateNames[] = {
goto doneBlack2da; \ goto doneBlack2da; \
case S_MakeUpW: \ case S_MakeUpW: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 = (int)((uint32_t)a0 + TabEnt->Param); \
RunLength += TabEnt->Param; \ RunLength = (int)((uint32_t)RunLength + \
TabEnt->Param); \
break; \ break; \
default: \ default: \
goto badWhite2d; \ goto badWhite2d; \
@@ -542,8 +548,9 @@ static const char *StateNames[] = {
goto doneWhite2db; \ goto doneWhite2db; \
case S_MakeUpW: \ case S_MakeUpW: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 = (int)((uint32_t)a0 + TabEnt->Param); \
RunLength += TabEnt->Param; \ RunLength = (int)((uint32_t)RunLength + \
TabEnt->Param); \
break; \ break; \
default: \ default: \
goto badWhite2d; \ goto badWhite2d; \
@@ -560,8 +567,9 @@ static const char *StateNames[] = {
goto doneBlack2db; \ goto doneBlack2db; \
case S_MakeUpB: \ case S_MakeUpB: \
case S_MakeUp: \ case S_MakeUp: \
a0 += TabEnt->Param; \ a0 = (int)((uint32_t)a0 + TabEnt->Param); \
RunLength += TabEnt->Param; \ RunLength = (int)((uint32_t)RunLength + \
TabEnt->Param); \
break; \ break; \
default: \ default: \
goto badBlack2d; \ goto badBlack2d; \
@@ -576,47 +584,47 @@ static const char *StateNames[] = {
SETVALUE(b1 - a0); \ SETVALUE(b1 - a0); \
if (pb >= sp->refruns + sp->nruns) \ if (pb >= sp->refruns + sp->nruns) \
{ \ { \
TIFFErrorExtR(tif, module, \ TIFFErrorExtR( \
"Buffer overflow at line %u of %s %u", \ tif, module, \
sp->line, \ "Buffer overflow at line %d of %s %u", sp->line, \
isTiled(tif) ? "tile" : "strip", \ isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_curstrip); \ : tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
b1 += *pb++; \ b1 = b1 + (int)*pb++; \
break; \ break; \
case S_VR: \ case S_VR: \
CHECK_b1; \ CHECK_b1; \
SETVALUE(b1 - a0 + TabEnt->Param); \ SETVALUE((int)((uint32_t)(b1 - a0) + TabEnt->Param)); \
if (pb >= sp->refruns + sp->nruns) \ if (pb >= sp->refruns + sp->nruns) \
{ \ { \
TIFFErrorExtR(tif, module, \ TIFFErrorExtR( \
"Buffer overflow at line %u of %s %u", \ tif, module, \
sp->line, \ "Buffer overflow at line %d of %s %u", sp->line, \
isTiled(tif) ? "tile" : "strip", \ isTiled(tif) ? "tile" : "strip", \
isTiled(tif) ? tif->tif_curtile \ isTiled(tif) ? tif->tif_dir.td_curtile \
: tif->tif_curstrip); \ : tif->tif_dir.td_curstrip); \
return (-1); \ return (-1); \
} \ } \
b1 += *pb++; \ b1 = b1 + (int)*pb++; \
break; \ break; \
case S_VL: \ case S_VL: \
CHECK_b1; \ CHECK_b1; \
if (b1 < (int)(a0 + TabEnt->Param)) \ if (b1 < (int)((uint32_t)a0 + TabEnt->Param)) \
{ \ { \
unexpected("VL", a0); \ unexpected("VL", a0); \
goto eol2d; \ goto eol2d; \
} \ } \
SETVALUE(b1 - a0 - TabEnt->Param); \ SETVALUE((int)((uint32_t)(b1 - a0) - TabEnt->Param)); \
b1 -= *--pb; \ b1 = b1 - (int)*--pb; \
break; \ break; \
case S_Ext: \ case S_Ext: \
*pa++ = lastx - a0; \ *pa++ = (uint32_t)((int)lastx - a0); \
extension(a0); \ extension(a0); \
goto eol2d; \ goto eol2d; \
case S_EOL: \ case S_EOL: \
*pa++ = lastx - a0; \ *pa++ = (uint32_t)((int)lastx - a0); \
NeedBits8(4, eof2d); \ NeedBits8(4, eof2d); \
if (GetBits(4)) \ if (GetBits(4)) \
unexpected("EOL", a0); \ unexpected("EOL", a0); \

File diff suppressed because it is too large Load Diff

View File

@@ -76,7 +76,7 @@ static const int anPrimes[] = {
100663319, 201326611, 402653189, 805306457, 1610612741}; 100663319, 201326611, 402653189, 805306457, 1610612741};
/************************************************************************/ /************************************************************************/
/* TIFFHashSetHashPointer() */ /* TIFFHashSetHashPointer() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -93,7 +93,7 @@ static unsigned long TIFFHashSetHashPointer(const void *elt)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetEqualPointer() */ /* TIFFHashSetEqualPointer() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -111,7 +111,7 @@ static bool TIFFHashSetEqualPointer(const void *elt1, const void *elt2)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetNew() */ /* TIFFHashSetNew() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -164,7 +164,7 @@ TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc,
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetSize() */ /* TIFFHashSetSize() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -184,7 +184,7 @@ int TIFFHashSetSize(const TIFFHashSet *set)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetGetNewListElt() */ /* TIFFHashSetGetNewListElt() */
/************************************************************************/ /************************************************************************/
static TIFFList *TIFFHashSetGetNewListElt(TIFFHashSet *set) static TIFFList *TIFFHashSetGetNewListElt(TIFFHashSet *set)
@@ -202,7 +202,7 @@ static TIFFList *TIFFHashSetGetNewListElt(TIFFHashSet *set)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetReturnListElt() */ /* TIFFHashSetReturnListElt() */
/************************************************************************/ /************************************************************************/
static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList) static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList)
@@ -220,7 +220,7 @@ static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetClearInternal() */ /* TIFFHashSetClearInternal() */
/************************************************************************/ /************************************************************************/
static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize) static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize)
@@ -246,7 +246,7 @@ static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize)
} }
/************************************************************************/ /************************************************************************/
/* TIFFListDestroy() */ /* TIFFListDestroy() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -270,7 +270,7 @@ static void TIFFListDestroy(TIFFList *psList)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetDestroy() */ /* TIFFHashSetDestroy() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -295,7 +295,7 @@ void TIFFHashSetDestroy(TIFFHashSet *set)
#ifdef notused #ifdef notused
/************************************************************************/ /************************************************************************/
/* TIFFHashSetClear() */ /* TIFFHashSetClear() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -319,7 +319,7 @@ void TIFFHashSetClear(TIFFHashSet *set)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetForeach() */ /* TIFFHashSetForeach() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -360,14 +360,14 @@ void TIFFHashSetForeach(TIFFHashSet *set, TIFFHashSetIterEltFunc fnIterFunc,
#endif #endif
/************************************************************************/ /************************************************************************/
/* TIFFHashSetRehash() */ /* TIFFHashSetRehash() */
/************************************************************************/ /************************************************************************/
static bool TIFFHashSetRehash(TIFFHashSet *set) static bool TIFFHashSetRehash(TIFFHashSet *set)
{ {
int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize]; int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
TIFFList **newTabList = TIFFList **newTabList =
(TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *))); (TIFFList **)(calloc((size_t)nNewAllocatedSize, sizeof(TIFFList *)));
if (newTabList == NULL) if (newTabList == NULL)
return false; return false;
#ifdef HASH_DEBUG #ifdef HASH_DEBUG
@@ -384,7 +384,7 @@ static bool TIFFHashSetRehash(TIFFHashSet *set)
while (cur) while (cur)
{ {
const unsigned long nNewHashVal = const unsigned long nNewHashVal =
set->fnHashFunc(cur->pData) % nNewAllocatedSize; set->fnHashFunc(cur->pData) % (unsigned long)nNewAllocatedSize;
#ifdef HASH_DEBUG #ifdef HASH_DEBUG
if (newTabList[nNewHashVal]) if (newTabList[nNewHashVal])
set->nCollisions++; set->nCollisions++;
@@ -403,12 +403,13 @@ static bool TIFFHashSetRehash(TIFFHashSet *set)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetFindPtr() */ /* TIFFHashSetFindPtr() */
/************************************************************************/ /************************************************************************/
static void **TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt) static void **TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt)
{ {
const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize; const unsigned long nHashVal =
set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize;
TIFFList *cur = set->tabList[nHashVal]; TIFFList *cur = set->tabList[nHashVal];
while (cur) while (cur)
{ {
@@ -464,7 +465,8 @@ bool TIFFHashSetInsert(TIFFHashSet *set, void *elt)
} }
} }
const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize; const unsigned long nHashVal =
set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize;
#ifdef HASH_DEBUG #ifdef HASH_DEBUG
if (set->tabList[nHashVal]) if (set->tabList[nHashVal])
set->nCollisions++; set->nCollisions++;
@@ -486,7 +488,7 @@ bool TIFFHashSetInsert(TIFFHashSet *set, void *elt)
} }
/************************************************************************/ /************************************************************************/
/* TIFFHashSetLookup() */ /* TIFFHashSetLookup() */
/************************************************************************/ /************************************************************************/
/** /**
@@ -532,7 +534,8 @@ static bool TIFFHashSetRemoveInternal(TIFFHashSet *set, const void *elt,
} }
} }
int nHashVal = (int)(set->fnHashFunc(elt) % set->nAllocatedSize); int nHashVal =
(int)(set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize);
TIFFList *cur = set->tabList[nHashVal]; TIFFList *cur = set->tabList[nHashVal];
TIFFList *prev = NULL; TIFFList *prev = NULL;
while (cur) while (cur)
@@ -581,7 +584,7 @@ bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt)
#ifdef notused #ifdef notused
/************************************************************************/ /************************************************************************/
/* TIFFHashSetRemoveDeferRehash() */ /* TIFFHashSetRemoveDeferRehash() */
/************************************************************************/ /************************************************************************/
/** /**

View File

@@ -33,7 +33,14 @@
#include "tiffiop.h" #include "tiffiop.h"
#ifdef JBIG_SUPPORT #ifdef JBIG_SUPPORT
#ifdef __cplusplus
extern "C"
{
#endif
#include "jbig.h" #include "jbig.h"
#ifdef __cplusplus
}
#endif
static int JBIGSetupDecode(TIFF *tif) static int JBIGSetupDecode(TIFF *tif)
{ {
@@ -100,7 +107,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
decodedSize = jbg_dec_getsize(&decoder); decodedSize = jbg_dec_getsize(&decoder);
if ((tmsize_t)decodedSize < size) if ((tmsize_t)decodedSize < size)
{ {
memset(buffer + decodedSize, 0, (size_t)(size - decodedSize)); memset(buffer + decodedSize, 0, (size_t)(size - (tmsize_t)decodedSize));
TIFFWarningExtR(tif, "JBIG", TIFFWarningExtR(tif, "JBIG",
"Only decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT "Only decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT
" requested", " requested",
@@ -116,7 +123,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
return 0; return 0;
} }
pImage = jbg_dec_getimage(&decoder, 0); pImage = jbg_dec_getimage(&decoder, 0);
_TIFFmemcpy(buffer, pImage, decodedSize); _TIFFmemcpy(buffer, pImage, (tmsize_t)decodedSize);
jbg_dec_free(&decoder); jbg_dec_free(&decoder);
tif->tif_rawcp += tif->tif_rawcc; tif->tif_rawcp += tif->tif_rawcc;

View File

@@ -22,9 +22,6 @@
* OF THIS SOFTWARE. * OF THIS SOFTWARE.
*/ */
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include "tiffiop.h" #include "tiffiop.h"
#include <stdlib.h> #include <stdlib.h>
@@ -146,20 +143,9 @@ int TIFFJPEGIsFullStripRequired_12(TIFF *tif);
#define LONGJMP(jbuf, code) longjmp(jbuf, code) #define LONGJMP(jbuf, code) longjmp(jbuf, code)
#define JMP_BUF jmp_buf #define JMP_BUF jmp_buf
#ifndef TIFF_jpeg_destination_mgr_defined typedef struct jpeg_destination_mgr tiff_jpeg_destination_mgr;
#define TIFF_jpeg_destination_mgr_defined typedef struct jpeg_source_mgr tiff_jpeg_source_mgr;
typedef struct jpeg_destination_mgr jpeg_destination_mgr; typedef struct jpeg_error_mgr tiff_jpeg_error_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 * State block for each open TIFF file using
@@ -174,6 +160,10 @@ typedef struct jpeg_error_mgr jpeg_error_mgr;
* so we can safely cast JPEGState* -> jpeg_xxx_struct* * so we can safely cast JPEGState* -> jpeg_xxx_struct*
* and vice versa! * and vice versa!
*/ */
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4324) /* structure padding due to alignment */
#endif
typedef struct typedef struct
{ {
union union
@@ -184,22 +174,24 @@ typedef struct
} cinfo; /* NB: must be first */ } cinfo; /* NB: must be first */
int cinfo_initialized; int cinfo_initialized;
jpeg_error_mgr err; /* libjpeg error manager */ tiff_jpeg_error_mgr err; /* libjpeg error manager */
JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */
struct jpeg_progress_mgr progress; struct jpeg_progress_mgr progress;
/* /*
* The following two members could be a union, but * The following two members could be a union, but
* they're small enough that it's not worth the effort. * they're small enough that it's not worth the effort.
*/ */
jpeg_destination_mgr dest; /* data dest for compression */ tiff_jpeg_destination_mgr dest; /* data dest for compression */
jpeg_source_mgr src; /* data source for decompression */ tiff_jpeg_source_mgr src; /* data source for decompression */
/* private state */ /* private state */
TIFF *tif; /* back link needed by some code */ TIFF *tif; /* back link needed by some code */
uint16_t photometric; /* copy of PhotometricInterpretation */ uint16_t photometric; /* copy of PhotometricInterpretation */
uint16_t h_sampling; /* luminance sampling factors */ uint16_t h_sampling; /* luminance sampling factors */
uint16_t v_sampling; uint16_t v_sampling;
tmsize_t bytesperline; /* decompressed bytes per scanline */ tmsize_t bytesperline; /* decompressed bytes per scanline */
uint32_t strile_width;
uint32_t strile_height;
/* pointers to intermediate buffers when processing downsampled data */ /* pointers to intermediate buffers when processing downsampled data */
TIFF_JSAMPARRAY ds_buffer[MAX_COMPONENTS]; TIFF_JSAMPARRAY ds_buffer[MAX_COMPONENTS];
int scancount; /* number of "scanlines" accumulated */ int scancount; /* number of "scanlines" accumulated */
@@ -209,6 +201,9 @@ typedef struct
int encode_raw_error; int encode_raw_error;
} JPEGState; } JPEGState;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#define JState(tif) ((JPEGState *)(tif)->tif_data) #define JState(tif) ((JPEGState *)(tif)->tif_data)
@@ -559,7 +554,7 @@ static boolean tables_empty_output_buffer(j_compress_ptr cinfo)
/* the entire buffer has been filled; enlarge it by 1000 bytes */ /* the entire buffer has been filled; enlarge it by 1000 bytes */
newbuf = newbuf =
_TIFFreallocExt(sp->tif, (void *)sp->otherSettings.jpegtables, _TIFFreallocExt(sp->tif, (void *)sp->otherSettings.jpegtables,
(tmsize_t)(sp->otherSettings.jpegtables_length + 1000)); (tmsize_t)sp->otherSettings.jpegtables_length + 1000);
if (newbuf == NULL) if (newbuf == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100);
sp->dest.next_output_byte = sp->dest.next_output_byte =
@@ -912,7 +907,7 @@ JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData *data)
return (0); return (0);
if (n < 2) if (n < 2)
return (0); return (0);
n -= 2; n = (uint16_t)(n - 2);
if (n > 0) if (n > 0)
JPEGFixupTagsSubsamplingSkip(data, n); JPEGFixupTagsSubsamplingSkip(data, n);
} }
@@ -1016,7 +1011,7 @@ JPEGFixupTagsSubsamplingReadByte(struct JPEGFixupTagsSubsamplingData *data,
assert(m < 0x80000000UL); assert(m < 0x80000000UL);
if (TIFFReadFile(data->tif, data->buffer, (tmsize_t)m) != (tmsize_t)m) if (TIFFReadFile(data->tif, data->buffer, (tmsize_t)m) != (tmsize_t)m)
return (0); return (0);
data->buffercurrentbyte = data->buffer; data->buffercurrentbyte = (uint8_t *)data->buffer;
data->bufferbytesleft = m; data->bufferbytesleft = m;
data->fileoffset += m; data->fileoffset += m;
data->filebytesleft -= m; data->filebytesleft -= m;
@@ -1037,7 +1032,7 @@ JPEGFixupTagsSubsamplingReadWord(struct JPEGFixupTagsSubsamplingData *data,
return (0); return (0);
if (!JPEGFixupTagsSubsamplingReadByte(data, &mb)) if (!JPEGFixupTagsSubsamplingReadByte(data, &mb))
return (0); return (0);
*result = (ma << 8) | mb; *result = (uint16_t)((ma << 8) | mb);
return (1); return (1);
} }
@@ -1159,6 +1154,47 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
return ret; return ret;
} }
static int JPEGComputeStrileWidthHeightBytesPerLine(TIFF *tif, uint16_t s)
{
JPEGState *sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
/*
* Check image parameters and set decompression parameters.
*/
if (isTiled(tif))
{
sp->strile_width = td->td_tilewidth;
sp->strile_height = td->td_tilelength;
sp->bytesperline = TIFFTileRowSize(tif);
}
else
{
sp->strile_width = td->td_imagewidth;
sp->strile_height = td->td_imagelength - tif->tif_dir.td_row;
if (sp->strile_height > td->td_rowsperstrip)
sp->strile_height = td->td_rowsperstrip;
sp->bytesperline = TIFFScanlineSize(tif);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
{
/*
* 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, "JPEGComputeStrileWidthHeightBytesPerLine",
"JPEG horizontal or vertical sampling is zero");
return (0);
}
sp->strile_width = TIFFhowmany_32(sp->strile_width, sp->h_sampling);
sp->strile_height = TIFFhowmany_32(sp->strile_height, sp->v_sampling);
}
return 1;
}
/* /*
* Set up for decoding a strip or tile. * Set up for decoding a strip or tile.
*/ */
@@ -1167,7 +1203,6 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
JPEGState *sp = JState(tif); JPEGState *sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
static const char module[] = "JPEGPreDecode"; static const char module[] = "JPEGPreDecode";
uint32_t segment_width, segment_height;
int downsampled_output; int downsampled_output;
int ci; int ci;
@@ -1193,52 +1228,24 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
return (0); return (0);
tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
tif->tif_rawcc = sp->src.bytes_in_buffer; tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
/* if (!JPEGComputeStrileWidthHeightBytesPerLine(tif, s))
* Check image parameters and set decompression parameters. return 0;
*/
if (isTiled(tif)) if (sp->cinfo.d.image_width < sp->strile_width ||
{ sp->cinfo.d.image_height < sp->strile_height)
segment_width = td->td_tilewidth;
segment_height = td->td_tilelength;
sp->bytesperline = TIFFTileRowSize(tif);
}
else
{
segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row;
if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip;
sp->bytesperline = TIFFScanlineSize(tif);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
{
/*
* 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);
}
if (sp->cinfo.d.image_width < segment_width ||
sp->cinfo.d.image_height < segment_height)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"Improper JPEG strip/tile size, " "Improper JPEG strip/tile size, "
"expected %" PRIu32 "x%" PRIu32 ", got %ux%u", "expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
segment_width, segment_height, sp->cinfo.d.image_width, sp->strile_width, sp->strile_height,
sp->cinfo.d.image_height); sp->cinfo.d.image_width, sp->cinfo.d.image_height);
} }
if (sp->cinfo.d.image_width == segment_width && if (sp->cinfo.d.image_width == sp->strile_width &&
sp->cinfo.d.image_height > segment_height && sp->cinfo.d.image_height > sp->strile_height &&
tif->tif_row + segment_height == td->td_imagelength && !isTiled(tif)) tif->tif_dir.td_row + sp->strile_height == td->td_imagelength &&
!isTiled(tif))
{ {
/* Some files have a last strip, that should be truncated, */ /* Some files have a last strip, that should be truncated, */
/* but their JPEG codestream has still the maximum strip */ /* but their JPEG codestream has still the maximum strip */
@@ -1247,11 +1254,11 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"JPEG strip size exceeds expected dimensions," "JPEG strip size exceeds expected dimensions,"
" expected %" PRIu32 "x%" PRIu32 ", got %ux%u", " expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
segment_width, segment_height, sp->cinfo.d.image_width, sp->strile_width, sp->strile_height,
sp->cinfo.d.image_height); sp->cinfo.d.image_width, sp->cinfo.d.image_height);
} }
else if (sp->cinfo.d.image_width > segment_width || else if (sp->cinfo.d.image_width > sp->strile_width ||
sp->cinfo.d.image_height > segment_height) sp->cinfo.d.image_height > sp->strile_height)
{ {
/* /*
* This case could be dangerous, if the strip or tile size has * This case could be dangerous, if the strip or tile size has
@@ -1262,8 +1269,8 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"JPEG strip/tile size exceeds expected dimensions," "JPEG strip/tile size exceeds expected dimensions,"
" expected %" PRIu32 "x%" PRIu32 ", got %ux%u", " expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
segment_width, segment_height, sp->cinfo.d.image_width, sp->strile_width, sp->strile_height,
sp->cinfo.d.image_height); sp->cinfo.d.image_width, sp->cinfo.d.image_height);
return (0); return (0);
} }
if (sp->cinfo.d.num_components != if (sp->cinfo.d.num_components !=
@@ -1282,7 +1289,8 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
sp->cinfo.d.data_precision = td->td_bitspersample; sp->cinfo.d.data_precision = td->td_bitspersample;
sp->cinfo.d.bits_in_jsample = td->td_bitspersample; sp->cinfo.d.bits_in_jsample = td->td_bitspersample;
#else #else
if (sp->cinfo.d.data_precision != td->td_bitspersample) if (td->td_bitspersample != BITS_IN_JSAMPLE ||
sp->cinfo.d.data_precision != td->td_bitspersample)
{ {
TIFFErrorExtR(tif, module, "Improper JPEG data precision"); TIFFErrorExtR(tif, module, "Improper JPEG data precision");
return (0); return (0);
@@ -1319,11 +1327,12 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
if (compptr->h_samp_factor > 0 && compptr->v_samp_factor > 0) if (compptr->h_samp_factor > 0 && compptr->v_samp_factor > 0)
{ {
nRequiredMemory += nRequiredMemory +=
(toff_t)(((compptr->width_in_blocks + (toff_t)((JDIMENSION)(((int)compptr->width_in_blocks +
compptr->h_samp_factor - 1) / compptr->h_samp_factor - 1) /
compptr->h_samp_factor)) * compptr->h_samp_factor)) *
((compptr->height_in_blocks + compptr->v_samp_factor - 1) / (JDIMENSION)(((int)compptr->height_in_blocks +
compptr->v_samp_factor) * compptr->v_samp_factor - 1) /
compptr->v_samp_factor) *
sizeof(JBLOCK); sizeof(JBLOCK);
} }
} }
@@ -1439,7 +1448,7 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
* Decode a chunk of pixels. * Decode a chunk of pixels.
* "Standard" case: returned data is not downsampled. * "Standard" case: returned data is not downsampled.
*/ */
#if !JPEG_LIB_MK1_OR_12BIT #if !defined(JPEG_LIB_MK1_OR_12BIT)
static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
{ {
JPEGState *sp = JState(tif); JPEGState *sp = JState(tif);
@@ -1464,7 +1473,18 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read"); TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read");
if (nrows > (tmsize_t)sp->cinfo.d.image_height) if (nrows > (tmsize_t)sp->cinfo.d.image_height)
{
/* Initialize the output buffer if the JPEG image is smaller than the
* strile height. */
memset(buf, 0, (size_t)cc);
nrows = sp->cinfo.d.image_height; nrows = sp->cinfo.d.image_height;
}
else if (sp->strile_width > sp->cinfo.d.image_width)
{
/* Initialize the output buffer if the JPEG image is smaller than the
* strile width. */
memset(buf, 0, (size_t)cc);
}
/* data is expected to be read in multiples of a scanline */ /* data is expected to be read in multiples of a scanline */
if (nrows) if (nrows)
@@ -1483,7 +1503,7 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
return (0); return (0);
} }
++tif->tif_row; ++tif->tif_dir.td_row;
buf += sp->bytesperline; buf += sp->bytesperline;
cc -= sp->bytesperline; cc -= sp->bytesperline;
} while (--nrows > 0); } while (--nrows > 0);
@@ -1491,15 +1511,15 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
/* Update information on consumed data */ /* Update information on consumed data */
tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
tif->tif_rawcc = sp->src.bytes_in_buffer; tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
/* Close down the decompressor if we've finished the strip or tile. */ /* Close down the decompressor if we've finished the strip or tile. */
return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height ||
TIFFjpeg_finish_decompress(sp); TIFFjpeg_finish_decompress(sp);
} }
#endif /* !JPEG_LIB_MK1_OR_12BIT */ #endif /* !defined(JPEG_LIB_MK1_OR_12BIT) */
#if JPEG_LIB_MK1_OR_12BIT #if defined(JPEG_LIB_MK1_OR_12BIT)
/*ARGSUSED*/ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, /*ARGSUSED*/ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc,
uint16_t s) uint16_t s)
{ {
@@ -1525,7 +1545,18 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read"); TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read");
if (nrows > (tmsize_t)sp->cinfo.d.image_height) if (nrows > (tmsize_t)sp->cinfo.d.image_height)
{
/* Initialize the output buffer if the JPEG image is smaller than the
* strile height. */
memset(buf, 0, (size_t)cc);
nrows = sp->cinfo.d.image_height; nrows = sp->cinfo.d.image_height;
}
else if (sp->strile_width > sp->cinfo.d.image_width)
{
/* Initialize the output buffer if the JPEG image is smaller than the
* strile width. */
memset(buf, 0, (size_t)cc);
}
/* data is expected to be read in multiples of a scanline */ /* data is expected to be read in multiples of a scanline */
if (nrows) if (nrows)
@@ -1539,8 +1570,9 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
if (sp->cinfo.d.data_precision == 12) if (sp->cinfo.d.data_precision == 12)
{ {
line_work_buf = (TIFF_JSAMPROW)_TIFFmallocExt( line_work_buf = (TIFF_JSAMPROW)_TIFFmallocExt(
tif, sizeof(short) * sp->cinfo.d.output_width * tif, (tmsize_t)((size_t)sizeof(short) *
sp->cinfo.d.num_components); (size_t)sp->cinfo.d.output_width *
(size_t)sp->cinfo.d.num_components));
} }
do do
@@ -1556,14 +1588,16 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
{ {
memset(buf, 0, (size_t)cc); memset(buf, 0, (size_t)cc);
_TIFFfreeExt(tif, line_work_buf);
return (0); return (0);
} }
if (sp->cinfo.d.data_precision == 12) if (sp->cinfo.d.data_precision == 12)
{ {
int value_pairs = (sp->cinfo.d.output_width * int value_pairs =
sp->cinfo.d.num_components) / (int)((JDIMENSION)sp->cinfo.d.output_width *
2; (JDIMENSION)sp->cinfo.d.num_components) /
2;
int iPair; int iPair;
for (iPair = 0; iPair < value_pairs; iPair++) for (iPair = 0; iPair < value_pairs; iPair++)
@@ -1582,18 +1616,19 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
else if (sp->cinfo.d.data_precision == 8) else if (sp->cinfo.d.data_precision == 8)
{ {
int value_count = int value_count =
(sp->cinfo.d.output_width * sp->cinfo.d.num_components); (int)((JDIMENSION)sp->cinfo.d.output_width *
(JDIMENSION)sp->cinfo.d.num_components);
int iValue; int iValue;
for (iValue = 0; iValue < value_count; iValue++) for (iValue = 0; iValue < value_count; iValue++)
{ {
((unsigned char *)buf)[iValue] = ((unsigned char *)buf)[iValue] =
line_work_buf[iValue] & 0xff; (unsigned char)(line_work_buf[iValue] & 0xff);
} }
} }
} }
++tif->tif_row; ++tif->tif_dir.td_row;
buf += sp->bytesperline; buf += sp->bytesperline;
cc -= sp->bytesperline; cc -= sp->bytesperline;
} while (--nrows > 0); } while (--nrows > 0);
@@ -1604,13 +1639,13 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
/* Update information on consumed data */ /* Update information on consumed data */
tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
tif->tif_rawcc = sp->src.bytes_in_buffer; tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
/* Close down the decompressor if we've finished the strip or tile. */ /* Close down the decompressor if we've finished the strip or tile. */
return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height ||
TIFFjpeg_finish_decompress(sp); TIFFjpeg_finish_decompress(sp);
} }
#endif /* JPEG_LIB_MK1_OR_12BIT */ #endif /* defined(JPEG_LIB_MK1_OR_12BIT) */
/*ARGSUSED*/ static int DecodeRowError(TIFF *tif, uint8_t *buf, tmsize_t cc, /*ARGSUSED*/ static int DecodeRowError(TIFF *tif, uint8_t *buf, tmsize_t cc,
uint16_t s) uint16_t s)
@@ -1644,8 +1679,16 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
/* For last strip, limit number of rows to its truncated height */ /* For last strip, limit number of rows to its truncated height */
/* even if the codestream height is larger (which is not compliant, */ /* even if the codestream height is larger (which is not compliant, */
/* but that we tolerate) */ /* but that we tolerate) */
if ((uint32_t)nrows > td->td_imagelength - tif->tif_row && !isTiled(tif)) if ((uint32_t)nrows > td->td_imagelength - tif->tif_dir.td_row &&
nrows = td->td_imagelength - tif->tif_row; !isTiled(tif))
nrows = td->td_imagelength - tif->tif_dir.td_row;
/* The downsampled-data decode loop below only writes up to the JPEG
* codestream dimensions (and, due to the clump stride, may not cover the
* full caller buffer even for compliant files). Zero the whole buffer so
* no uninitialised heap is ever returned, mirroring the guard JPEGDecode
* received in 65759931ab6e (#826). */
memset(buf, 0, (size_t)cc);
#if defined(JPEG_LIB_MK1_OR_12BIT) #if defined(JPEG_LIB_MK1_OR_12BIT)
unsigned short *tmpbuf = NULL; unsigned short *tmpbuf = NULL;
@@ -1660,9 +1703,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
int samples_per_clump = sp->samplesperclump; int samples_per_clump = sp->samplesperclump;
#if defined(JPEG_LIB_MK1_OR_12BIT) #if defined(JPEG_LIB_MK1_OR_12BIT)
tmpbuf = _TIFFmallocExt(tif, sizeof(unsigned short) * tmpbuf = (unsigned short *)_TIFFmallocExt(
sp->cinfo.d.output_width * tif, (tmsize_t)((size_t)sizeof(unsigned short) *
sp->cinfo.d.num_components); (size_t)sp->cinfo.d.output_width *
(size_t)sp->cinfo.d.num_components));
if (tmpbuf == NULL) if (tmpbuf == NULL)
{ {
TIFFErrorExtR(tif, "JPEGDecodeRaw", "Out of memory"); TIFFErrorExtR(tif, "JPEGDecodeRaw", "Out of memory");
@@ -1755,18 +1799,20 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
if (sp->cinfo.d.data_precision == 8) if (sp->cinfo.d.data_precision == 8)
{ {
int i = 0; int i = 0;
int len = int len = (int)((JDIMENSION)sp->cinfo.d.output_width *
sp->cinfo.d.output_width * sp->cinfo.d.num_components; (JDIMENSION)sp->cinfo.d.num_components);
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
((unsigned char *)buf)[i] = tmpbuf[i] & 0xff; ((unsigned char *)buf)[i] =
(unsigned char)(tmpbuf[i] & 0xff);
} }
} }
else else
{ /* 12-bit */ { /* 12-bit */
int value_pairs = (sp->cinfo.d.output_width * int value_pairs =
sp->cinfo.d.num_components) / (int)((JDIMENSION)sp->cinfo.d.output_width *
2; (JDIMENSION)sp->cinfo.d.num_components) /
2;
int iPair; int iPair;
for (iPair = 0; iPair < value_pairs; iPair++) for (iPair = 0; iPair < value_pairs; iPair++)
{ {
@@ -1785,7 +1831,7 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
#endif #endif
sp->scancount++; sp->scancount++;
tif->tif_row += sp->v_sampling; tif->tif_dir.td_row += sp->v_sampling;
buf += sp->bytesperline; buf += sp->bytesperline;
cc -= sp->bytesperline; cc -= sp->bytesperline;
@@ -2024,9 +2070,9 @@ static int JPEGSetupEncode(TIFF *tif)
if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &ref)) if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &ref))
{ {
float refbw[6]; float refbw[6];
long top = 1L << td->td_bitspersample; uint32_t top = 1U << td->td_bitspersample;
refbw[0] = 0; refbw[0] = 0;
refbw[1] = (float)(top - 1L); refbw[1] = (float)(top - 1);
refbw[2] = (float)(top >> 1); refbw[2] = (float)(top >> 1);
refbw[3] = refbw[1]; refbw[3] = refbw[1];
refbw[4] = refbw[2]; refbw[4] = refbw[2];
@@ -2074,30 +2120,30 @@ static int JPEGSetupEncode(TIFF *tif)
#endif #endif
if (isTiled(tif)) if (isTiled(tif))
{ {
if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) if ((td->td_tilelength % ((uint32_t)sp->v_sampling * DCTSIZE)) != 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"JPEG tile height must be multiple of %" PRIu32, "JPEG tile height must be multiple of %" PRIu32,
(uint32_t)(sp->v_sampling * DCTSIZE)); (uint32_t)sp->v_sampling * DCTSIZE);
return (0); return (0);
} }
if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) if ((td->td_tilewidth % ((uint32_t)sp->h_sampling * DCTSIZE)) != 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"JPEG tile width must be multiple of %" PRIu32, "JPEG tile width must be multiple of %" PRIu32,
(uint32_t)(sp->h_sampling * DCTSIZE)); (uint32_t)sp->h_sampling * DCTSIZE);
return (0); return (0);
} }
} }
else else
{ {
if (td->td_rowsperstrip < td->td_imagelength && if (td->td_rowsperstrip < td->td_imagelength &&
(td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) (td->td_rowsperstrip % ((uint32_t)sp->v_sampling * DCTSIZE)) != 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"RowsPerStrip must be multiple of %" PRIu32 "RowsPerStrip must be multiple of %" PRIu32
" for JPEG", " for JPEG",
(uint32_t)(sp->v_sampling * DCTSIZE)); (uint32_t)sp->v_sampling * DCTSIZE);
return (0); return (0);
} }
} }
@@ -2153,7 +2199,6 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s)
JPEGState *sp = JState(tif); JPEGState *sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
static const char module[] = "JPEGPreEncode"; static const char module[] = "JPEGPreEncode";
uint32_t segment_width, segment_height;
int downsampled_input; int downsampled_input;
assert(sp != NULL); assert(sp != NULL);
@@ -2164,47 +2209,20 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s)
} }
assert(!sp->cinfo.comm.is_decompressor); assert(!sp->cinfo.comm.is_decompressor);
/*
* Set encoding parameters for this strip/tile. if (!JPEGComputeStrileWidthHeightBytesPerLine(tif, s))
*/ return 0;
if (isTiled(tif))
{ if (sp->strile_width > (uint32_t)JPEG_MAX_DIMENSION ||
segment_width = td->td_tilewidth; sp->strile_height > (uint32_t)JPEG_MAX_DIMENSION)
segment_height = td->td_tilelength;
sp->bytesperline = TIFFTileRowSize(tif);
}
else
{
segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row;
if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip;
sp->bytesperline = TIFFScanlineSize(tif);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
{
/* 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);
}
if (segment_width > (uint32_t)JPEG_MAX_DIMENSION ||
segment_height > (uint32_t)JPEG_MAX_DIMENSION)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Strip/tile too large for JPEG. Maximum dimension is %d", "Strip/tile too large for JPEG. Maximum dimension is %d",
(int)JPEG_MAX_DIMENSION); (int)JPEG_MAX_DIMENSION);
return (0); return (0);
} }
sp->cinfo.c.image_width = segment_width; sp->cinfo.c.image_width = sp->strile_width;
sp->cinfo.c.image_height = segment_height; sp->cinfo.c.image_height = sp->strile_height;
downsampled_input = FALSE; downsampled_input = FALSE;
if (td->td_planarconfig == PLANARCONFIG_CONTIG) if (td->td_planarconfig == PLANARCONFIG_CONTIG)
{ {
@@ -2276,7 +2294,13 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s)
/* an existing file */ /* an existing file */
suppress_huff_table(sp, 0); suppress_huff_table(sp, 0);
suppress_huff_table(sp, 1); suppress_huff_table(sp, 1);
sp->cinfo.c.optimize_coding = FALSE;
/* We want to keep optimize_coding = TRUE for 12-bit JPEG */
/* See lengthy explanation at
* https://gitlab.com/libtiff/libtiff/-/work_items/773#note_3009836854
*/
if (sp->cinfo.c.data_precision == 8)
sp->cinfo.c.optimize_coding = FALSE;
} }
else else
sp->cinfo.c.optimize_coding = TRUE; sp->cinfo.c.optimize_coding = TRUE;
@@ -2332,13 +2356,15 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
TIFFWarningExtR(tif, tif->tif_name, "fractional scanline discarded"); TIFFWarningExtR(tif, tif->tif_name, "fractional scanline discarded");
/* The last strip will be limited to image size */ /* The last strip will be limited to image size */
if (!isTiled(tif) && tif->tif_row + nrows > tif->tif_dir.td_imagelength) if (!isTiled(tif) &&
nrows = tif->tif_dir.td_imagelength - tif->tif_row; tif->tif_dir.td_row + nrows > tif->tif_dir.td_imagelength)
nrows = tif->tif_dir.td_imagelength - tif->tif_dir.td_row;
if (sp->cinfo.c.data_precision == 12) if (sp->cinfo.c.data_precision == 12)
{ {
line16_count = (int)((sp->bytesperline * 2) / 3); line16_count = (int)((sp->bytesperline * 2) / 3);
line16 = (short *)_TIFFmallocExt(tif, sizeof(short) * line16_count); line16 = (short *)_TIFFmallocExt(
tif, (tmsize_t)(sizeof(short) * (size_t)line16_count));
if (!line16) if (!line16)
{ {
TIFFErrorExtR(tif, "JPEGEncode", "Failed to allocate memory"); TIFFErrorExtR(tif, "JPEGEncode", "Failed to allocate memory");
@@ -2363,8 +2389,10 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3; unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3;
TIFF_JSAMPLE *out_ptr = (TIFF_JSAMPLE *)(line16 + iPair * 2); TIFF_JSAMPLE *out_ptr = (TIFF_JSAMPLE *)(line16 + iPair * 2);
out_ptr[0] = (in_ptr[0] << 4) | ((in_ptr[1] & 0xf0) >> 4); out_ptr[0] = (TIFF_JSAMPLE)((in_ptr[0] << 4) |
out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2]; ((in_ptr[1] & 0xf0) >> 4));
out_ptr[1] =
(TIFF_JSAMPLE)(((in_ptr[1] & 0x0f) << 8) | in_ptr[2]);
} }
} }
else else
@@ -2374,7 +2402,7 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
return (0); return (0);
if (nrows > 0) if (nrows > 0)
tif->tif_row++; tif->tif_dir.td_row++;
buf += sp->bytesperline; buf += sp->bytesperline;
} }
@@ -2443,8 +2471,9 @@ static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
{ {
int hsamp = compptr->h_samp_factor; int hsamp = compptr->h_samp_factor;
int vsamp = compptr->v_samp_factor; int vsamp = compptr->v_samp_factor;
int padding = (int)(compptr->width_in_blocks * DCTSIZE - int padding =
clumps_per_line * hsamp); (int)(compptr->width_in_blocks * DCTSIZE -
(JDIMENSION)clumps_per_line * (JDIMENSION)hsamp);
for (ypos = 0; ypos < vsamp; ypos++) for (ypos = 0; ypos < vsamp; ypos++)
{ {
inptr = ((TIFF_JSAMPLE *)buf) + clumpoffset; inptr = ((TIFF_JSAMPLE *)buf) + clumpoffset;
@@ -2488,7 +2517,7 @@ static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
} }
sp->scancount = 0; sp->scancount = 0;
} }
tif->tif_row += sp->v_sampling; tif->tif_dir.td_row += sp->v_sampling;
buf += bytesperclumpline; buf += bytesperclumpline;
nrows -= sp->v_sampling; nrows -= sp->v_sampling;
} }
@@ -2582,10 +2611,11 @@ static void JPEGResetUpsampled(TIFF *tif)
* Must recalculate cached tile size in case sampling state changed. * Must recalculate cached tile size in case sampling state changed.
* Should we really be doing this now if image size isn't set? * Should we really be doing this now if image size isn't set?
*/ */
if (tif->tif_tilesize > 0) if (tif->tif_dir.td_tilesize > 0)
tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); tif->tif_dir.td_tilesize =
if (tif->tif_scanlinesize > 0) isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
tif->tif_scanlinesize = TIFFScanlineSize(tif); if (tif->tif_dir.td_scanlinesize > 0)
tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
} }
static int JPEGVSetField(TIFF *tif, uint32_t tag, va_list ap) static int JPEGVSetField(TIFF *tif, uint32_t tag, va_list ap)
@@ -2793,6 +2823,33 @@ static int JPEGInitializeLibJPEG(TIFF *tif, int decompress)
return 1; return 1;
} }
static uint64_t JPEGGetMaxCompressionRatio(TIFF *tif)
{
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
const JPEGState *sp = JState(tif);
if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) &&
(tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) &&
(tif->tif_dir.td_samplesperpixel == 3))
{
if (sp->h_sampling == 2 && sp->v_sampling == 2)
{
if (tif->tif_dir.td_bitspersample == 12)
return 768;
else
return 512;
}
return 0; /* unknown */
}
if (tif->tif_dir.td_bitspersample == 12)
return 384;
else
return 256;
}
/* Common to tif_jpeg.c and tif_jpeg_12.c */ /* Common to tif_jpeg.c and tif_jpeg_12.c */
static void TIFFInitJPEGCommon(TIFF *tif) static void TIFFInitJPEGCommon(TIFF *tif)
{ {
@@ -2829,6 +2886,7 @@ static void TIFFInitJPEGCommon(TIFF *tif)
tif->tif_encoderow = JPEGEncode; tif->tif_encoderow = JPEGEncode;
tif->tif_encodestrip = JPEGEncode; tif->tif_encodestrip = JPEGEncode;
tif->tif_encodetile = JPEGEncode; tif->tif_encodetile = JPEGEncode;
tif->tif_getmaxcompressionratio = JPEGGetMaxCompressionRatio;
tif->tif_cleanup = JPEGCleanup; tif->tif_cleanup = JPEGCleanup;
tif->tif_defstripsize = JPEGDefaultStripSize; tif->tif_defstripsize = JPEGDefaultStripSize;

View File

@@ -33,6 +33,7 @@
#include "Lerc_c_api.h" #include "Lerc_c_api.h"
#include "zlib.h" #include "zlib.h"
#include <math.h>
#ifdef ZSTD_SUPPORT #ifdef ZSTD_SUPPORT
#include "zstd.h" #include "zstd.h"
#endif #endif
@@ -188,7 +189,7 @@ static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module)
else else
{ {
sp->segment_width = td->td_imagewidth; sp->segment_width = td->td_imagewidth;
sp->segment_height = td->td_imagelength - tif->tif_row; sp->segment_height = td->td_imagelength - tif->tif_dir.td_row;
if (sp->segment_height > td->td_rowsperstrip) if (sp->segment_height > td->td_rowsperstrip)
sp->segment_height = td->td_rowsperstrip; sp->segment_height = td->td_rowsperstrip;
} }
@@ -242,7 +243,7 @@ static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module)
} }
if ((td->td_planarconfig == PLANARCONFIG_CONTIG && if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_extrasamples > 0 && td->td_extrasamples > 0 && td->td_sampleinfo &&
td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA && td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
GetLercDataType(tif) == 1) || GetLercDataType(tif) == 1) ||
(td->td_sampleformat == SAMPLEFORMAT_IEEEFP && (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
@@ -343,7 +344,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
if (res != LIBDEFLATE_SUCCESS) if (res != LIBDEFLATE_SUCCESS)
{ {
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu", TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
return 0; return 0;
} }
assert(lerc_data_sizet == (unsigned int)lerc_data_sizet); assert(lerc_data_sizet == (unsigned int)lerc_data_sizet);
@@ -387,7 +388,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
size_t zstd_ret; size_t zstd_ret;
zstd_ret = ZSTD_decompress(sp->compressed_buffer, sp->compressed_size, zstd_ret = ZSTD_decompress(sp->compressed_buffer, sp->compressed_size,
tif->tif_rawcp, tif->tif_rawcc); tif->tif_rawcp, (size_t)tif->tif_rawcc);
if (ZSTD_isError(zstd_ret)) if (ZSTD_isError(zstd_ret))
{ {
TIFFErrorExtR(tif, module, "Error in ZSTD_decompress(): %s", TIFFErrorExtR(tif, module, "Error in ZSTD_decompress(): %s",
@@ -420,6 +421,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
/* LERC info has dim == samplesperpixel - 1, then there is a LERC */ /* LERC info has dim == samplesperpixel - 1, then there is a LERC */
/* mask. */ /* mask. */
if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 && if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
td->td_sampleinfo &&
td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA && td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
GetLercDataType(tif) == 1 && GetLercDataType(tif) == 1 &&
infoArray[2] == td->td_samplesperpixel - 1U) infoArray[2] == td->td_samplesperpixel - 1U)
@@ -432,7 +434,8 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
use_mask = 1; use_mask = 1;
} }
ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1; ndims =
(int)(td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1);
/* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols, /* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols,
nRows, nBands, nValidPixels, blobSize, nRows, nBands, nValidPixels, blobSize,
@@ -440,12 +443,12 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
if (infoArray[0] != (unsigned)sp->lerc_version) if (infoArray[0] != (unsigned)sp->lerc_version)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"Unexpected version number: %d. Expected: %d", "Unexpected version number: %u. Expected: %d",
infoArray[0], sp->lerc_version); infoArray[0], sp->lerc_version);
} }
if (infoArray[1] != (unsigned)lerc_data_type) if (infoArray[1] != (unsigned)lerc_data_type)
{ {
TIFFErrorExtR(tif, module, "Unexpected dataType: %d. Expected: %d", TIFFErrorExtR(tif, module, "Unexpected dataType: %u. Expected: %d",
infoArray[1], lerc_data_type); infoArray[1], lerc_data_type);
return 0; return 0;
} }
@@ -458,7 +461,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
{ {
if (nFoundDims != 1 && nFoundDims != (unsigned)ndims) if (nFoundDims != 1 && nFoundDims != (unsigned)ndims)
{ {
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: 1 or %d", TIFFErrorExtR(tif, module, "Unexpected nDim: %u. Expected: 1 or %d",
nFoundDims, ndims); nFoundDims, ndims);
return 0; return 0;
} }
@@ -467,20 +470,20 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
#endif #endif
if (nFoundDims != (unsigned)ndims) if (nFoundDims != (unsigned)ndims)
{ {
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d", TIFFErrorExtR(tif, module, "Unexpected nDim: %u. Expected: %d",
nFoundDims, ndims); nFoundDims, ndims);
return 0; return 0;
} }
if (infoArray[3] != sp->segment_width) if (infoArray[3] != sp->segment_width)
{ {
TIFFErrorExtR(tif, module, "Unexpected nCols: %d. Expected: %du", TIFFErrorExtR(tif, module, "Unexpected nCols: %u. Expected: %u",
infoArray[3], sp->segment_width); infoArray[3], sp->segment_width);
return 0; return 0;
} }
if (infoArray[4] != sp->segment_height) if (infoArray[4] != sp->segment_height)
{ {
TIFFErrorExtR(tif, module, "Unexpected nRows: %d. Expected: %u", TIFFErrorExtR(tif, module, "Unexpected nRows: %u. Expected: %u",
infoArray[4], sp->segment_height); infoArray[4], sp->segment_height);
return 0; return 0;
} }
@@ -504,28 +507,28 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
#endif #endif
if (nFoundBands != td->td_samplesperpixel) if (nFoundBands != td->td_samplesperpixel)
{ {
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d", TIFFErrorExtR(tif, module, "Unexpected nBands: %u. Expected: %d",
nFoundBands, td->td_samplesperpixel); nFoundBands, td->td_samplesperpixel);
return 0; return 0;
} }
} }
else if (nFoundBands != 1) else if (nFoundBands != 1)
{ {
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d", TIFFErrorExtR(tif, module, "Unexpected nBands: %u. Expected: %d",
nFoundBands, 1); nFoundBands, 1);
return 0; return 0;
} }
if (infoArray[7] != lerc_data_size) if (infoArray[7] != lerc_data_size)
{ {
TIFFErrorExtR(tif, module, "Unexpected blobSize: %d. Expected: %u", TIFFErrorExtR(tif, module, "Unexpected blobSize: %u. Expected: %u",
infoArray[7], lerc_data_size); infoArray[7], lerc_data_size);
return 0; return 0;
} }
int nRequestedMasks = use_mask ? 1 : 0; int nRequestedMasks = use_mask ? 1 : 0;
#if LERC_AT_LEAST_VERSION(3, 0, 0) #if LERC_AT_LEAST_VERSION(3, 0, 0)
const int nFoundMasks = infoArray[8]; const int nFoundMasks = (int)infoArray[8];
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1 && nFoundDims == 1) td->td_samplesperpixel > 1 && nFoundDims == 1)
@@ -576,21 +579,22 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
sp->uncompressed_buffer_multiband_alloc = num_bytes_needed; sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
} }
lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks, lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks,
sp->mask_buffer, nFoundDims, sp->segment_width, sp->mask_buffer, (int)nFoundDims,
sp->segment_height, nFoundBands, lerc_data_type, (int)sp->segment_width, (int)sp->segment_height,
(int)nFoundBands, (unsigned int)lerc_data_type,
sp->uncompressed_buffer_multiband); sp->uncompressed_buffer_multiband);
} }
else else
#endif #endif
{ {
lerc_ret = lerc_ret = lerc_decode(
lerc_decode(lerc_data, lerc_data_size, lerc_data, lerc_data_size,
#if LERC_AT_LEAST_VERSION(3, 0, 0) #if LERC_AT_LEAST_VERSION(3, 0, 0)
nRequestedMasks, nRequestedMasks,
#endif #endif
use_mask ? sp->mask_buffer : NULL, nFoundDims, use_mask ? sp->mask_buffer : NULL, (int)nFoundDims,
sp->segment_width, sp->segment_height, nFoundBands, (int)sp->segment_width, (int)sp->segment_height, (int)nFoundBands,
lerc_data_type, sp->uncompressed_buffer); (unsigned int)lerc_data_type, sp->uncompressed_buffer);
} }
if (lerc_ret != 0) if (lerc_ret != 0)
{ {
@@ -601,17 +605,17 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
/* Interleave alpha mask with other samples. */ /* Interleave alpha mask with other samples. */
if (use_mask && GetLercDataType(tif) == 1) if (use_mask && GetLercDataType(tif) == 1)
{ {
unsigned src_stride = unsigned src_stride = (unsigned int)((td->td_samplesperpixel - 1) *
(td->td_samplesperpixel - 1) * (td->td_bitspersample / 8); (td->td_bitspersample / 8));
unsigned dst_stride = unsigned dst_stride =
td->td_samplesperpixel * (td->td_bitspersample / 8); (unsigned int)(td->td_samplesperpixel * (td->td_bitspersample / 8));
unsigned i = sp->segment_width * sp->segment_height; unsigned i = sp->segment_width * sp->segment_height;
/* Operate from end to begin to be able to move in place */ /* Operate from end to begin to be able to move in place */
while (i > 0 && i > nomask_bands) while (i > 0 && i > nomask_bands)
{ {
i--; i--;
sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel - sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel -
1] = 255 * sp->mask_buffer[i]; 1] = (uint8_t)(255 * sp->mask_buffer[i]);
memcpy(sp->uncompressed_buffer + i * dst_stride, memcpy(sp->uncompressed_buffer + i * dst_stride,
sp->uncompressed_buffer + i * src_stride, src_stride); sp->uncompressed_buffer + i * src_stride, src_stride);
} }
@@ -620,7 +624,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
{ {
i--; i--;
sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel - sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel -
1] = 255 * sp->mask_buffer[i]; 1] = (uint8_t)(255 * sp->mask_buffer[i]);
memmove(sp->uncompressed_buffer + i * dst_stride, memmove(sp->uncompressed_buffer + i * dst_stride,
sp->uncompressed_buffer + i * src_stride, src_stride); sp->uncompressed_buffer + i * src_stride, src_stride);
} }
@@ -649,7 +653,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
} }
else else
{ {
const double nan_float64 = nan_float32; const double nan_float64 = (double)nan_float32;
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
if (sp->mask_buffer[i] == 0) if (sp->mask_buffer[i] == 0)
@@ -677,7 +681,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
} }
else else
{ {
const double nan_float64 = nan_float32; const double nan_float64 = (double)nan_float32;
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
for (int j = 0; j < td->td_samplesperpixel; j++) for (int j = 0; j < td->td_samplesperpixel; j++)
@@ -704,30 +708,32 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
{ {
for (int j = 0; j < td->td_samplesperpixel; j++) for (int j = 0; j < td->td_samplesperpixel; j++)
{ {
if (sp->mask_buffer[i + j * nb_pixels] == 0) if (sp->mask_buffer[i + (unsigned int)j * nb_pixels] ==
0)
((float *)sp->uncompressed_buffer)[k] = nan_float32; ((float *)sp->uncompressed_buffer)[k] = nan_float32;
else else
((float *)sp->uncompressed_buffer)[k] = ((float *)sp->uncompressed_buffer)[k] =
((float *)sp->uncompressed_buffer_multiband) ((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels]; [i + (unsigned int)j * nb_pixels];
++k; ++k;
} }
} }
} }
else else
{ {
const double nan_float64 = nan_float32; const double nan_float64 = (double)nan_float32;
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
for (int j = 0; j < td->td_samplesperpixel; j++) for (int j = 0; j < td->td_samplesperpixel; j++)
{ {
if (sp->mask_buffer[i + j * nb_pixels] == 0) if (sp->mask_buffer[i + (unsigned int)j * nb_pixels] ==
0)
((double *)sp->uncompressed_buffer)[k] = ((double *)sp->uncompressed_buffer)[k] =
nan_float64; nan_float64;
else else
((double *)sp->uncompressed_buffer)[k] = ((double *)sp->uncompressed_buffer)[k] =
((double *)sp->uncompressed_buffer_multiband) ((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels]; [i + (unsigned int)j * nb_pixels];
++k; ++k;
} }
} }
@@ -766,8 +772,8 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
return 0; return 0;
} }
memcpy(op, sp->uncompressed_buffer + sp->uncompressed_offset, occ); memcpy(op, sp->uncompressed_buffer + sp->uncompressed_offset, (size_t)occ);
sp->uncompressed_offset += (unsigned)occ; sp->uncompressed_offset += (unsigned int)occ;
return 1; return 1;
} }
@@ -832,8 +838,8 @@ static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
return 0; return 0;
} }
memcpy(sp->uncompressed_buffer + sp->uncompressed_offset, bp, cc); memcpy(sp->uncompressed_buffer + sp->uncompressed_offset, bp, (size_t)cc);
sp->uncompressed_offset += (unsigned)cc; sp->uncompressed_offset += (unsigned int)cc;
return 1; return 1;
} }
@@ -863,13 +869,15 @@ static int LERCPostEncode(TIFF *tif)
/* Extract alpha mask (if containing only 0 and 255 values, */ /* Extract alpha mask (if containing only 0 and 255 values, */
/* and compact array of regular bands */ /* and compact array of regular bands */
if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 && if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
td->td_sampleinfo &&
td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA && td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
GetLercDataType(tif) == 1) GetLercDataType(tif) == 1)
{ {
const unsigned dst_stride = const unsigned dst_stride =
(td->td_samplesperpixel - 1) * (td->td_bitspersample / 8); (unsigned int)((td->td_samplesperpixel - 1) *
(td->td_bitspersample / 8));
const unsigned src_stride = const unsigned src_stride =
td->td_samplesperpixel * (td->td_bitspersample / 8); (unsigned int)(td->td_samplesperpixel * (td->td_bitspersample / 8));
unsigned i = 0; unsigned i = 0;
use_mask = 1; use_mask = 1;
@@ -923,7 +931,7 @@ static int LERCPostEncode(TIFF *tif)
{ {
const float val = ((float *)sp->uncompressed_buffer)[k]; const float val = ((float *)sp->uncompressed_buffer)[k];
++k; ++k;
if (val != val) if (isnan(val))
{ {
++count_nan; ++count_nan;
} }
@@ -944,7 +952,7 @@ static int LERCPostEncode(TIFF *tif)
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
const float val = ((float *)sp->uncompressed_buffer)[i]; const float val = ((float *)sp->uncompressed_buffer)[i];
if (val != val) if (isnan(val))
{ {
use_mask = 1; use_mask = 1;
break; break;
@@ -965,7 +973,7 @@ static int LERCPostEncode(TIFF *tif)
const double val = const double val =
((double *)sp->uncompressed_buffer)[k]; ((double *)sp->uncompressed_buffer)[k];
++k; ++k;
if (val != val) if (isnan(val))
{ {
++count_nan; ++count_nan;
} }
@@ -986,7 +994,7 @@ static int LERCPostEncode(TIFF *tif)
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
const double val = ((double *)sp->uncompressed_buffer)[i]; const double val = ((double *)sp->uncompressed_buffer)[i];
if (val != val) if (isnan(val))
{ {
use_mask = 1; use_mask = 1;
break; break;
@@ -1025,10 +1033,10 @@ static int LERCPostEncode(TIFF *tif)
const float val = const float val =
((float *)sp->uncompressed_buffer)[k]; ((float *)sp->uncompressed_buffer)[k];
((float *)sp->uncompressed_buffer_multiband) ((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val; [i + (unsigned int)j * nb_pixels] = val;
++k; ++k;
sp->mask_buffer[i + j * nb_pixels] = sp->mask_buffer[i + (unsigned int)j * nb_pixels] =
(val == val) ? 255 : 0; !isnan(val) ? 255 : 0;
} }
} }
} }
@@ -1041,10 +1049,10 @@ static int LERCPostEncode(TIFF *tif)
const double val = const double val =
((double *)sp->uncompressed_buffer)[k]; ((double *)sp->uncompressed_buffer)[k];
((double *)sp->uncompressed_buffer_multiband) ((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val; [i + (unsigned int)j * nb_pixels] = val;
++k; ++k;
sp->mask_buffer[i + j * nb_pixels] = sp->mask_buffer[i + (unsigned int)j * nb_pixels] =
(val == val) ? 255 : 0; !isnan(val) ? 255 : 0;
} }
} }
} }
@@ -1064,7 +1072,7 @@ static int LERCPostEncode(TIFF *tif)
{ {
const float val = const float val =
((float *)sp->uncompressed_buffer)[i * dst_nbands]; ((float *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0; sp->mask_buffer[i] = !isnan(val) ? 255 : 0;
} }
} }
else else
@@ -1073,7 +1081,7 @@ static int LERCPostEncode(TIFF *tif)
{ {
const double val = const double val =
((double *)sp->uncompressed_buffer)[i * dst_nbands]; ((double *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0; sp->mask_buffer[i] = !isnan(val) ? 255 : 0;
} }
} }
} }
@@ -1084,7 +1092,7 @@ static int LERCPostEncode(TIFF *tif)
for (i = 0; i < nb_pixels; i++) for (i = 0; i < nb_pixels; i++)
{ {
const float val = ((float *)sp->uncompressed_buffer)[i]; const float val = ((float *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0; sp->mask_buffer[i] = !isnan(val) ? 255 : 0;
} }
} }
else else
@@ -1093,7 +1101,7 @@ static int LERCPostEncode(TIFF *tif)
{ {
const double val = const double val =
((double *)sp->uncompressed_buffer)[i]; ((double *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0; sp->mask_buffer[i] = !isnan(val) ? 255 : 0;
} }
} }
} }
@@ -1104,7 +1112,8 @@ static int LERCPostEncode(TIFF *tif)
#if LERC_AT_LEAST_VERSION(3, 0, 0) #if LERC_AT_LEAST_VERSION(3, 0, 0)
if (mask_count > 1) if (mask_count > 1)
{ {
estimated_compressed_size += nb_pixels * mask_count / 8; estimated_compressed_size +=
(unsigned int)(nb_pixels * (unsigned int)mask_count / 8);
} }
#endif #endif
@@ -1125,8 +1134,9 @@ static int LERCPostEncode(TIFF *tif)
{ {
lerc_ret = lerc_encodeForVersion( lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer_multiband, sp->lerc_version, sp->uncompressed_buffer_multiband, sp->lerc_version,
GetLercDataType(tif), 1, sp->segment_width, sp->segment_height, (unsigned int)GetLercDataType(tif), 1, (int)sp->segment_width,
dst_nbands, dst_nbands, sp->mask_buffer, sp->maxzerror, (int)sp->segment_height, (int)dst_nbands, (int)dst_nbands,
sp->mask_buffer, sp->maxzerror,
(unsigned char *)sp->compressed_buffer, sp->compressed_size, (unsigned char *)sp->compressed_buffer, sp->compressed_size,
&numBytesWritten); &numBytesWritten);
} }
@@ -1134,9 +1144,10 @@ static int LERCPostEncode(TIFF *tif)
#endif #endif
{ {
lerc_ret = lerc_encodeForVersion( lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif), sp->uncompressed_buffer, sp->lerc_version,
td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1, (unsigned int)GetLercDataType(tif),
sp->segment_width, sp->segment_height, 1, (int)(td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1),
(int)sp->segment_width, (int)sp->segment_height, 1,
#if LERC_AT_LEAST_VERSION(3, 0, 0) #if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0, use_mask ? 1 : 0,
#endif #endif
@@ -1179,14 +1190,14 @@ static int LERCPostEncode(TIFF *tif)
return 0; return 0;
} }
tif->tif_rawcc = libdeflate_zlib_compress( tif->tif_rawcc = (tmsize_t)libdeflate_zlib_compress(
sp->libdeflate_enc, sp->compressed_buffer, numBytesWritten, sp->libdeflate_enc, sp->compressed_buffer, numBytesWritten,
sp->uncompressed_buffer, sp->uncompressed_alloc); sp->uncompressed_buffer, sp->uncompressed_alloc);
if (tif->tif_rawcc == 0) if (tif->tif_rawcc == 0)
{ {
TIFFErrorExtR(tif, module, "Encoder error at scanline %lu", TIFFErrorExtR(tif, module, "Encoder error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
return 0; return 0;
} }
#else #else
@@ -1252,7 +1263,7 @@ static int LERCPostEncode(TIFF *tif)
int ret; int ret;
uint8_t *tif_rawdata_backup = tif->tif_rawdata; uint8_t *tif_rawdata_backup = tif->tif_rawdata;
tif->tif_rawdata = sp->uncompressed_buffer; tif->tif_rawdata = sp->uncompressed_buffer;
tif->tif_rawcc = zstd_ret; tif->tif_rawcc = (tmsize_t)zstd_ret;
ret = TIFFFlushData1(tif); ret = TIFFFlushData1(tif);
tif->tif_rawdata = tif_rawdata_backup; tif->tif_rawdata = tif_rawdata_backup;
if (!ret) if (!ret)
@@ -1350,7 +1361,7 @@ static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
{ {
case TIFFTAG_LERC_PARAMETERS: case TIFFTAG_LERC_PARAMETERS:
{ {
uint32_t count = va_arg(ap, int); uint32_t count = (uint32_t)va_arg(ap, int);
int *params = va_arg(ap, int *); int *params = va_arg(ap, int *);
if (count < 2) if (count < 2)
{ {
@@ -1529,6 +1540,13 @@ int TIFFInitLERC(TIFF *tif, int scheme)
#endif #endif
tif->tif_cleanup = LERCCleanup; tif->tif_cleanup = LERCCleanup;
/* LERC compression ratio can grow to several millions */
/* eg. 5703725 for Lerc deflate on 16383x16383 array */
/* or 3829644 for regular Lerc */
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* so we don't define tif->tif_getmaxcompressionratio */
/* Default values for codec-specific fields */ /* Default values for codec-specific fields */
TIFFSetField(tif, TIFFTAG_LERC_VERSION, LERC_VERSION_2_4); TIFFSetField(tif, TIFFTAG_LERC_VERSION, LERC_VERSION_2_4);
TIFFSetField(tif, TIFFTAG_LERC_ADD_COMPRESSION, LERC_ADD_COMPRESSION_NONE); TIFFSetField(tif, TIFFTAG_LERC_ADD_COMPRESSION, LERC_ADD_COMPRESSION_NONE);

View File

@@ -212,7 +212,7 @@ static int LogL16Decode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} }
tp = (int16_t *)sp->tbuf; tp = (int16_t *)sp->tbuf;
} }
_TIFFmemset((void *)tp, 0, npixels * sizeof(tp[0])); _TIFFmemset((void *)tp, 0, (tmsize_t)((size_t)npixels * sizeof(tp[0])));
bp = (unsigned char *)tif->tif_rawcp; bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc; cc = tif->tif_rawcc;
@@ -235,7 +235,7 @@ static int LogL16Decode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{ /* non-run */ { /* non-run */
rc = *bp++; /* nul is noop */ rc = *bp++; /* nul is noop */
while (--cc && rc-- && i < npixels) while (--cc && rc-- && i < npixels)
tp[i++] |= (int16_t)*bp++ << shft; tp[i++] |= (int16_t)(*bp++ << shft);
} }
} }
if (i != npixels) if (i != npixels)
@@ -243,7 +243,7 @@ static int LogL16Decode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at row %" PRIu32 "Not enough data at row %" PRIu32
" (short %" TIFF_SSIZE_FORMAT " pixels)", " (short %" TIFF_SSIZE_FORMAT " pixels)",
tif->tif_row, npixels - i); tif->tif_dir.td_row, npixels - i);
tif->tif_rawcp = (uint8_t *)bp; tif->tif_rawcp = (uint8_t *)bp;
tif->tif_rawcc = cc; tif->tif_rawcc = cc;
return (0); return (0);
@@ -290,7 +290,7 @@ static int LogLuvDecode24(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
cc = tif->tif_rawcc; cc = tif->tif_rawcc;
for (i = 0; i < npixels && cc >= 3; i++) for (i = 0; i < npixels && cc >= 3; i++)
{ {
tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; tp[i] = (uint32_t)bp[0] << 16 | (uint32_t)bp[1] << 8 | bp[2];
bp += 3; bp += 3;
cc -= 3; cc -= 3;
} }
@@ -301,7 +301,7 @@ static int LogLuvDecode24(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at row %" PRIu32 "Not enough data at row %" PRIu32
" (short %" TIFF_SSIZE_FORMAT " pixels)", " (short %" TIFF_SSIZE_FORMAT " pixels)",
tif->tif_row, npixels - i); tif->tif_dir.td_row, npixels - i);
return (0); return (0);
} }
(*sp->tfunc)(sp, op, npixels); (*sp->tfunc)(sp, op, npixels);
@@ -342,7 +342,7 @@ static int LogLuvDecode32(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} }
tp = (uint32_t *)sp->tbuf; tp = (uint32_t *)sp->tbuf;
} }
_TIFFmemset((void *)tp, 0, npixels * sizeof(tp[0])); _TIFFmemset((void *)tp, 0, (tmsize_t)((size_t)npixels * sizeof(tp[0])));
bp = (unsigned char *)tif->tif_rawcp; bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc; cc = tif->tif_rawcc;
@@ -373,7 +373,7 @@ static int LogLuvDecode32(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at row %" PRIu32 "Not enough data at row %" PRIu32
" (short %" TIFF_SSIZE_FORMAT " pixels)", " (short %" TIFF_SSIZE_FORMAT " pixels)",
tif->tif_row, npixels - i); tif->tif_dir.td_row, npixels - i);
tif->tif_rawcp = (uint8_t *)bp; tif->tif_rawcp = (uint8_t *)bp;
tif->tif_rawcc = cc; tif->tif_rawcc = cc;
return (0); return (0);
@@ -767,25 +767,21 @@ static int LogLuvEncodeTile(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#undef log2 /* Conflict with C'99 function */
#define log2(x) ((1. / M_LN2) * log(x))
#undef exp2 /* Conflict with C'99 function */
#define exp2(x) exp(M_LN2 *(x))
#define TIFF_RAND_MAX 32767 #define TIFF_RAND_MAX 32767
// From POSIX.1-2001 as an example of an implementation of rand() // From POSIX.1-2001 as an example of an implementation of rand()
static uint32_t _TIFFRand() static uint32_t _TIFFRand(void)
{ {
static uint32_t nCounter = 0; static uint32_t nCounter = 0;
if (!nCounter) if (!nCounter)
nCounter = (uint32_t)(time(NULL) & UINT32_MAX); nCounter = (uint32_t)(time(NULL) & UINT32_MAX);
++nCounter; ++nCounter;
uint32_t nCounterLocal = uint32_t nCounterLocal =
(uint32_t)(((uint64_t)(nCounter)*1103515245U + 12345U) & UINT32_MAX); (uint32_t)(((uint64_t)(nCounter) * 1103515245U + 12345U) & UINT32_MAX);
nCounter = nCounterLocal; nCounter = nCounterLocal;
return (nCounterLocal / 65536U) % (TIFF_RAND_MAX + 1); return (nCounterLocal / 65536U) % (TIFF_RAND_MAX + 1);
}; }
static int tiff_itrunc(double x, int m) static int tiff_itrunc(double x, int m)
{ {
@@ -797,8 +793,7 @@ static int tiff_itrunc(double x, int m)
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
double double LogL16toY(int p16) /* compute luminance from 16-bit LogL */
LogL16toY(int p16) /* compute luminance from 16-bit LogL */
{ {
int Le = p16 & 0x7fff; int Le = p16 & 0x7fff;
double Y; double Y;
@@ -812,8 +807,7 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
int int LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
{ {
if (Y >= 1.8371976e19) if (Y >= 1.8371976e19)
return (0x7fff); return (0x7fff);
@@ -855,20 +849,22 @@ static void L16fromY(LogLuvState *sp, uint8_t *op, tmsize_t n)
float *yp = (float *)op; float *yp = (float *)op;
while (n-- > 0) while (n-- > 0)
*l16++ = (int16_t)(LogL16fromY(*yp++, sp->encode_meth)); *l16++ = (int16_t)(LogL16fromY((double)*yp++, sp->encode_meth));
} }
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
void void XYZtoRGB24(float *xyz, uint8_t *rgb)
XYZtoRGB24(float *xyz, uint8_t *rgb)
{ {
double r, g, b; double r, g, b;
/* assume CCIR-709 primaries */ /* assume CCIR-709 primaries */
r = 2.690 * xyz[0] + -1.276 * xyz[1] + -0.414 * xyz[2]; r = 2.690 * (double)xyz[0] + -1.276 * (double)xyz[1] +
g = -1.022 * xyz[0] + 1.978 * xyz[1] + 0.044 * xyz[2]; -0.414 * (double)xyz[2];
b = 0.061 * xyz[0] + -0.224 * xyz[1] + 1.163 * xyz[2]; g = -1.022 * (double)xyz[0] + 1.978 * (double)xyz[1] +
0.044 * (double)xyz[2];
b = 0.061 * (double)xyz[0] + -0.224 * (double)xyz[1] +
1.163 * (double)xyz[2];
/* assume 2.0 gamma for speed */ /* assume 2.0 gamma for speed */
/* could use integer sqrt approx., but this is probably faster */ /* could use integer sqrt approx., but this is probably faster */
rgb[0] = (uint8_t)((r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256. * sqrt(r))); rgb[0] = (uint8_t)((r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256. * sqrt(r)));
@@ -879,8 +875,7 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
double double LogL10toY(int p10) /* compute luminance from 10-bit LogL */
LogL10toY(int p10) /* compute luminance from 10-bit LogL */
{ {
if (p10 == 0) if (p10 == 0)
return (0.); return (0.);
@@ -890,8 +885,7 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
int int LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
{ {
if (Y >= 15.742) if (Y >= 15.742)
return (0x3ff); return (0x3ff);
@@ -903,13 +897,14 @@ static
#define NANGLES 100 #define NANGLES 100
#define uv2ang(u, v) \ #define uv2ang(u, v) \
((NANGLES * .499999999 / M_PI) * atan2((v)-V_NEU, (u)-U_NEU) + .5 * NANGLES) ((NANGLES * .499999999 / M_PI) * atan2((v) - V_NEU, (u) - U_NEU) + \
.5 * NANGLES)
static int oog_encode(double u, double v) /* encode out-of-gamut chroma */ static int oog_encode(double u, double v) /* encode out-of-gamut chroma */
{ {
static int oog_table[NANGLES]; static int oog_table[NANGLES];
static int initialized = 0; static int initialized = 0;
register int i; int i;
if (!initialized) if (!initialized)
{ /* set up perimeter table */ { /* set up perimeter table */
@@ -919,13 +914,14 @@ static int oog_encode(double u, double v) /* encode out-of-gamut chroma */
eps[i] = 2.; eps[i] = 2.;
for (vi = UV_NVS; vi--;) for (vi = UV_NVS; vi--;)
{ {
va = UV_VSTART + (vi + .5) * UV_SQSIZ; va = (double)UV_VSTART + ((double)vi + .5) * (double)UV_SQSIZ;
ustep = uv_row[vi].nus - 1; ustep = uv_row[vi].nus - 1;
if (vi == UV_NVS - 1 || vi == 0 || ustep <= 0) if (vi == UV_NVS - 1 || vi == 0 || ustep <= 0)
ustep = 1; ustep = 1;
for (ui = uv_row[vi].nus - 1; ui >= 0; ui -= ustep) for (ui = uv_row[vi].nus - 1; ui >= 0; ui -= ustep)
{ {
ua = uv_row[vi].ustart + (ui + .5) * UV_SQSIZ; ua = (double)uv_row[vi].ustart +
((double)ui + .5) * (double)UV_SQSIZ;
ang = uv2ang(ua, va); ang = uv2ang(ua, va);
i = (int)ang; i = (int)ang;
epsa = fabs(ang - (i + .5)); epsa = fabs(ang - (i + .5));
@@ -963,27 +959,28 @@ static int oog_encode(double u, double v) /* encode out-of-gamut chroma */
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
int int uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
{ {
unsigned int vi; unsigned int vi;
int ui; int ui;
/* check for NaN */ /* check for NaN */
if (u != u || v != v) if (isnan(u) || isnan(v))
{ {
u = U_NEU; u = U_NEU;
v = V_NEU; v = V_NEU;
} }
if (v < UV_VSTART) if ((double)v < (double)UV_VSTART)
return oog_encode(u, v); return oog_encode(u, v);
vi = tiff_itrunc((v - UV_VSTART) * (1. / UV_SQSIZ), em); vi = (unsigned int)tiff_itrunc(
((double)v - (double)UV_VSTART) * (1. / (double)UV_SQSIZ), em);
if (vi >= UV_NVS) if (vi >= UV_NVS)
return oog_encode(u, v); return oog_encode(u, v);
if (u < uv_row[vi].ustart) if ((double)u < (double)uv_row[vi].ustart)
return oog_encode(u, v); return oog_encode(u, v);
ui = tiff_itrunc((u - uv_row[vi].ustart) * (1. / UV_SQSIZ), em); ui = tiff_itrunc(
((double)u - (double)uv_row[vi].ustart) * (1. / (double)UV_SQSIZ), em);
if (ui >= uv_row[vi].nus) if (ui >= uv_row[vi].nus)
return oog_encode(u, v); return oog_encode(u, v);
@@ -993,8 +990,7 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
int int uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
{ {
unsigned int upper, lower; unsigned int upper, lower;
int ui; int ui;
@@ -1020,16 +1016,15 @@ static
} }
vi = lower; vi = lower;
ui = c - uv_row[vi].ncum; ui = c - uv_row[vi].ncum;
*up = uv_row[vi].ustart + (ui + .5) * UV_SQSIZ; *up = (double)uv_row[vi].ustart + ((double)ui + .5) * (double)UV_SQSIZ;
*vp = UV_VSTART + (vi + .5) * UV_SQSIZ; *vp = (double)UV_VSTART + ((double)vi + .5) * (double)UV_SQSIZ;
return (0); return (0);
} }
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
void void LogLuv24toXYZ(uint32_t p, float *XYZ)
LogLuv24toXYZ(uint32_t p, float *XYZ)
{ {
int Ce; int Ce;
double L, u, v, s, x, y; double L, u, v, s, x, y;
@@ -1059,15 +1054,14 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
uint32_t uint32_t LogLuv24fromXYZ(float *XYZ, int em)
LogLuv24fromXYZ(float *XYZ, int em)
{ {
int Le, Ce; int Le, Ce;
double u, v, s; double u, v, s;
/* encode luminance */ /* encode luminance */
Le = LogL10fromY(XYZ[1], em); Le = LogL10fromY((double)XYZ[1], em);
/* encode color */ /* encode color */
s = XYZ[0] + 15. * XYZ[1] + 3. * XYZ[2]; s = (double)XYZ[0] + 15. * (double)XYZ[1] + 3. * (double)XYZ[2];
if (!Le || s <= 0.) if (!Le || s <= 0.)
{ {
u = U_NEU; u = U_NEU;
@@ -1075,14 +1069,14 @@ static
} }
else else
{ {
u = 4. * XYZ[0] / s; u = 4. * (double)XYZ[0] / s;
v = 9. * XYZ[1] / s; v = 9. * (double)XYZ[1] / s;
} }
Ce = uv_encode(u, v, em); Ce = uv_encode(u, v, em);
if (Ce < 0) /* never happens */ if (Ce < 0) /* never happens */
Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
/* combine encodings */ /* combine encodings */
return (Le << 14 | Ce); return (uint32_t)Le << 14 | (uint32_t)Ce;
} }
static void Luv24toXYZ(LogLuvState *sp, uint8_t *op, tmsize_t n) static void Luv24toXYZ(LogLuvState *sp, uint8_t *op, tmsize_t n)
@@ -1113,8 +1107,8 @@ static void Luv24toLuv48(LogLuvState *sp, uint8_t *op, tmsize_t n)
u = U_NEU; u = U_NEU;
v = V_NEU; v = V_NEU;
} }
*luv3++ = (int16_t)(u * (1L << 15)); *luv3++ = (int16_t)(u * (1 << 15));
*luv3++ = (int16_t)(v * (1L << 15)); *luv3++ = (int16_t)(v * (1 << 15));
luv++; luv++;
} }
} }
@@ -1168,7 +1162,7 @@ static void Luv24fromLuv48(LogLuvState *sp, uint8_t *op, tmsize_t n)
sp->encode_meth); sp->encode_meth);
if (Ce < 0) /* never happens */ if (Ce < 0) /* never happens */
Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
*luv++ = (uint32_t)Le << 14 | Ce; *luv++ = (uint32_t)Le << 14 | (uint32_t)Ce;
luv3 += 3; luv3 += 3;
} }
} }
@@ -1176,8 +1170,7 @@ static void Luv24fromLuv48(LogLuvState *sp, uint8_t *op, tmsize_t n)
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
void void LogLuv32toXYZ(uint32_t p, float *XYZ)
LogLuv32toXYZ(uint32_t p, float *XYZ)
{ {
double L, u, v, s, x, y; double L, u, v, s, x, y;
/* decode luminance */ /* decode luminance */
@@ -1202,15 +1195,14 @@ static
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static
#endif #endif
uint32_t uint32_t LogLuv32fromXYZ(float *XYZ, int em)
LogLuv32fromXYZ(float *XYZ, int em)
{ {
unsigned int Le, ue, ve; unsigned int Le, ue, ve;
double u, v, s; double u, v, s;
/* encode luminance */ /* encode luminance */
Le = (unsigned int)LogL16fromY(XYZ[1], em); Le = (unsigned int)LogL16fromY((double)XYZ[1], em);
/* encode color */ /* encode color */
s = XYZ[0] + 15. * XYZ[1] + 3. * XYZ[2]; s = (double)XYZ[0] + 15. * (double)XYZ[1] + 3. * (double)XYZ[2];
if (!Le || s <= 0.) if (!Le || s <= 0.)
{ {
u = U_NEU; u = U_NEU;
@@ -1218,19 +1210,19 @@ static
} }
else else
{ {
u = 4. * XYZ[0] / s; u = 4. * (double)XYZ[0] / s;
v = 9. * XYZ[1] / s; v = 9. * (double)XYZ[1] / s;
} }
if (u <= 0.) if (u <= 0.)
ue = 0; ue = 0;
else else
ue = tiff_itrunc(UVSCALE * u, em); ue = (unsigned int)tiff_itrunc(UVSCALE * u, em);
if (ue > 255) if (ue > 255)
ue = 255; ue = 255;
if (v <= 0.) if (v <= 0.)
ve = 0; ve = 0;
else else
ve = tiff_itrunc(UVSCALE * v, em); ve = (unsigned int)tiff_itrunc(UVSCALE * v, em);
if (ve > 255) if (ve > 255)
ve = 255; ve = 255;
/* combine encodings */ /* combine encodings */
@@ -1261,8 +1253,8 @@ static void Luv32toLuv48(LogLuvState *sp, uint8_t *op, tmsize_t n)
*luv3++ = (int16_t)(*luv >> 16); *luv3++ = (int16_t)(*luv >> 16);
u = 1. / UVSCALE * ((*luv >> 8 & 0xff) + .5); u = 1. / UVSCALE * ((*luv >> 8 & 0xff) + .5);
v = 1. / UVSCALE * ((*luv & 0xff) + .5); v = 1. / UVSCALE * ((*luv & 0xff) + .5);
*luv3++ = (int16_t)(u * (1L << 15)); *luv3++ = (int16_t)(u * (1 << 15));
*luv3++ = (int16_t)(v * (1L << 15)); *luv3++ = (int16_t)(v * (1 << 15));
luv++; luv++;
} }
} }
@@ -1303,22 +1295,24 @@ static void Luv32fromLuv48(LogLuvState *sp, uint8_t *op, tmsize_t n)
{ {
while (n-- > 0) while (n-- > 0)
{ {
*luv++ = (uint32_t)luv3[0] << 16 | *luv++ =
(luv3[1] * (uint32_t)(UVSCALE + .5) >> 7 & 0xff00) | (uint32_t)luv3[0] << 16 |
(luv3[2] * (uint32_t)(UVSCALE + .5) >> 15 & 0xff); ((uint32_t)luv3[1] * (uint32_t)(UVSCALE + .5) >> 7 & 0xff00) |
((uint32_t)luv3[2] * (uint32_t)(UVSCALE + .5) >> 15 & 0xff);
luv3 += 3; luv3 += 3;
} }
return; return;
} }
while (n-- > 0) while (n-- > 0)
{ {
*luv++ = *luv++ = (uint32_t)luv3[0] << 16 |
(uint32_t)luv3[0] << 16 | ((uint32_t)tiff_itrunc(luv3[1] * (UVSCALE / (1 << 15)),
(tiff_itrunc(luv3[1] * (UVSCALE / (1 << 15)), sp->encode_meth) sp->encode_meth)
<< 8 & << 8 &
0xff00) | 0xff00) |
(tiff_itrunc(luv3[2] * (UVSCALE / (1 << 15)), sp->encode_meth) & ((uint32_t)tiff_itrunc(luv3[2] * (UVSCALE / (1 << 15)),
0xff); sp->encode_meth) &
0xff);
luv3 += 3; luv3 += 3;
} }
} }
@@ -1345,6 +1339,8 @@ static int LogL16GuessDataFmt(TIFFDirectory *td)
case PACK(1, 8, SAMPLEFORMAT_VOID): case PACK(1, 8, SAMPLEFORMAT_VOID):
case PACK(1, 8, SAMPLEFORMAT_UINT): case PACK(1, 8, SAMPLEFORMAT_UINT):
return (SGILOGDATAFMT_8BIT); return (SGILOGDATAFMT_8BIT);
default:
break;
} }
#undef PACK #undef PACK
return (SGILOGDATAFMT_UNKNOWN); return (SGILOGDATAFMT_UNKNOWN);
@@ -1399,7 +1395,7 @@ static int LogL16InitState(TIFF *tif)
sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength); sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength);
if (multiply_ms(sp->tbuflen, sizeof(int16_t)) == 0 || if (multiply_ms(sp->tbuflen, sizeof(int16_t)) == 0 ||
(sp->tbuf = (uint8_t *)_TIFFmallocExt( (sp->tbuf = (uint8_t *)_TIFFmallocExt(
tif, sp->tbuflen * sizeof(int16_t))) == NULL) tif, (tmsize_t)((size_t)sp->tbuflen * sizeof(int16_t)))) == NULL)
{ {
TIFFErrorExtR(tif, module, "No space for SGILog translation buffer"); TIFFErrorExtR(tif, module, "No space for SGILog translation buffer");
return (0); return (0);
@@ -1506,7 +1502,7 @@ static int LogLuvInitState(TIFF *tif)
sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength); sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength);
if (multiply_ms(sp->tbuflen, sizeof(uint32_t)) == 0 || if (multiply_ms(sp->tbuflen, sizeof(uint32_t)) == 0 ||
(sp->tbuf = (uint8_t *)_TIFFmallocExt( (sp->tbuf = (uint8_t *)_TIFFmallocExt(
tif, sp->tbuflen * sizeof(uint32_t))) == NULL) tif, (tmsize_t)((size_t)sp->tbuflen * sizeof(uint32_t)))) == NULL)
{ {
TIFFErrorExtR(tif, module, "No space for SGILog translation buffer"); TIFFErrorExtR(tif, module, "No space for SGILog translation buffer");
return (0); return (0);
@@ -1546,6 +1542,8 @@ static int LogLuvSetupDecode(TIFF *tif)
case SGILOGDATAFMT_8BIT: case SGILOGDATAFMT_8BIT:
sp->tfunc = Luv24toRGB; sp->tfunc = Luv24toRGB;
break; break;
default:
break;
} }
} }
else else
@@ -1562,6 +1560,8 @@ static int LogLuvSetupDecode(TIFF *tif)
case SGILOGDATAFMT_8BIT: case SGILOGDATAFMT_8BIT:
sp->tfunc = Luv32toRGB; sp->tfunc = Luv32toRGB;
break; break;
default:
break;
} }
} }
return (1); return (1);
@@ -1577,6 +1577,8 @@ static int LogLuvSetupDecode(TIFF *tif)
case SGILOGDATAFMT_8BIT: case SGILOGDATAFMT_8BIT:
sp->tfunc = L16toGry; sp->tfunc = L16toGry;
break; break;
default:
break;
} }
return (1); return (1);
default: default:
@@ -1755,8 +1757,9 @@ static int LogLuvVSetField(TIFF *tif, uint32_t tag, va_list ap)
/* /*
* Must recalculate sizes should bits/sample change. * Must recalculate sizes should bits/sample change.
*/ */
tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)-1; tif->tif_dir.td_tilesize =
tif->tif_scanlinesize = TIFFScanlineSize(tif); isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)-1;
tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
return (1); return (1);
case TIFFTAG_SGILOGENCODE: case TIFFTAG_SGILOGENCODE:
sp->encode_meth = (int)va_arg(ap, int); sp->encode_meth = (int)va_arg(ap, int);

View File

@@ -95,6 +95,17 @@ static const char *LZMAStrerror(lzma_ret ret)
return "no progress is possible (stream is truncated or corrupt)"; return "no progress is possible (stream is truncated or corrupt)";
case LZMA_PROG_ERROR: case LZMA_PROG_ERROR:
return "programming error"; return "programming error";
#if LZMA_VERSION >= 50040000 /* 5.4.0 */
case LZMA_SEEK_NEEDED:
case LZMA_RET_INTERNAL1:
case LZMA_RET_INTERNAL2:
case LZMA_RET_INTERNAL3:
case LZMA_RET_INTERNAL4:
case LZMA_RET_INTERNAL5:
case LZMA_RET_INTERNAL6:
case LZMA_RET_INTERNAL7:
case LZMA_RET_INTERNAL8:
#endif
default: default:
return "unidentified liblzma error"; return "unidentified liblzma error";
} }
@@ -179,7 +190,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"LZMADecode: Scanline %" PRIu32 " cannot be read due to " "LZMADecode: Scanline %" PRIu32 " cannot be read due to "
"previous error", "previous error",
tif->tif_row); tif->tif_dir.td_row);
return 0; return 0;
} }
@@ -231,7 +242,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Decoding error at scanline %" PRIu32 ", %s", "Decoding error at scanline %" PRIu32 ", %s",
tif->tif_row, LZMAStrerror(ret)); tif->tif_dir.td_row, LZMAStrerror(ret));
break; break;
} }
} while (sp->stream.avail_out > 0); } while (sp->stream.avail_out > 0);
@@ -242,12 +253,12 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 "Not enough data at scanline %" PRIu32
" (short %" TIFF_SIZE_FORMAT " bytes)", " (short %" TIFF_SIZE_FORMAT " bytes)",
tif->tif_row, sp->stream.avail_out); tif->tif_dir.td_row, sp->stream.avail_out);
return 0; return 0;
} }
tif->tif_rawcp = (uint8_t *)sp->stream.next_in; /* cast away const */ tif->tif_rawcp = (uint8_t *)sp->stream.next_in; /* cast away const */
tif->tif_rawcc = sp->stream.avail_in; tif->tif_rawcc = (tmsize_t)sp->stream.avail_in;
return 1; return 1;
} }
@@ -326,7 +337,7 @@ static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Encoding error at scanline %" PRIu32 ", %s", "Encoding error at scanline %" PRIu32 ", %s",
tif->tif_row, LZMAStrerror(ret)); tif->tif_dir.td_row, LZMAStrerror(ret));
return 0; return 0;
} }
if (sp->stream.avail_out == 0) if (sp->stream.avail_out == 0)
@@ -365,7 +376,7 @@ static int LZMAPostEncode(TIFF *tif)
if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
{ {
tif->tif_rawcc = tif->tif_rawcc =
tif->tif_rawdatasize - sp->stream.avail_out; tif->tif_rawdatasize - (tmsize_t)sp->stream.avail_out;
if (!TIFFFlushData1(tif)) if (!TIFFFlushData1(tif))
return 0; return 0;
sp->stream.next_out = tif->tif_rawdata; sp->stream.next_out = tif->tif_rawdata;
@@ -376,6 +387,27 @@ static int LZMAPostEncode(TIFF *tif)
ZIPPreEncode */ ZIPPreEncode */
} }
break; break;
case LZMA_NO_CHECK:
case LZMA_UNSUPPORTED_CHECK:
case LZMA_GET_CHECK:
case LZMA_MEM_ERROR:
case LZMA_MEMLIMIT_ERROR:
case LZMA_FORMAT_ERROR:
case LZMA_OPTIONS_ERROR:
case LZMA_DATA_ERROR:
case LZMA_BUF_ERROR:
case LZMA_PROG_ERROR:
#if LZMA_VERSION >= 50040000 /* 5.4.0 */
case LZMA_SEEK_NEEDED:
case LZMA_RET_INTERNAL1:
case LZMA_RET_INTERNAL2:
case LZMA_RET_INTERNAL3:
case LZMA_RET_INTERNAL4:
case LZMA_RET_INTERNAL5:
case LZMA_RET_INTERNAL6:
case LZMA_RET_INTERNAL7:
case LZMA_RET_INTERNAL8:
#endif
default: default:
TIFFErrorExtR(tif, module, "Liblzma error: %s", TIFFErrorExtR(tif, module, "Liblzma error: %s",
LZMAStrerror(ret)); LZMAStrerror(ret));
@@ -416,7 +448,7 @@ static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
{ {
case TIFFTAG_LZMAPRESET: case TIFFTAG_LZMAPRESET:
sp->preset = (int)va_arg(ap, int); sp->preset = (int)va_arg(ap, int);
lzma_lzma_preset(&sp->opt_lzma, sp->preset); lzma_lzma_preset(&sp->opt_lzma, (uint32_t)sp->preset);
if (sp->state & LSTATE_INIT_ENCODE) if (sp->state & LSTATE_INIT_ENCODE)
{ {
lzma_ret ret = lzma_ret ret =
@@ -454,6 +486,21 @@ static const TIFFField lzmaFields[] = {
FALSE, "LZMA2 Compression Preset", NULL}, FALSE, "LZMA2 Compression Preset", NULL},
}; };
static uint64_t LZMAGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* 1024x1024: 3800 */
/* 4096x4096: 6534 */
/* 16383x16383: 6846 */
/* 65536x65536: 6874 */
return 7000;
}
int TIFFInitLZMA(TIFF *tif, int scheme) int TIFFInitLZMA(TIFF *tif, int scheme)
{ {
static const char module[] = "TIFFInitLZMA"; static const char module[] = "TIFFInitLZMA";
@@ -506,7 +553,7 @@ int TIFFInitLZMA(TIFF *tif, int scheme)
sp->filters[0].id = LZMA_FILTER_DELTA; sp->filters[0].id = LZMA_FILTER_DELTA;
sp->filters[0].options = &sp->opt_delta; sp->filters[0].options = &sp->opt_delta;
lzma_lzma_preset(&sp->opt_lzma, sp->preset); lzma_lzma_preset(&sp->opt_lzma, (uint32_t)sp->preset);
sp->filters[1].id = LZMA_FILTER_LZMA2; sp->filters[1].id = LZMA_FILTER_LZMA2;
sp->filters[1].options = &sp->opt_lzma; sp->filters[1].options = &sp->opt_lzma;
@@ -529,6 +576,8 @@ int TIFFInitLZMA(TIFF *tif, int scheme)
tif->tif_encodestrip = LZMAEncode; tif->tif_encodestrip = LZMAEncode;
tif->tif_encodetile = LZMAEncode; tif->tif_encodetile = LZMAEncode;
tif->tif_cleanup = LZMACleanup; tif->tif_cleanup = LZMACleanup;
tif->tif_getmaxcompressionratio = LZMAGetMaxCompressionRatio;
/* /*
* Setup predictor setup. * Setup predictor setup.
*/ */

View File

@@ -60,7 +60,7 @@ typedef size_t WordType;
*/ */
#define LZW_COMPAT /* include backwards compatibility code */ #define LZW_COMPAT /* include backwards compatibility code */
#define MAXCODE(n) ((1L << (n)) - 1) #define MAXCODE(n) ((1 << (n)) - 1)
/* /*
* The TIFF spec specifies that encoded bit * The TIFF spec specifies that encoded bit
* strings range from 9 to 12 bits. * strings range from 9 to 12 bits.
@@ -72,7 +72,7 @@ typedef size_t WordType;
#define CODE_EOI 257 /* end-of-information code */ #define CODE_EOI 257 /* end-of-information code */
#define CODE_FIRST 258 /* first free code entry */ #define CODE_FIRST 258 /* first free code entry */
#define CODE_MAX MAXCODE(BITS_MAX) #define CODE_MAX MAXCODE(BITS_MAX)
#define HSIZE 9001L /* 91% occupancy */ #define HSIZE 9001 /* 91% occupancy */
#define HSHIFT (13 - 8) #define HSHIFT (13 - 8)
#ifdef LZW_COMPAT #ifdef LZW_COMPAT
/* NB: +1024 is for compatibility with old files */ /* NB: +1024 is for compatibility with old files */
@@ -325,7 +325,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
*/ */
/* Get the next 32 or 64-bit from the input data */ /* Get the next 32 or 64-bit from the input data */
#ifdef WORDS_BIGENDIAN #if WORDS_BIGENDIAN
#define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata)) #define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata))
#elif SIZEOF_WORDTYPE == 8 #elif SIZEOF_WORDTYPE == 8
#if defined(_M_X64) #if defined(_M_X64)
@@ -372,7 +372,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
nextbits += 8 * SIZEOF_WORDTYPE; \ nextbits += 8 * SIZEOF_WORDTYPE; \
dec_bitsleft -= 8 * SIZEOF_WORDTYPE; \ dec_bitsleft -= 8 * SIZEOF_WORDTYPE; \
code = (WordType)((codetmp | (nextdata >> nextbits)) & \ code = (WordType)((codetmp | (nextdata >> nextbits)) & \
nbitsmask); \ (WordType)nbitsmask); \
break; \ break; \
} \ } \
else \ else \
@@ -396,7 +396,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
} \ } \
} \ } \
} \ } \
code = (WordType)((nextdata >> nextbits) & nbitsmask); \ code = (WordType)((nextdata >> nextbits) & (WordType)nbitsmask); \
} while (0) } while (0)
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
@@ -420,7 +420,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"LZWDecode: Scanline %" PRIu32 " cannot be read due to " "LZWDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error", "previous error",
tif->tif_row); tif->tif_dir.td_row);
return 0; return 0;
} }
@@ -472,7 +472,8 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
} }
bp = (uint8_t *)tif->tif_rawcp; bp = (uint8_t *)tif->tif_rawcp;
sp->dec_bitsleft += (((uint64_t)tif->tif_rawcc - sp->old_tif_rawcc) << 3); sp->dec_bitsleft +=
(((uint64_t)tif->tif_rawcc - (uint64_t)sp->old_tif_rawcc) << 3);
uint64_t dec_bitsleft = sp->dec_bitsleft; uint64_t dec_bitsleft = sp->dec_bitsleft;
nbits = sp->lzw_nbits; nbits = sp->lzw_nbits;
nextdata = sp->lzw_nextdata; nextdata = sp->lzw_nextdata;
@@ -493,7 +494,7 @@ begin:
{ {
WordType code; WordType code;
GetNextCodeLZW(); GetNextCodeLZW();
codep = dec_codetab + code; codep = dec_codetab + (unsigned long)code;
if (code >= CODE_FIRST) if (code >= CODE_FIRST)
goto code_above_or_equal_to_258; goto code_above_or_equal_to_258;
if (code < 256) if (code < 256)
@@ -508,7 +509,7 @@ code_below_256:
goto error_code; goto error_code;
free_entp->next = oldcodep; free_entp->next = oldcodep;
free_entp->firstchar = oldcodep->firstchar; free_entp->firstchar = oldcodep->firstchar;
free_entp->length = oldcodep->length + 1; free_entp->length = (uint16_t)(oldcodep->length + 1);
free_entp->value = (uint8_t)code; free_entp->value = (uint8_t)code;
free_entp->repeated = free_entp->repeated =
(bool)(oldcodep->repeated & (oldcodep->value == code)); (bool)(oldcodep->repeated & (oldcodep->value == code));
@@ -556,7 +557,7 @@ code_above_or_equal_to_258:
free_entp->next = oldcodep; free_entp->next = oldcodep;
free_entp->firstchar = oldcodep->firstchar; free_entp->firstchar = oldcodep->firstchar;
free_entp->length = oldcodep->length + 1; free_entp->length = (uint16_t)(oldcodep->length + 1);
if (++free_entp > maxcodep) if (++free_entp > maxcodep)
{ {
if (++nbits > BITS_MAX) /* should not happen for a conformant encoder */ if (++nbits > BITS_MAX) /* should not happen for a conformant encoder */
@@ -673,7 +674,7 @@ code_clear:
free_entp = dec_codetab + CODE_FIRST; free_entp = dec_codetab + CODE_FIRST;
nbits = BITS_MIN; nbits = BITS_MIN;
nbitsmask = MAXCODE(BITS_MIN); nbitsmask = MAXCODE(BITS_MIN);
maxcodep = dec_codetab + nbitsmask - 1; maxcodep = dec_codetab + (unsigned long)nbitsmask - 1;
do do
{ {
GetNextCodeLZW(); GetNextCodeLZW();
@@ -736,7 +737,7 @@ after_loop:
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 " (short %" PRIu64 "Not enough data at scanline %" PRIu32 " (short %" PRIu64
" bytes)", " bytes)",
tif->tif_row, (uint64_t)occ); tif->tif_dir.td_row, (uint64_t)occ);
return (0); return (0);
} }
return (1); return (1);
@@ -746,7 +747,7 @@ no_eoi:
sp->read_error = 1; sp->read_error = 1;
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"LZWDecode: Strip %" PRIu32 " not terminated with EOI code", "LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
tif->tif_curstrip); tif->tif_dir.td_curstrip);
return 0; return 0;
error_code: error_code:
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
@@ -768,13 +769,13 @@ error_code:
TIFFWarningExtR(_tif, module, \ TIFFWarningExtR(_tif, module, \
"LZWDecode: Strip %" PRIu32 \ "LZWDecode: Strip %" PRIu32 \
" not terminated with EOI code", \ " not terminated with EOI code", \
_tif->tif_curstrip); \ _tif->tif_dir.td_curstrip); \
_code = CODE_EOI; \ _code = CODE_EOI; \
} \ } \
else \ else \
{ \ { \
_get(_sp, _bp, _code); \ _get(_sp, _bp, _code); \
dec_bitsleft -= nbits; \ dec_bitsleft -= (uint64_t)nbits; \
} \ } \
} }
@@ -790,7 +791,7 @@ error_code:
nextdata |= (unsigned long)*(bp)++ << nextbits; \ nextdata |= (unsigned long)*(bp)++ << nextbits; \
nextbits += 8; \ nextbits += 8; \
} \ } \
code = (hcode_t)(nextdata & nbitsmask); \ code = (hcode_t)(nextdata & (unsigned long)nbitsmask); \
nextdata >>= nbits; \ nextdata >>= nbits; \
nextbits -= nbits; \ nextbits -= nbits; \
} }
@@ -858,7 +859,8 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
bp = (uint8_t *)tif->tif_rawcp; bp = (uint8_t *)tif->tif_rawcp;
sp->dec_bitsleft += (((uint64_t)tif->tif_rawcc - sp->old_tif_rawcc) << 3); sp->dec_bitsleft +=
(((uint64_t)tif->tif_rawcc - (uint64_t)sp->old_tif_rawcc) << 3);
uint64_t dec_bitsleft = sp->dec_bitsleft; uint64_t dec_bitsleft = sp->dec_bitsleft;
nbits = sp->lzw_nbits; nbits = sp->lzw_nbits;
@@ -893,7 +895,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
TIFFErrorExtR( TIFFErrorExtR(
tif, tif->tif_name, tif, tif->tif_name,
"LZWDecode: Corrupted LZW table at scanline %" PRIu32, "LZWDecode: Corrupted LZW table at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
*op++ = (uint8_t)code; *op++ = (uint8_t)code;
@@ -911,7 +913,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Corrupted LZW table at scanline %" PRIu32, "Corrupted LZW table at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
@@ -921,11 +923,11 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Corrupted LZW table at scanline %" PRIu32, "Corrupted LZW table at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
free_entp->firstchar = free_entp->next->firstchar; free_entp->firstchar = free_entp->next->firstchar;
free_entp->length = free_entp->next->length + 1; free_entp->length = (uint16_t)(free_entp->next->length + 1);
free_entp->value = free_entp->value =
(codep < free_entp) ? codep->firstchar : free_entp->firstchar; (codep < free_entp) ? codep->firstchar : free_entp->firstchar;
if (++free_entp > maxcodep) if (++free_entp > maxcodep)
@@ -948,7 +950,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
tif, module, tif, module,
"Wrong length of decoded " "Wrong length of decoded "
"string: data probably corrupted at scanline %" PRIu32, "string: data probably corrupted at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
if (codep->length > occ) if (codep->length > occ)
@@ -1010,7 +1012,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 " (short %" PRIu64 "Not enough data at scanline %" PRIu32 " (short %" PRIu64
" bytes)", " bytes)",
tif->tif_row, (uint64_t)occ); tif->tif_dir.td_row, (uint64_t)occ);
return (0); return (0);
} }
return (1); return (1);
@@ -1116,10 +1118,10 @@ static int LZWPreEncode(TIFF *tif, uint16_t s)
*/ */
static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{ {
register LZWCodecState *sp = LZWEncoderState(tif); LZWCodecState *sp = LZWEncoderState(tif);
register long fcode; long fcode;
register hash_t *hp; hash_t *hp;
register int h, c; int h, c;
hcode_t ent; hcode_t ent;
long disp; long disp;
tmsize_t incount, outcount, checkpoint; tmsize_t incount, outcount, checkpoint;
@@ -1196,7 +1198,7 @@ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
* Avoid pointer arithmetic because of * Avoid pointer arithmetic because of
* wraparound problems with segments. * wraparound problems with segments.
*/ */
if ((h -= disp) < 0) if ((h -= (int)disp) < 0)
h += HSIZE; h += HSIZE;
hp = &sp->enc_hashtab[h]; hp = &sp->enc_hashtab[h];
if (hp->hash == fcode) if (hp->hash == fcode)
@@ -1301,7 +1303,7 @@ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
*/ */
static int LZWPostEncode(TIFF *tif) static int LZWPostEncode(TIFF *tif)
{ {
register LZWCodecState *sp = LZWEncoderState(tif); LZWCodecState *sp = LZWEncoderState(tif);
uint8_t *op = tif->tif_rawcp; uint8_t *op = tif->tif_rawcp;
long nextbits = sp->lzw_nextbits; long nextbits = sp->lzw_nextbits;
WordType nextdata = sp->lzw_nextdata; WordType nextdata = sp->lzw_nextdata;
@@ -1319,7 +1321,7 @@ static int LZWPostEncode(TIFF *tif)
{ {
int free_ent = sp->lzw_free_ent; int free_ent = sp->lzw_free_ent;
PutNextCode(op, sp->enc_oldcode); PutNextCode(op, (WordType)sp->enc_oldcode);
sp->enc_oldcode = (hcode_t)-1; sp->enc_oldcode = (hcode_t)-1;
free_ent++; free_ent++;
@@ -1357,8 +1359,8 @@ static int LZWPostEncode(TIFF *tif)
*/ */
static void cl_hash(LZWCodecState *sp) static void cl_hash(LZWCodecState *sp)
{ {
register hash_t *hp = &sp->enc_hashtab[HSIZE - 1]; hash_t *hp = &sp->enc_hashtab[HSIZE - 1];
register long i = HSIZE - 8; long i = HSIZE - 8;
do do
{ {
@@ -1397,6 +1399,21 @@ static void LZWCleanup(TIFF *tif)
_TIFFSetDefaultCompressionState(tif); _TIFFSetDefaultCompressionState(tif);
} }
static uint64_t LZWGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* 1024x1024: 562 */
/* 4096x4096: 1243 */
/* 16383x16383: 1353 */
/* 65536x65536: 1362 */
return 1400;
}
int TIFFInitLZW(TIFF *tif, int scheme) int TIFFInitLZW(TIFF *tif, int scheme)
{ {
static const char module[] = "TIFFInitLZW"; static const char module[] = "TIFFInitLZW";
@@ -1430,6 +1447,7 @@ int TIFFInitLZW(TIFF *tif, int scheme)
tif->tif_encodestrip = LZWEncode; tif->tif_encodestrip = LZWEncode;
tif->tif_encodetile = LZWEncode; tif->tif_encodetile = LZWEncode;
#endif #endif
tif->tif_getmaxcompressionratio = LZWGetMaxCompressionRatio;
tif->tif_cleanup = LZWCleanup; tif->tif_cleanup = LZWCleanup;
/* /*
* Setup predictor setup. * Setup predictor setup.

View File

@@ -38,21 +38,22 @@
op[0] = (unsigned char)((v) << 6); \ op[0] = (unsigned char)((v) << 6); \
break; \ break; \
case 1: \ case 1: \
op[0] |= (v) << 4; \ op[0] |= (unsigned char)((v) << 4); \
break; \ break; \
case 2: \ case 2: \
op[0] |= (v) << 2; \ op[0] |= (unsigned char)((v) << 2); \
break; \ break; \
case 3: \ case 3: \
*op++ |= (v); \ *op++ |= (unsigned char)(v); \
op_offset++; \ op_offset++; \
break; \ break; \
default: \
break; \
} \ } \
} }
#define LITERALROW 0x00 #define LITERALROW 0x00
#define LITERALSPAN 0x40 #define LITERALSPAN 0x40
#define WHITE ((1 << 2) - 1)
static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
{ {
@@ -73,7 +74,7 @@ static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
bp = (unsigned char *)tif->tif_rawcp; bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc; cc = tif->tif_rawcc;
scanline = tif->tif_scanlinesize; scanline = tif->tif_dir.td_scanlinesize;
if (occ % scanline) if (occ % scanline)
{ {
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
@@ -146,7 +147,7 @@ static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Invalid data for scanline %" PRIu32, "Invalid data for scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
if (cc == 0) if (cc == 0)
@@ -163,7 +164,7 @@ static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
return (1); return (1);
bad: bad:
TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32, TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }

View File

@@ -122,9 +122,6 @@
restarting of LibJpeg decoding session. restarting of LibJpeg decoding session.
*/ */
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include "tiffiop.h" #include "tiffiop.h"
#ifdef OJPEG_SUPPORT #ifdef OJPEG_SUPPORT
@@ -209,18 +206,12 @@ static const TIFFField ojpegFields[] = {
#include "jerror.h" #include "jerror.h"
#include "jpeglib.h" #include "jpeglib.h"
#ifndef TIFF_jpeg_source_mgr_defined typedef struct jpeg_source_mgr tiff_ojpeg_source_mgr;
#define TIFF_jpeg_source_mgr_defined
typedef struct jpeg_source_mgr jpeg_source_mgr;
#endif
#ifndef TIFF_jpeg_error_mgr_defined typedef struct jpeg_error_mgr tiff_ojpeg_error_mgr;
#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_common_struct tiff_ojpeg_common_struct;
typedef struct jpeg_decompress_struct jpeg_decompress_struct; typedef struct jpeg_decompress_struct tiff_ojpeg_decompress_struct;
typedef enum typedef enum
{ {
@@ -316,9 +307,9 @@ typedef struct
uint32_t write_curstrile; uint32_t write_curstrile;
uint8_t libjpeg_session_active; uint8_t libjpeg_session_active;
uint8_t libjpeg_jpeg_query_style; uint8_t libjpeg_jpeg_query_style;
jpeg_error_mgr libjpeg_jpeg_error_mgr; tiff_ojpeg_error_mgr libjpeg_jpeg_error_mgr;
jpeg_decompress_struct libjpeg_jpeg_decompress_struct; tiff_ojpeg_decompress_struct libjpeg_jpeg_decompress_struct;
jpeg_source_mgr libjpeg_jpeg_source_mgr; tiff_ojpeg_source_mgr libjpeg_jpeg_source_mgr;
uint8_t subsampling_convert_log; uint8_t subsampling_convert_log;
uint32_t subsampling_convert_ylinelen; uint32_t subsampling_convert_ylinelen;
uint32_t subsampling_convert_ylines; uint32_t subsampling_convert_ylines;
@@ -413,46 +404,51 @@ static void OJPEGWriteStreamEoi(TIFF *tif, void **mem, uint32_t *len);
#ifdef LIBJPEG_ENCAP_EXTERNAL #ifdef LIBJPEG_ENCAP_EXTERNAL
extern int jpeg_create_decompress_encap(OJPEGState *sp, extern int jpeg_create_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo); tiff_ojpeg_decompress_struct *cinfo);
extern int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo, extern int jpeg_read_header_encap(OJPEGState *sp,
tiff_ojpeg_decompress_struct *cinfo,
uint8_t require_image); uint8_t require_image);
extern int jpeg_start_decompress_encap(OJPEGState *sp, extern int jpeg_start_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo); tiff_ojpeg_decompress_struct *cinfo);
extern int jpeg_read_scanlines_encap(OJPEGState *sp, extern int jpeg_read_scanlines_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, tiff_ojpeg_decompress_struct *cinfo,
void *scanlines, uint32_t max_lines); void *scanlines, uint32_t max_lines);
extern int jpeg_read_raw_data_encap(OJPEGState *sp, extern int jpeg_read_raw_data_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, void *data, tiff_ojpeg_decompress_struct *cinfo,
uint32_t max_lines); void *data, uint32_t max_lines);
extern void jpeg_encap_unwind(TIFF *tif); extern void jpeg_encap_unwind(TIFF *tif);
#else #else
static int jpeg_create_decompress_encap(OJPEGState *sp, static int jpeg_create_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *j); tiff_ojpeg_decompress_struct *j);
static int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo, static int jpeg_read_header_encap(OJPEGState *sp,
tiff_ojpeg_decompress_struct *cinfo,
uint8_t require_image); uint8_t require_image);
static int jpeg_start_decompress_encap(OJPEGState *sp, static int jpeg_start_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo); tiff_ojpeg_decompress_struct *cinfo);
static int jpeg_read_scanlines_encap(OJPEGState *sp, static int jpeg_read_scanlines_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, tiff_ojpeg_decompress_struct *cinfo,
void *scanlines, uint32_t max_lines); void *scanlines, uint32_t max_lines);
static int jpeg_read_raw_data_encap(OJPEGState *sp, static int jpeg_read_raw_data_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, void *data, tiff_ojpeg_decompress_struct *cinfo,
uint32_t max_lines); void *data, uint32_t max_lines);
static void jpeg_encap_unwind(TIFF *tif); static void jpeg_encap_unwind(TIFF *tif);
#endif #endif
static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct *cinfo);
static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct *cinfo);
static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct *cinfo);
static boolean
OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct *cinfo);
static void static void
OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct *cinfo, OJPEGLibjpegJpegErrorMgrOutputMessage(tiff_ojpeg_common_struct *cinfo);
static void OJPEGLibjpegJpegErrorMgrErrorExit(tiff_ojpeg_common_struct *cinfo);
static void
OJPEGLibjpegJpegSourceMgrInitSource(tiff_ojpeg_decompress_struct *cinfo);
static boolean
OJPEGLibjpegJpegSourceMgrFillInputBuffer(tiff_ojpeg_decompress_struct *cinfo);
static void
OJPEGLibjpegJpegSourceMgrSkipInputData(tiff_ojpeg_decompress_struct *cinfo,
long num_bytes); long num_bytes);
static boolean static boolean
OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct *cinfo, OJPEGLibjpegJpegSourceMgrResyncToRestart(tiff_ojpeg_decompress_struct *cinfo,
int desired); int desired);
static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct *cinfo); static void
OJPEGLibjpegJpegSourceMgrTermSource(tiff_ojpeg_decompress_struct *cinfo);
int TIFFInitOJPEG(TIFF *tif, int scheme) int TIFFInitOJPEG(TIFF *tif, int scheme)
{ {
@@ -473,7 +469,7 @@ int TIFFInitOJPEG(TIFF *tif, int scheme)
} }
/* state block */ /* state block */
sp = _TIFFmallocExt(tif, sizeof(OJPEGState)); sp = (OJPEGState *)_TIFFmallocExt(tif, sizeof(OJPEGState));
if (sp == NULL) if (sp == NULL)
{ {
TIFFErrorExtR(tif, module, "No space for OJPEG state block"); TIFFErrorExtR(tif, module, "No space for OJPEG state block");
@@ -724,9 +720,9 @@ static int OJPEGPreDecode(TIFF *tif, uint16_t s)
return (0); return (0);
} }
if (isTiled(tif)) if (isTiled(tif))
m = tif->tif_curtile; m = tif->tif_dir.td_curtile;
else else
m = tif->tif_curstrip; m = tif->tif_dir.td_curstrip;
if ((sp->writeheader_done != 0) && if ((sp->writeheader_done != 0) &&
((sp->write_cursample != s) || (sp->write_curstrile > m))) ((sp->write_cursample != s) || (sp->write_curstrile > m)))
{ {
@@ -797,7 +793,7 @@ static int OJPEGPreDecodeSkipRaw(TIFF *tif)
{ {
if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct), if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
sp->subsampling_convert_ycbcrimage, sp->subsampling_convert_ycbcrimage,
sp->subsampling_ver * 8) == 0) (uint32_t)sp->subsampling_ver * 8) == 0)
return (0); return (0);
m -= sp->subsampling_convert_clines; m -= sp->subsampling_convert_clines;
} }
@@ -805,7 +801,7 @@ static int OJPEGPreDecodeSkipRaw(TIFF *tif)
{ {
if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct), if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
sp->subsampling_convert_ycbcrimage, sp->subsampling_convert_ycbcrimage,
sp->subsampling_ver * 8) == 0) (uint32_t)sp->subsampling_ver * 8) == 0)
return (0); return (0);
sp->subsampling_convert_state = m; sp->subsampling_convert_state = m;
} }
@@ -819,7 +815,7 @@ static int OJPEGPreDecodeSkipScanlines(TIFF *tif)
uint32_t m; uint32_t m;
if (sp->skip_buffer == NULL) if (sp->skip_buffer == NULL)
{ {
sp->skip_buffer = _TIFFmallocExt(tif, sp->bytes_per_line); sp->skip_buffer = (uint8_t *)_TIFFmallocExt(tif, sp->bytes_per_line);
if (sp->skip_buffer == NULL) if (sp->skip_buffer == NULL)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -910,10 +906,10 @@ static int OJPEGDecodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc)
{ {
if (sp->subsampling_convert_state == 0) if (sp->subsampling_convert_state == 0)
{ {
if (jpeg_read_raw_data_encap(sp, if (jpeg_read_raw_data_encap(
&(sp->libjpeg_jpeg_decompress_struct), sp, &(sp->libjpeg_jpeg_decompress_struct),
sp->subsampling_convert_ycbcrimage, sp->subsampling_convert_ycbcrimage,
sp->subsampling_ver * 8) == 0) (uint32_t)sp->subsampling_ver * 8) == 0)
{ {
sp->error_in_raw_data_decoding = 1; sp->error_in_raw_data_decoding = 1;
return (0); return (0);
@@ -1225,7 +1221,7 @@ static int OJPEGReadHeaderInfo(TIFF *tif)
TIFFErrorExtR(tif, module, "Invalid subsampling values"); TIFFErrorExtR(tif, module, "Invalid subsampling values");
return (0); return (0);
} }
if (sp->strile_length % (sp->subsampling_ver * 8) != 0) if (sp->strile_length % ((uint32_t)sp->subsampling_ver * 8) != 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Incompatible vertical subsampling and image " "Incompatible vertical subsampling and image "
@@ -1233,9 +1229,11 @@ static int OJPEGReadHeaderInfo(TIFF *tif)
return (0); return (0);
} }
sp->restart_interval = sp->restart_interval =
(uint16_t)(((sp->strile_width + sp->subsampling_hor * 8 - 1) / (uint16_t)(((sp->strile_width + (uint32_t)sp->subsampling_hor * 8 -
(sp->subsampling_hor * 8)) * 1) /
(sp->strile_length / (sp->subsampling_ver * 8))); ((uint32_t)sp->subsampling_hor * 8)) *
(sp->strile_length /
((uint32_t)sp->subsampling_ver * 8)));
} }
if (OJPEGReadHeaderInfoSec(tif) == 0) if (OJPEGReadHeaderInfoSec(tif) == 0)
return (0); return (0);
@@ -1358,20 +1356,43 @@ static int OJPEGWriteHeaderInfo(TIFF *tif)
/* Check for division by zero. */ /* Check for division by zero. */
if (sp->subsampling_hor == 0 || sp->subsampling_ver == 0) if (sp->subsampling_hor == 0 || sp->subsampling_ver == 0)
return (0); return (0);
/* Check for potential overflow in subsampling_convert_ylinelen
* computation.
*/
if (sp->strile_width >
UINT32_MAX - ((uint32_t)sp->subsampling_hor * 8 - 1))
return (0);
sp->subsampling_convert_ylinelen = sp->subsampling_convert_ylinelen =
((sp->strile_width + sp->subsampling_hor * 8 - 1) / ((sp->strile_width + (uint32_t)sp->subsampling_hor * 8 - 1) /
(sp->subsampling_hor * 8) * sp->subsampling_hor * 8); ((uint32_t)sp->subsampling_hor * 8) *
sp->subsampling_convert_ylines = sp->subsampling_ver * 8; ((uint32_t)sp->subsampling_hor * 8));
sp->subsampling_convert_ylines = (uint32_t)sp->subsampling_ver * 8;
sp->subsampling_convert_clinelen = sp->subsampling_convert_clinelen =
sp->subsampling_convert_ylinelen / sp->subsampling_hor; sp->subsampling_convert_ylinelen / sp->subsampling_hor;
sp->subsampling_convert_clines = 8; sp->subsampling_convert_clines = 8;
sp->subsampling_convert_ybuflen = sp->subsampling_convert_ylinelen * /* Check for potential overflow in buffer length computations.
sp->subsampling_convert_ylines; * Use 64-bit intermediates to detect uint32_t overflow in
sp->subsampling_convert_cbuflen = sp->subsampling_convert_clinelen * * ylinelen * ylines, clinelen * clines, and their sum.
sp->subsampling_convert_clines; */
sp->subsampling_convert_ycbcrbuflen = {
sp->subsampling_convert_ybuflen + uint64_t ybuflen64 =
2 * sp->subsampling_convert_cbuflen; (uint64_t)sp->subsampling_convert_ylinelen *
sp->subsampling_convert_ylines;
uint64_t cbuflen64 =
(uint64_t)sp->subsampling_convert_clinelen *
sp->subsampling_convert_clines;
uint64_t ycbcrbuflen64 = ybuflen64 + 2 * cbuflen64;
if (ybuflen64 > UINT32_MAX || cbuflen64 > UINT32_MAX ||
ycbcrbuflen64 > UINT32_MAX)
{
TIFFErrorExtR(tif, module,
"Integer overflow in OJPEG buffer size");
return (0);
}
sp->subsampling_convert_ybuflen = (uint32_t)ybuflen64;
sp->subsampling_convert_cbuflen = (uint32_t)cbuflen64;
sp->subsampling_convert_ycbcrbuflen = (uint32_t)ycbcrbuflen64;
}
/* The calloc is not normally necessary, except in some edge/broken /* The calloc is not normally necessary, except in some edge/broken
* cases */ * cases */
/* for example for a tiled image of height 1 with a tile height of 1 /* for example for a tiled image of height 1 with a tile height of 1
@@ -1383,8 +1404,8 @@ static int OJPEGWriteHeaderInfo(TIFF *tif)
/* Even if this case is allowed (?), its handling is broken because /* Even if this case is allowed (?), its handling is broken because
* OJPEGPreDecode() should also likely */ * OJPEGPreDecode() should also likely */
/* reset subsampling_convert_state to 0 when changing tile. */ /* reset subsampling_convert_state to 0 when changing tile. */
sp->subsampling_convert_ycbcrbuf = sp->subsampling_convert_ycbcrbuf = (uint8_t *)_TIFFcallocExt(
_TIFFcallocExt(tif, 1, sp->subsampling_convert_ycbcrbuflen); tif, 1, sp->subsampling_convert_ycbcrbuflen);
if (sp->subsampling_convert_ycbcrbuf == 0) if (sp->subsampling_convert_ycbcrbuf == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1398,8 +1419,9 @@ static int OJPEGWriteHeaderInfo(TIFF *tif)
sp->subsampling_convert_ycbcrimagelen = sp->subsampling_convert_ycbcrimagelen =
3 + sp->subsampling_convert_ylines + 3 + sp->subsampling_convert_ylines +
2 * sp->subsampling_convert_clines; 2 * sp->subsampling_convert_clines;
sp->subsampling_convert_ycbcrimage = _TIFFmallocExt( sp->subsampling_convert_ycbcrimage = (uint8_t **)_TIFFmallocExt(
tif, sp->subsampling_convert_ycbcrimagelen * sizeof(uint8_t *)); tif, (tmsize_t)((size_t)sp->subsampling_convert_ycbcrimagelen *
sizeof(uint8_t *)));
if (sp->subsampling_convert_ycbcrimage == 0) if (sp->subsampling_convert_ycbcrimage == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1426,9 +1448,14 @@ static int OJPEGWriteHeaderInfo(TIFF *tif)
((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0); ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0);
sp->subsampling_convert_state = 0; sp->subsampling_convert_state = 0;
sp->error_in_raw_data_decoding = 0; sp->error_in_raw_data_decoding = 0;
sp->bytes_per_line =
sp->subsampling_convert_clinelenout * const uint64_t bpl =
(sp->subsampling_ver * sp->subsampling_hor + 2); (uint64_t)sp->subsampling_convert_clinelenout *
((uint64_t)sp->subsampling_ver * sp->subsampling_hor + 2);
if (bpl > UINT32_MAX)
return (0);
sp->bytes_per_line = (uint32_t)bpl;
sp->lines_per_strile = sp->lines_per_strile =
sp->strile_length / sp->subsampling_ver + sp->strile_length / sp->subsampling_ver +
((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0); ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0);
@@ -1478,7 +1505,8 @@ static void OJPEGLibjpegSessionAbort(TIFF *tif)
{ {
OJPEGState *sp = (OJPEGState *)tif->tif_data; OJPEGState *sp = (OJPEGState *)tif->tif_data;
assert(sp->libjpeg_session_active != 0); assert(sp->libjpeg_session_active != 0);
jpeg_destroy((jpeg_common_struct *)(&(sp->libjpeg_jpeg_decompress_struct))); jpeg_destroy(
(tiff_ojpeg_common_struct *)(&(sp->libjpeg_jpeg_decompress_struct)));
sp->libjpeg_session_active = 0; sp->libjpeg_session_active = 0;
} }
@@ -1560,7 +1588,7 @@ static int OJPEGReadHeaderInfoSec(TIFF *tif)
return (0); return (0);
} }
if (n > 2) if (n > 2)
OJPEGReadSkip(sp, n - 2); OJPEGReadSkip(sp, (uint16_t)(n - 2));
break; break;
case JPEG_MARKER_DRI: case JPEG_MARKER_DRI:
if (OJPEGReadHeaderInfoSecStreamDri(tif) == 0) if (OJPEGReadHeaderInfoSecStreamDri(tif) == 0)
@@ -1603,8 +1631,9 @@ static int OJPEGReadHeaderInfoSec(TIFF *tif)
return (0); return (0);
sp->sof_marker_id = JPEG_MARKER_SOF0; sp->sof_marker_id = JPEG_MARKER_SOF0;
for (o = 0; o < sp->samples_per_pixel; o++) for (o = 0; o < sp->samples_per_pixel; o++)
sp->sof_c[o] = o; sp->sof_c[o] = (uint8_t)o;
sp->sof_hv[0] = ((sp->subsampling_hor << 4) | sp->subsampling_ver); sp->sof_hv[0] =
(uint8_t)((sp->subsampling_hor << 4) | sp->subsampling_ver);
for (o = 1; o < sp->samples_per_pixel; o++) for (o = 1; o < sp->samples_per_pixel; o++)
sp->sof_hv[o] = 17; sp->sof_hv[o] = 17;
sp->sof_x = sp->strile_width; sp->sof_x = sp->strile_width;
@@ -1659,10 +1688,10 @@ static int OJPEGReadHeaderInfoSecStreamDqt(TIFF *tif)
return (0); return (0);
} }
if (sp->subsamplingcorrect != 0) if (sp->subsamplingcorrect != 0)
OJPEGReadSkip(sp, m - 2); OJPEGReadSkip(sp, (uint16_t)(m - 2));
else else
{ {
m -= 2; m = (uint16_t)(m - 2);
do do
{ {
if (m < 65) if (m < 65)
@@ -1671,7 +1700,7 @@ static int OJPEGReadHeaderInfoSecStreamDqt(TIFF *tif)
return (0); return (0);
} }
na = sizeof(uint32_t) + 69; na = sizeof(uint32_t) + 69;
nb = _TIFFmallocExt(tif, na); nb = (uint8_t *)_TIFFmallocExt(tif, na);
if (nb == 0) if (nb == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1697,7 +1726,7 @@ static int OJPEGReadHeaderInfoSecStreamDqt(TIFF *tif)
if (sp->qtable[o] != 0) if (sp->qtable[o] != 0)
_TIFFfreeExt(tif, sp->qtable[o]); _TIFFfreeExt(tif, sp->qtable[o]);
sp->qtable[o] = nb; sp->qtable[o] = nb;
m -= 65; m = (uint16_t)(m - 65);
} while (m > 0); } while (m > 0);
} }
return (1); return (1);
@@ -1725,12 +1754,12 @@ static int OJPEGReadHeaderInfoSecStreamDht(TIFF *tif)
} }
if (sp->subsamplingcorrect != 0) if (sp->subsamplingcorrect != 0)
{ {
OJPEGReadSkip(sp, m - 2); OJPEGReadSkip(sp, (uint16_t)(m - 2));
} }
else else
{ {
na = sizeof(uint32_t) + 2 + m; na = (uint32_t)(sizeof(uint32_t) + 2 + m);
nb = _TIFFmallocExt(tif, na); nb = (uint8_t *)_TIFFmallocExt(tif, na);
if (nb == 0) if (nb == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -1739,9 +1768,10 @@ static int OJPEGReadHeaderInfoSecStreamDht(TIFF *tif)
*(uint32_t *)nb = na; *(uint32_t *)nb = na;
nb[sizeof(uint32_t)] = 255; nb[sizeof(uint32_t)] = 255;
nb[sizeof(uint32_t) + 1] = JPEG_MARKER_DHT; nb[sizeof(uint32_t) + 1] = JPEG_MARKER_DHT;
nb[sizeof(uint32_t) + 2] = (m >> 8); nb[sizeof(uint32_t) + 2] = (uint8_t)(m >> 8);
nb[sizeof(uint32_t) + 3] = (m & 255); nb[sizeof(uint32_t) + 3] = (uint8_t)(m & 255);
if (OJPEGReadBlock(sp, m - 2, &nb[sizeof(uint32_t) + 4]) == 0) if (OJPEGReadBlock(sp, (uint16_t)(m - 2), &nb[sizeof(uint32_t) + 4]) ==
0)
{ {
_TIFFfreeExt(tif, nb); _TIFFfreeExt(tif, nb);
return (0); return (0);
@@ -1809,7 +1839,7 @@ static int OJPEGReadHeaderInfoSecStreamSof(TIFF *tif, uint8_t marker_id)
TIFFErrorExtR(tif, module, "Corrupt SOF marker in JPEG data"); TIFFErrorExtR(tif, module, "Corrupt SOF marker in JPEG data");
return (0); return (0);
} }
m -= 8; m = (uint16_t)(m - 8);
if (m % 3 != 0) if (m % 3 != 0)
{ {
if (sp->subsamplingcorrect == 0) if (sp->subsamplingcorrect == 0)
@@ -2030,7 +2060,7 @@ static int OJPEGReadHeaderInfoSecTablesQTable(TIFF *tif)
} }
} }
oa = sizeof(uint32_t) + 69; oa = sizeof(uint32_t) + 69;
ob = _TIFFmallocExt(tif, oa); ob = (uint8_t *)_TIFFmallocExt(tif, oa);
if (ob == 0) if (ob == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2098,8 +2128,8 @@ static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF *tif)
q = 0; q = 0;
for (n = 0; n < 16; n++) for (n = 0; n < 16; n++)
q += o[n]; q += o[n];
ra = sizeof(uint32_t) + 21 + q; ra = (uint32_t)(sizeof(uint32_t) + 21 + q);
rb = _TIFFmallocExt(tif, ra); rb = (uint8_t *)_TIFFmallocExt(tif, ra);
if (rb == 0) if (rb == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2122,7 +2152,7 @@ static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF *tif)
if (sp->dctable[m] != 0) if (sp->dctable[m] != 0)
_TIFFfreeExt(tif, sp->dctable[m]); _TIFFfreeExt(tif, sp->dctable[m]);
sp->dctable[m] = rb; sp->dctable[m] = rb;
sp->sos_tda[m] = (m << 4); sp->sos_tda[m] = (uint8_t)(m << 4);
} }
else else
sp->sos_tda[m] = sp->sos_tda[m - 1]; sp->sos_tda[m] = sp->sos_tda[m - 1];
@@ -2168,8 +2198,8 @@ static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF *tif)
q = 0; q = 0;
for (n = 0; n < 16; n++) for (n = 0; n < 16; n++)
q += o[n]; q += o[n];
ra = sizeof(uint32_t) + 21 + q; ra = (uint32_t)(sizeof(uint32_t) + 21 + q);
rb = _TIFFmallocExt(tif, ra); rb = (uint8_t *)_TIFFmallocExt(tif, ra);
if (rb == 0) if (rb == 0)
{ {
TIFFErrorExtR(tif, module, "Out of memory"); TIFFErrorExtR(tif, module, "Out of memory");
@@ -2220,7 +2250,7 @@ static int OJPEGReadBufferFill(OJPEGState *sp)
if ((uint64_t)m > sp->in_buffer_file_togo) if ((uint64_t)m > sp->in_buffer_file_togo)
m = (uint16_t)sp->in_buffer_file_togo; m = (uint16_t)sp->in_buffer_file_togo;
n = TIFFReadFile(sp->tif, sp->in_buffer, (tmsize_t)m); n = TIFFReadFile(sp->tif, sp->in_buffer, (tmsize_t)m);
if (n == 0) if (n <= 0)
return (0); return (0);
assert(n > 0); assert(n > 0);
assert(n <= OJPEG_BUFFER); assert(n <= OJPEG_BUFFER);
@@ -2286,6 +2316,7 @@ static int OJPEGReadBufferFill(OJPEGState *sp)
sp->in_buffer_next_strile++; sp->in_buffer_next_strile++;
} }
break; break;
case osibsEof:
default: default:
return (0); return (0);
} }
@@ -2331,7 +2362,7 @@ static int OJPEGReadWord(OJPEGState *sp, uint16_t *word)
uint8_t m; uint8_t m;
if (OJPEGReadByte(sp, &m) == 0) if (OJPEGReadByte(sp, &m) == 0)
return (0); return (0);
*word = (m << 8); *word = (uint16_t)(m << 8);
if (OJPEGReadByte(sp, &m) == 0) if (OJPEGReadByte(sp, &m) == 0)
return (0); return (0);
*word |= m; *word |= m;
@@ -2345,7 +2376,7 @@ static int OJPEGReadBlock(OJPEGState *sp, uint16_t len, void *mem)
uint16_t n; uint16_t n;
assert(len > 0); assert(len > 0);
mlen = len; mlen = len;
mmem = mem; mmem = (uint8_t *)mem;
do do
{ {
if (sp->in_buffer_togo == 0) if (sp->in_buffer_togo == 0)
@@ -2359,8 +2390,8 @@ static int OJPEGReadBlock(OJPEGState *sp, uint16_t len, void *mem)
n = sp->in_buffer_togo; n = sp->in_buffer_togo;
_TIFFmemcpy(mmem, sp->in_buffer_cur, n); _TIFFmemcpy(mmem, sp->in_buffer_cur, n);
sp->in_buffer_cur += n; sp->in_buffer_cur += n;
sp->in_buffer_togo -= n; sp->in_buffer_togo = (uint16_t)(sp->in_buffer_togo - n);
mlen -= n; mlen = (uint16_t)(mlen - n);
mmem += n; mmem += n;
} while (mlen > 0); } while (mlen > 0);
return (1); return (1);
@@ -2375,8 +2406,8 @@ static void OJPEGReadSkip(OJPEGState *sp, uint16_t len)
if (n > sp->in_buffer_togo) if (n > sp->in_buffer_togo)
n = sp->in_buffer_togo; n = sp->in_buffer_togo;
sp->in_buffer_cur += n; sp->in_buffer_cur += n;
sp->in_buffer_togo -= n; sp->in_buffer_togo = (uint16_t)(sp->in_buffer_togo - n);
m -= n; m = (uint16_t)(m - n);
if (m > 0) if (m > 0)
{ {
assert(sp->in_buffer_togo == 0); assert(sp->in_buffer_togo == 0);
@@ -2462,6 +2493,8 @@ static int OJPEGWriteStream(TIFF *tif, void **mem, uint32_t *len)
case ososEoi: case ososEoi:
OJPEGWriteStreamEoi(tif, mem, len); OJPEGWriteStreamEoi(tif, mem, len);
break; break;
default:
break;
} }
} while (*len == 0); } while (*len == 0);
return (1); return (1);
@@ -2475,7 +2508,7 @@ static void OJPEGWriteStreamSoi(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[1] = JPEG_MARKER_SOI; sp->out_buffer[1] = JPEG_MARKER_SOI;
*len = 2; *len = 2;
*mem = (void *)sp->out_buffer; *mem = (void *)sp->out_buffer;
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamQTable(TIFF *tif, uint8_t table_index, void **mem, static void OJPEGWriteStreamQTable(TIFF *tif, uint8_t table_index, void **mem,
@@ -2485,9 +2518,10 @@ static void OJPEGWriteStreamQTable(TIFF *tif, uint8_t table_index, void **mem,
if (sp->qtable[table_index] != 0) if (sp->qtable[table_index] != 0)
{ {
*mem = (void *)(sp->qtable[table_index] + sizeof(uint32_t)); *mem = (void *)(sp->qtable[table_index] + sizeof(uint32_t));
*len = *((uint32_t *)sp->qtable[table_index]) - sizeof(uint32_t); *len = (uint32_t)(*((uint32_t *)sp->qtable[table_index]) -
sizeof(uint32_t));
} }
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamDcTable(TIFF *tif, uint8_t table_index, void **mem, static void OJPEGWriteStreamDcTable(TIFF *tif, uint8_t table_index, void **mem,
@@ -2497,9 +2531,10 @@ static void OJPEGWriteStreamDcTable(TIFF *tif, uint8_t table_index, void **mem,
if (sp->dctable[table_index] != 0) if (sp->dctable[table_index] != 0)
{ {
*mem = (void *)(sp->dctable[table_index] + sizeof(uint32_t)); *mem = (void *)(sp->dctable[table_index] + sizeof(uint32_t));
*len = *((uint32_t *)sp->dctable[table_index]) - sizeof(uint32_t); *len = (uint32_t)(*((uint32_t *)sp->dctable[table_index]) -
sizeof(uint32_t));
} }
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamAcTable(TIFF *tif, uint8_t table_index, void **mem, static void OJPEGWriteStreamAcTable(TIFF *tif, uint8_t table_index, void **mem,
@@ -2509,9 +2544,10 @@ static void OJPEGWriteStreamAcTable(TIFF *tif, uint8_t table_index, void **mem,
if (sp->actable[table_index] != 0) if (sp->actable[table_index] != 0)
{ {
*mem = (void *)(sp->actable[table_index] + sizeof(uint32_t)); *mem = (void *)(sp->actable[table_index] + sizeof(uint32_t));
*len = *((uint32_t *)sp->actable[table_index]) - sizeof(uint32_t); *len = (uint32_t)(*((uint32_t *)sp->actable[table_index]) -
sizeof(uint32_t));
} }
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamDri(TIFF *tif, void **mem, uint32_t *len) static void OJPEGWriteStreamDri(TIFF *tif, void **mem, uint32_t *len)
@@ -2524,12 +2560,12 @@ static void OJPEGWriteStreamDri(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[1] = JPEG_MARKER_DRI; sp->out_buffer[1] = JPEG_MARKER_DRI;
sp->out_buffer[2] = 0; sp->out_buffer[2] = 0;
sp->out_buffer[3] = 4; sp->out_buffer[3] = 4;
sp->out_buffer[4] = (sp->restart_interval >> 8); sp->out_buffer[4] = (uint8_t)(sp->restart_interval >> 8);
sp->out_buffer[5] = (sp->restart_interval & 255); sp->out_buffer[5] = (uint8_t)(sp->restart_interval & 255);
*len = 6; *len = 6;
*mem = (void *)sp->out_buffer; *mem = (void *)sp->out_buffer;
} }
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len) static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len)
@@ -2542,15 +2578,15 @@ static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[1] = sp->sof_marker_id; sp->out_buffer[1] = sp->sof_marker_id;
/* Lf */ /* Lf */
sp->out_buffer[2] = 0; sp->out_buffer[2] = 0;
sp->out_buffer[3] = 8 + sp->samples_per_pixel_per_plane * 3; sp->out_buffer[3] = (uint8_t)(8 + sp->samples_per_pixel_per_plane * 3);
/* P */ /* P */
sp->out_buffer[4] = 8; sp->out_buffer[4] = 8;
/* Y */ /* Y */
sp->out_buffer[5] = (uint8_t)(sp->sof_y >> 8); sp->out_buffer[5] = (uint8_t)(sp->sof_y >> 8);
sp->out_buffer[6] = (sp->sof_y & 255); sp->out_buffer[6] = (uint8_t)(sp->sof_y & 255);
/* X */ /* X */
sp->out_buffer[7] = (uint8_t)(sp->sof_x >> 8); sp->out_buffer[7] = (uint8_t)(sp->sof_x >> 8);
sp->out_buffer[8] = (sp->sof_x & 255); sp->out_buffer[8] = (uint8_t)(sp->sof_x & 255);
/* Nf */ /* Nf */
sp->out_buffer[9] = sp->samples_per_pixel_per_plane; sp->out_buffer[9] = sp->samples_per_pixel_per_plane;
for (m = 0; m < sp->samples_per_pixel_per_plane; m++) for (m = 0; m < sp->samples_per_pixel_per_plane; m++)
@@ -2564,9 +2600,9 @@ static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[10 + m * 3 + 2] = sp->out_buffer[10 + m * 3 + 2] =
sp->sof_tq[sp->plane_sample_offset + m]; sp->sof_tq[sp->plane_sample_offset + m];
} }
*len = 10 + sp->samples_per_pixel_per_plane * 3; *len = 10 + (uint32_t)sp->samples_per_pixel_per_plane * 3;
*mem = (void *)sp->out_buffer; *mem = (void *)sp->out_buffer;
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len) static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len)
@@ -2579,7 +2615,7 @@ static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[1] = JPEG_MARKER_SOS; sp->out_buffer[1] = JPEG_MARKER_SOS;
/* Ls */ /* Ls */
sp->out_buffer[2] = 0; sp->out_buffer[2] = 0;
sp->out_buffer[3] = 6 + sp->samples_per_pixel_per_plane * 2; sp->out_buffer[3] = (uint8_t)(6 + sp->samples_per_pixel_per_plane * 2);
/* Ns */ /* Ns */
sp->out_buffer[4] = sp->samples_per_pixel_per_plane; sp->out_buffer[4] = sp->samples_per_pixel_per_plane;
for (m = 0; m < sp->samples_per_pixel_per_plane; m++) for (m = 0; m < sp->samples_per_pixel_per_plane; m++)
@@ -2596,9 +2632,9 @@ static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len)
sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 1] = 63; sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 1] = 63;
/* Ah and Al */ /* Ah and Al */
sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 2] = 0; sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 2] = 0;
*len = 8 + sp->samples_per_pixel_per_plane * 2; *len = 8 + (uint32_t)sp->samples_per_pixel_per_plane * 2;
*mem = (void *)sp->out_buffer; *mem = (void *)sp->out_buffer;
sp->out_state++; sp->out_state = (OJPEGStateOutState)(sp->out_state + 1);
} }
static int OJPEGWriteStreamCompressed(TIFF *tif, void **mem, uint32_t *len) static int OJPEGWriteStreamCompressed(TIFF *tif, void **mem, uint32_t *len)
@@ -2626,6 +2662,8 @@ static int OJPEGWriteStreamCompressed(TIFF *tif, void **mem, uint32_t *len)
case osibsEof: case osibsEof:
sp->out_state = ososEoi; sp->out_state = ososEoi;
break; break;
case osibsNotSetYet:
case osibsJpegInterchangeFormat:
default: default:
break; break;
} }
@@ -2638,7 +2676,7 @@ static void OJPEGWriteStreamRst(TIFF *tif, void **mem, uint32_t *len)
OJPEGState *sp = (OJPEGState *)tif->tif_data; OJPEGState *sp = (OJPEGState *)tif->tif_data;
assert(OJPEG_BUFFER >= 2); assert(OJPEG_BUFFER >= 2);
sp->out_buffer[0] = 255; sp->out_buffer[0] = 255;
sp->out_buffer[1] = JPEG_MARKER_RST0 + sp->restart_index; sp->out_buffer[1] = (uint8_t)(JPEG_MARKER_RST0 + sp->restart_index);
sp->restart_index++; sp->restart_index++;
if (sp->restart_index == 8) if (sp->restart_index == 8)
sp->restart_index = 0; sp->restart_index = 0;
@@ -2659,7 +2697,7 @@ static void OJPEGWriteStreamEoi(TIFF *tif, void **mem, uint32_t *len)
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
static int jpeg_create_decompress_encap(OJPEGState *sp, static int jpeg_create_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo) tiff_ojpeg_decompress_struct *cinfo)
{ {
if (SETJMP(sp->exit_jmpbuf)) if (SETJMP(sp->exit_jmpbuf))
return 0; return 0;
@@ -2672,7 +2710,8 @@ static int jpeg_create_decompress_encap(OJPEGState *sp,
#endif #endif
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
static int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo, static int jpeg_read_header_encap(OJPEGState *sp,
tiff_ojpeg_decompress_struct *cinfo,
uint8_t require_image) uint8_t require_image)
{ {
if (SETJMP(sp->exit_jmpbuf)) if (SETJMP(sp->exit_jmpbuf))
@@ -2687,7 +2726,7 @@ static int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo,
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
static int jpeg_start_decompress_encap(OJPEGState *sp, static int jpeg_start_decompress_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo) tiff_ojpeg_decompress_struct *cinfo)
{ {
if (SETJMP(sp->exit_jmpbuf)) if (SETJMP(sp->exit_jmpbuf))
return 0; return 0;
@@ -2701,14 +2740,14 @@ static int jpeg_start_decompress_encap(OJPEGState *sp,
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
static int jpeg_read_scanlines_encap(OJPEGState *sp, static int jpeg_read_scanlines_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, tiff_ojpeg_decompress_struct *cinfo,
void *scanlines, uint32_t max_lines) void *scanlines, uint32_t max_lines)
{ {
if (SETJMP(sp->exit_jmpbuf)) if (SETJMP(sp->exit_jmpbuf))
return 0; return 0;
else else
{ {
jpeg_read_scanlines(cinfo, scanlines, max_lines); jpeg_read_scanlines(cinfo, (JSAMPARRAY)scanlines, max_lines);
return 1; return 1;
} }
} }
@@ -2716,14 +2755,14 @@ static int jpeg_read_scanlines_encap(OJPEGState *sp,
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
static int jpeg_read_raw_data_encap(OJPEGState *sp, static int jpeg_read_raw_data_encap(OJPEGState *sp,
jpeg_decompress_struct *cinfo, void *data, tiff_ojpeg_decompress_struct *cinfo,
uint32_t max_lines) void *data, uint32_t max_lines)
{ {
if (SETJMP(sp->exit_jmpbuf)) if (SETJMP(sp->exit_jmpbuf))
return 0; return 0;
else else
{ {
jpeg_read_raw_data(cinfo, data, max_lines); jpeg_read_raw_data(cinfo, (JSAMPIMAGE)data, max_lines);
return 1; return 1;
} }
} }
@@ -2737,14 +2776,15 @@ static void jpeg_encap_unwind(TIFF *tif)
} }
#endif #endif
static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct *cinfo) static void
OJPEGLibjpegJpegErrorMgrOutputMessage(tiff_ojpeg_common_struct *cinfo)
{ {
char buffer[JMSG_LENGTH_MAX]; char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo, buffer); (*cinfo->err->format_message)(cinfo, buffer);
TIFFWarningExtR(((TIFF *)(cinfo->client_data)), "LibJpeg", "%s", buffer); TIFFWarningExtR(((TIFF *)(cinfo->client_data)), "LibJpeg", "%s", buffer);
} }
static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct *cinfo) static void OJPEGLibjpegJpegErrorMgrErrorExit(tiff_ojpeg_common_struct *cinfo)
{ {
char buffer[JMSG_LENGTH_MAX]; char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo, buffer); (*cinfo->err->format_message)(cinfo, buffer);
@@ -2752,13 +2792,14 @@ static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct *cinfo)
jpeg_encap_unwind((TIFF *)(cinfo->client_data)); jpeg_encap_unwind((TIFF *)(cinfo->client_data));
} }
static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct *cinfo) static void
OJPEGLibjpegJpegSourceMgrInitSource(tiff_ojpeg_decompress_struct *cinfo)
{ {
(void)cinfo; (void)cinfo;
} }
static boolean static boolean
OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct *cinfo) OJPEGLibjpegJpegSourceMgrFillInputBuffer(tiff_ojpeg_decompress_struct *cinfo)
{ {
TIFF *tif = (TIFF *)cinfo->client_data; TIFF *tif = (TIFF *)cinfo->client_data;
OJPEGState *sp = (OJPEGState *)tif->tif_data; OJPEGState *sp = (OJPEGState *)tif->tif_data;
@@ -2770,12 +2811,12 @@ OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct *cinfo)
jpeg_encap_unwind(tif); jpeg_encap_unwind(tif);
} }
sp->libjpeg_jpeg_source_mgr.bytes_in_buffer = len; sp->libjpeg_jpeg_source_mgr.bytes_in_buffer = len;
sp->libjpeg_jpeg_source_mgr.next_input_byte = mem; sp->libjpeg_jpeg_source_mgr.next_input_byte = (const JOCTET *)mem;
return (1); return (1);
} }
static void static void
OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct *cinfo, OJPEGLibjpegJpegSourceMgrSkipInputData(tiff_ojpeg_decompress_struct *cinfo,
long num_bytes) long num_bytes)
{ {
TIFF *tif = (TIFF *)cinfo->client_data; TIFF *tif = (TIFF *)cinfo->client_data;
@@ -2789,7 +2830,7 @@ OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct *cinfo,
#pragma warning(disable : 4702) /* unreachable code */ #pragma warning(disable : 4702) /* unreachable code */
#endif #endif
static boolean static boolean
OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct *cinfo, OJPEGLibjpegJpegSourceMgrResyncToRestart(tiff_ojpeg_decompress_struct *cinfo,
int desired) int desired)
{ {
TIFF *tif = (TIFF *)cinfo->client_data; TIFF *tif = (TIFF *)cinfo->client_data;
@@ -2802,7 +2843,8 @@ OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct *cinfo,
#pragma warning(pop) #pragma warning(pop)
#endif #endif
static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct *cinfo) static void
OJPEGLibjpegJpegSourceMgrTermSource(tiff_ojpeg_decompress_struct *cinfo)
{ {
(void)cinfo; (void)cinfo;
} }

View File

@@ -77,7 +77,7 @@ int _TIFFgetMode(TIFFOpenOptions *opts, thandle_t clientdata, const char *mode,
return (m); return (m);
} }
TIFFOpenOptions *TIFFOpenOptionsAlloc() TIFFOpenOptions *TIFFOpenOptionsAlloc(void)
{ {
TIFFOpenOptions *opts = TIFFOpenOptions *opts =
(TIFFOpenOptions *)_TIFFcalloc(1, sizeof(TIFFOpenOptions)); (TIFFOpenOptions *)_TIFFcalloc(1, sizeof(TIFFOpenOptions));
@@ -308,6 +308,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
TIFF *tif; TIFF *tif;
int m; int m;
const char *cp; const char *cp;
tmsize_t size_to_alloc;
/* The following are configuration checks. They should be redundant, but /* The following are configuration checks. They should be redundant, but
* should not compile to any actual code in an optimised release build * should not compile to any actual code in an optimised release build
@@ -330,7 +331,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
n.a8[0] = 1; n.a8[0] = 1;
n.a8[1] = 0; n.a8[1] = 0;
(void)n; (void)n;
#ifdef WORDS_BIGENDIAN #if WORDS_BIGENDIAN
assert(n.a16 == 256); assert(n.a16 == 256);
#else #else
assert(n.a16 == 1); assert(n.a16 == 1);
@@ -340,7 +341,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
m = _TIFFgetMode(opts, clientdata, mode, module); m = _TIFFgetMode(opts, clientdata, mode, module);
if (m == -1) if (m == -1)
goto bad2; goto bad2;
tmsize_t size_to_alloc = (tmsize_t)(sizeof(TIFF) + strlen(name) + 1); size_to_alloc = (tmsize_t)(sizeof(TIFF) + strlen(name) + 1);
if (opts && opts->max_single_mem_alloc > 0 && if (opts && opts->max_single_mem_alloc > 0 &&
size_to_alloc > opts->max_single_mem_alloc) size_to_alloc > opts->max_single_mem_alloc)
{ {
@@ -377,8 +378,6 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */
tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER; tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
tif->tif_curoff = 0; tif->tif_curoff = 0;
tif->tif_curstrip = (uint32_t)-1; /* invalid strip */
tif->tif_row = (uint32_t)-1; /* read/write pre-increment */
tif->tif_clientdata = clientdata; tif->tif_clientdata = clientdata;
tif->tif_readproc = readproc; tif->tif_readproc = readproc;
tif->tif_writeproc = writeproc; tif->tif_writeproc = writeproc;
@@ -398,6 +397,10 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_warn_about_unknown_tags = opts->warn_about_unknown_tags; tif->tif_warn_about_unknown_tags = opts->warn_about_unknown_tags;
} }
/* Reset tif->tif_dir structure to zero and
* initialize some IFD strile counter and index parameters. */
_TIFFResetTifDirAndInitStrileCounters(&tif->tif_dir);
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -480,13 +483,13 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
switch (*cp) switch (*cp)
{ {
case 'b': case 'b':
#ifndef WORDS_BIGENDIAN #if !WORDS_BIGENDIAN
if (m & O_CREAT) if (m & O_CREAT)
tif->tif_flags |= TIFF_SWAB; tif->tif_flags |= TIFF_SWAB;
#endif #endif
break; break;
case 'l': case 'l':
#ifdef WORDS_BIGENDIAN #if WORDS_BIGENDIAN
if ((m & O_CREAT)) if ((m & O_CREAT))
tif->tif_flags |= TIFF_SWAB; tif->tif_flags |= TIFF_SWAB;
#endif #endif
@@ -536,7 +539,9 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
case 'O': case 'O':
if (m == O_RDONLY) if (m == O_RDONLY)
tif->tif_flags |= tif->tif_flags |=
(TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD); (TIFF_LAZYSTRILELOAD_ASKED | TIFF_DEFERSTRILELOAD);
break;
default:
break; break;
} }
@@ -561,7 +566,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
/* /*
* Setup header and write. * Setup header and write.
*/ */
#ifdef WORDS_BIGENDIAN #if WORDS_BIGENDIAN
tif->tif_header.common.tiff_magic = tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
#else #else
@@ -654,13 +659,13 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
} }
if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN)
{ {
#ifndef WORDS_BIGENDIAN #if !WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB; tif->tif_flags |= TIFF_SWAB;
#endif #endif
} }
else else
{ {
#ifdef WORDS_BIGENDIAN #if WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB; tif->tif_flags |= TIFF_SWAB;
#endif #endif
} }
@@ -780,6 +785,8 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
if (!TIFFDefaultDirectory(tif)) if (!TIFFDefaultDirectory(tif))
goto bad; goto bad;
return (tif); return (tif);
default:
break;
} }
bad: bad:
tif->tif_mode = O_RDONLY; /* XXX avoid flush */ tif->tif_mode = O_RDONLY; /* XXX avoid flush */
@@ -861,7 +868,7 @@ int TIFFIsTiled(TIFF *tif) { return (isTiled(tif)); }
/* /*
* Return current row being read/written. * Return current row being read/written.
*/ */
uint32_t TIFFCurrentRow(TIFF *tif) { return (tif->tif_row); } uint32_t TIFFCurrentRow(TIFF *tif) { return (tif->tif_dir.td_row); }
/* /*
* Return index of the current directory. * Return index of the current directory.
@@ -871,12 +878,12 @@ tdir_t TIFFCurrentDirectory(TIFF *tif) { return (tif->tif_curdir); }
/* /*
* Return current strip. * Return current strip.
*/ */
uint32_t TIFFCurrentStrip(TIFF *tif) { return (tif->tif_curstrip); } uint32_t TIFFCurrentStrip(TIFF *tif) { return (tif->tif_dir.td_curstrip); }
/* /*
* Return current tile. * Return current tile.
*/ */
uint32_t TIFFCurrentTile(TIFF *tif) { return (tif->tif_curtile); } uint32_t TIFFCurrentTile(TIFF *tif) { return (tif->tif_dir.td_curtile); }
/* /*
* Return nonzero if the file has byte-swapped data. * Return nonzero if the file has byte-swapped data.

View File

@@ -194,12 +194,17 @@ static int PackBitsEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
*/ */
if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126) if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126)
{ {
state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL); state =
(((*lastliteral) = (uint8_t)(*lastliteral + 2)) == 127
? BASE
: LITERAL);
op[-2] = op[-1]; /* replicate */ op[-2] = op[-1]; /* replicate */
} }
else else
state = RUN; state = RUN;
goto again; goto again;
default:
break;
} }
} }
tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
@@ -306,12 +311,22 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{ {
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32, TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
return (0); return (0);
} }
return (1); return (1);
} }
static uint64_t PackBitsGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
return 64;
}
int TIFFInitPackBits(TIFF *tif, int scheme) int TIFFInitPackBits(TIFF *tif, int scheme)
{ {
(void)scheme; (void)scheme;
@@ -325,6 +340,8 @@ int TIFFInitPackBits(TIFF *tif, int scheme)
tif->tif_encodestrip = PackBitsEncodeChunk; tif->tif_encodestrip = PackBitsEncodeChunk;
tif->tif_encodetile = PackBitsEncodeChunk; tif->tif_encodetile = PackBitsEncodeChunk;
#endif #endif
tif->tif_getmaxcompressionratio = PackBitsGetMaxCompressionRatio;
return (1); return (1);
} }
#endif /* PACKBITS_SUPPORT */ #endif /* PACKBITS_SUPPORT */

View File

@@ -117,11 +117,11 @@ static float LogK1, LogK2;
} while (i > 0); \ } while (i > 0); \
} }
static void horizontalAccumulateF(uint16_t *wp, int n, int stride, float *op, static void horizontalAccumulateF(uint16_t *wp, tmsize_t n, int stride,
float *ToLinearF) float *op, float *ToLinearF)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
register float t0, t1, t2, t3; float t0, t1, t2, t3;
if (n >= stride) if (n >= stride)
{ {
@@ -180,22 +180,22 @@ static void horizontalAccumulateF(uint16_t *wp, int n, int stride, float *op,
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; *op = ToLinearF[*wp & mask]; REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
wp++; op++) *op = ToLinearF[*wp & mask]; wp++; op++)
n -= stride; n -= stride;
} }
} }
} }
} }
static void horizontalAccumulate12(uint16_t *wp, int n, int stride, int16_t *op, static void horizontalAccumulate12(uint16_t *wp, tmsize_t n, int stride,
float *ToLinearF) int16_t *op, float *ToLinearF)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
register float t0, t1, t2, t3; float t0, t1, t2, t3;
#define SCALE12 2048.0F #define SCALE12 2048.0f
#define CLAMP12(t) (((t) < 3071) ? (uint16_t)(t) : 3071) #define CLAMP12(t) (((t) < 3071) ? (int16_t)(uint16_t)(t) : (int16_t)3071)
if (n >= stride) if (n >= stride)
{ {
@@ -255,19 +255,19 @@ static void horizontalAccumulate12(uint16_t *wp, int n, int stride, int16_t *op,
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
t0 = ToLinearF[wp[stride] & mask] * SCALE12; t0 = ToLinearF[*wp & mask] * SCALE12; *op = CLAMP12(t0);
*op = CLAMP12(t0); wp++; op++) wp++; op++)
n -= stride; n -= stride;
} }
} }
} }
} }
static void horizontalAccumulate16(uint16_t *wp, int n, int stride, static void horizontalAccumulate16(uint16_t *wp, tmsize_t n, int stride,
uint16_t *op, uint16_t *ToLinear16) uint16_t *op, uint16_t *ToLinear16)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
if (n >= stride) if (n >= stride)
{ {
@@ -312,8 +312,8 @@ static void horizontalAccumulate16(uint16_t *wp, int n, int stride,
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; *op = ToLinear16[*wp & mask]; REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
wp++; op++) *op = ToLinear16[*wp & mask]; wp++; op++)
n -= stride; n -= stride;
} }
} }
@@ -324,10 +324,10 @@ static void horizontalAccumulate16(uint16_t *wp, int n, int stride,
* Returns the log encoded 11-bit values with the horizontal * Returns the log encoded 11-bit values with the horizontal
* differencing undone. * differencing undone.
*/ */
static void horizontalAccumulate11(uint16_t *wp, int n, int stride, static void horizontalAccumulate11(uint16_t *wp, tmsize_t n, int stride,
uint16_t *op) uint16_t *op)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
if (n >= stride) if (n >= stride)
{ {
@@ -375,21 +375,22 @@ static void horizontalAccumulate11(uint16_t *wp, int n, int stride,
} }
else else
{ {
REPEAT(stride, *op = *wp & mask; wp++; op++) REPEAT(stride, *op = (uint16_t)(*wp & mask); wp++; op++)
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; *op = *wp & mask; wp++; op++) REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
*op = (uint16_t)(*wp & mask); wp++; op++)
n -= stride; n -= stride;
} }
} }
} }
} }
static void horizontalAccumulate8(uint16_t *wp, int n, int stride, static void horizontalAccumulate8(uint16_t *wp, tmsize_t n, int stride,
unsigned char *op, unsigned char *ToLinear8) unsigned char *op, unsigned char *ToLinear8)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
if (n >= stride) if (n >= stride)
{ {
@@ -434,20 +435,20 @@ static void horizontalAccumulate8(uint16_t *wp, int n, int stride,
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask]; REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
wp++; op++) *op = ToLinear8[*wp & mask]; wp++; op++)
n -= stride; n -= stride;
} }
} }
} }
} }
static void horizontalAccumulate8abgr(uint16_t *wp, int n, int stride, static void horizontalAccumulate8abgr(uint16_t *wp, tmsize_t n, int stride,
unsigned char *op, unsigned char *op,
unsigned char *ToLinear8) unsigned char *ToLinear8)
{ {
register unsigned int cr, cg, cb, ca, mask; unsigned int cr, cg, cb, ca, mask;
register unsigned char t0, t1, t2, t3; unsigned char t0, t1, t2, t3;
if (n >= stride) if (n >= stride)
{ {
@@ -508,8 +509,8 @@ static void horizontalAccumulate8abgr(uint16_t *wp, int n, int stride,
n -= stride; n -= stride;
while (n > 0) while (n > 0)
{ {
REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask]; REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
wp++; op++) *op = ToLinear8[*wp & mask]; wp++; op++)
n -= stride; n -= stride;
} }
} }
@@ -577,7 +578,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
LogK1 = (float)(1. / c); /* if (v >= 2) token = k1*log(v*k2) */ LogK1 = (float)(1. / c); /* if (v >= 2) token = k1*log(v*k2) */
LogK2 = (float)(1. / b); LogK2 = (float)(1. / b);
lt2size = (int)(2. / linstep) + 1; lt2size = (int)(2. / linstep) + 1;
FromLT2 = (uint16_t *)_TIFFmallocExt(tif, lt2size * sizeof(uint16_t)); FromLT2 = (uint16_t *)_TIFFmallocExt(
tif, (tmsize_t)((size_t)lt2size * sizeof(uint16_t)));
From14 = (uint16_t *)_TIFFmallocExt(tif, 16384 * sizeof(uint16_t)); From14 = (uint16_t *)_TIFFmallocExt(tif, 16384 * sizeof(uint16_t));
From8 = (uint16_t *)_TIFFmallocExt(tif, 256 * sizeof(uint16_t)); From8 = (uint16_t *)_TIFFmallocExt(tif, 256 * sizeof(uint16_t));
ToLinearF = (float *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(float)); ToLinearF = (float *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(float));
@@ -623,16 +625,17 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
for (i = 0; i < TSIZEP1; i++) for (i = 0; i < TSIZEP1; i++)
{ {
v = ToLinearF[i] * 65535.0 + 0.5; v = (double)ToLinearF[i] * 65535.0 + 0.5;
ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v; ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v;
v = ToLinearF[i] * 255.0 + 0.5; v = (double)ToLinearF[i] * 255.0 + 0.5;
ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v; ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v;
} }
j = 0; j = 0;
for (i = 0; i < lt2size; i++) for (i = 0; i < lt2size; i++)
{ {
if ((i * linstep) * (i * linstep) > ToLinearF[j] * ToLinearF[j + 1]) if ((i * linstep) * (i * linstep) >
(double)ToLinearF[j] * (double)ToLinearF[j + 1])
j++; j++;
FromLT2[i] = (uint16_t)j; FromLT2[i] = (uint16_t)j;
} }
@@ -645,7 +648,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
j = 0; j = 0;
for (i = 0; i < 16384; i++) for (i = 0; i < 16384; i++)
{ {
while ((i / 16383.) * (i / 16383.) > ToLinearF[j] * ToLinearF[j + 1]) while ((i / 16383.) * (i / 16383.) >
(double)ToLinearF[j] * (double)ToLinearF[j + 1])
j++; j++;
From14[i] = (uint16_t)j; From14[i] = (uint16_t)j;
} }
@@ -653,7 +657,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
j = 0; j = 0;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
while ((i / 255.) * (i / 255.) > ToLinearF[j] * ToLinearF[j + 1]) while ((i / 255.) * (i / 255.) >
(double)ToLinearF[j] * (double)ToLinearF[j + 1])
j++; j++;
From8[i] = (uint16_t)j; From8[i] = (uint16_t)j;
} }
@@ -708,6 +713,8 @@ static int PixarLogGuessDataFmt(TIFFDirectory *td)
if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
guess = PIXARLOGDATAFMT_8BIT; guess = PIXARLOGDATAFMT_8BIT;
break; break;
default:
break;
} }
return guess; return guess;
@@ -769,7 +776,8 @@ static int PixarLogSetupDecode(TIFF *tif)
multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), strip_height), multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), strip_height),
sizeof(uint16_t)); sizeof(uint16_t));
/* add one more stride in case input ends mid-stride */ /* add one more stride in case input ends mid-stride */
tbuf_size = add_ms(tbuf_size, sizeof(uint16_t) * sp->stride); tbuf_size =
add_ms(tbuf_size, (tmsize_t)(sizeof(uint16_t) * (size_t)sp->stride));
if (tbuf_size == 0) if (tbuf_size == 0)
return (0); /* TODO: this is an error return without error report return (0); /* TODO: this is an error return without error report
through TIFFErrorExt */ through TIFFErrorExt */
@@ -838,18 +846,21 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
PixarLogState *sp = PixarLogDecoderState(tif); PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t i; tmsize_t i;
tmsize_t nsamples; tmsize_t nsamples;
int llen; tmsize_t llen;
uint16_t *up; uint16_t *up;
switch (sp->user_datafmt) switch (sp->user_datafmt)
{ {
case PIXARLOGDATAFMT_FLOAT: case PIXARLOGDATAFMT_FLOAT:
nsamples = occ / sizeof(float); /* XXX float == 32 bits */ nsamples = (tmsize_t)((uint64_t)occ /
sizeof(float)); /* XXX float == 32 bits */
break; break;
case PIXARLOGDATAFMT_16BIT: case PIXARLOGDATAFMT_16BIT:
case PIXARLOGDATAFMT_12BITPICIO: case PIXARLOGDATAFMT_12BITPICIO:
case PIXARLOGDATAFMT_11BITLOG: case PIXARLOGDATAFMT_11BITLOG:
nsamples = occ / sizeof(uint16_t); /* XXX uint16_t == 16 bits */ nsamples =
(tmsize_t)((uint64_t)occ /
sizeof(uint16_t)); /* XXX uint16_t == 16 bits */
break; break;
case PIXARLOGDATAFMT_8BIT: case PIXARLOGDATAFMT_8BIT:
case PIXARLOGDATAFMT_8BITABGR: case PIXARLOGDATAFMT_8BITABGR:
@@ -863,7 +874,55 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
return 0; return 0;
} }
llen = sp->stride * td->td_imagewidth; llen = (tmsize_t)sp->stride * td->td_imagewidth;
/* Fix: ABGR with stride=3 expands 3 samples to 4 output bytes per pixel */
if (sp->user_datafmt == PIXARLOGDATAFMT_8BITABGR && sp->stride == 3)
{
tmsize_t required = (tmsize_t)td->td_imagewidth * 4;
tmsize_t max_rows;
tmsize_t max_nsamples;
/*
* Ensure at least one expanded output row fits.
*/
if (occ < required)
{
TIFFErrorExtR(tif, module,
"Output buffer too small for PixarLog ABGR data");
memset(op, 0, (size_t)occ);
return (0);
}
/*
* The caller-provided output buffer size must represent a whole
* number of expanded ABGR scanlines.
*/
if (occ % required)
{
TIFFErrorExtR(
tif, module,
"Fractional scanline not supported for PixarLog ABGR data");
memset(op, 0, (size_t)occ);
return (0);
}
/*
* PixarLogDecode() may process multiple rows per call
* (e.g. strip decoding). Limit nsamples so the total
* output written by the loop below never exceeds occ.
*/
max_rows = occ / required;
max_nsamples = max_rows * llen;
if (nsamples > max_nsamples)
{
TIFFErrorExtR(tif, module,
"Output buffer too small for PixarLog ABGR data");
memset(op, 0, (size_t)occ);
return (0);
}
}
(void)s; (void)s;
assert(sp != NULL); assert(sp != NULL);
@@ -876,8 +935,8 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_out = (uInt)(nsamples * sizeof(uint16_t)); sp->stream.avail_out = (uInt)((unsigned long)nsamples * sizeof(uint16_t));
if (sp->stream.avail_out != nsamples * sizeof(uint16_t)) if (sp->stream.avail_out != (unsigned long)nsamples * sizeof(uint16_t))
{ {
TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size"); TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
@@ -899,9 +958,10 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} }
if (state == Z_DATA_ERROR) if (state == Z_DATA_ERROR)
{ {
TIFFErrorExtR( TIFFErrorExtR(tif, module,
tif, module, "Decoding error at scanline %" PRIu32 ", %s", "Decoding error at scanline %" PRIu32 ", %s",
tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); tif->tif_dir.td_row,
sp->stream.msg ? sp->stream.msg : "(null)");
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
return (0); return (0);
} }
@@ -920,7 +980,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 "Not enough data at scanline %" PRIu32
" (short %u bytes)", " (short %u bytes)",
tif->tif_row, sp->stream.avail_out); tif->tif_dir.td_row, sp->stream.avail_out);
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
return (0); return (0);
} }
@@ -941,7 +1001,8 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (nsamples % llen) if (nsamples % llen)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"stride %d is not a multiple of sample count, " "stride %" TIFF_SSIZE_FORMAT
" is not a multiple of sample count, "
"%" TIFF_SSIZE_FORMAT ", data truncated.", "%" TIFF_SSIZE_FORMAT ", data truncated.",
llen, nsamples); llen, nsamples);
nsamples -= nsamples % llen; nsamples -= nsamples % llen;
@@ -954,31 +1015,37 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
case PIXARLOGDATAFMT_FLOAT: case PIXARLOGDATAFMT_FLOAT:
horizontalAccumulateF(up, llen, sp->stride, (float *)op, horizontalAccumulateF(up, llen, sp->stride, (float *)op,
sp->ToLinearF); sp->ToLinearF);
op += llen * sizeof(float); op += (unsigned long)llen * sizeof(float);
break; break;
case PIXARLOGDATAFMT_16BIT: case PIXARLOGDATAFMT_16BIT:
horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op, horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op,
sp->ToLinear16); sp->ToLinear16);
op += llen * sizeof(uint16_t); op += (unsigned long)llen * sizeof(uint16_t);
break; break;
case PIXARLOGDATAFMT_12BITPICIO: case PIXARLOGDATAFMT_12BITPICIO:
horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op, horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op,
sp->ToLinearF); sp->ToLinearF);
op += llen * sizeof(int16_t); op += (unsigned long)llen * sizeof(int16_t);
break; break;
case PIXARLOGDATAFMT_11BITLOG: case PIXARLOGDATAFMT_11BITLOG:
horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op); horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op);
op += llen * sizeof(uint16_t); op += (unsigned long)llen * sizeof(uint16_t);
break; break;
case PIXARLOGDATAFMT_8BIT: case PIXARLOGDATAFMT_8BIT:
horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op, horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op,
sp->ToLinear8); sp->ToLinear8);
op += llen * sizeof(unsigned char); op += (unsigned long)llen * sizeof(unsigned char);
break; break;
case PIXARLOGDATAFMT_8BITABGR: case PIXARLOGDATAFMT_8BITABGR:
horizontalAccumulate8abgr(up, llen, sp->stride, horizontalAccumulate8abgr(up, llen, sp->stride,
(unsigned char *)op, sp->ToLinear8); (unsigned char *)op, sp->ToLinear8);
op += llen * sizeof(unsigned char);
/* For stride == 3 (RGB), horizontalAccumulate8abgr expands to 4
* bytes/pixel (ABGR) */
if (sp->stride == 3)
op += (unsigned long)td->td_imagewidth * 4;
else
op += (unsigned long)llen * sizeof(unsigned char);
break; break;
default: default:
TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16, TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
@@ -1063,17 +1130,18 @@ static int PixarLogPreEncode(TIFF *tif, uint16_t s)
return (deflateReset(&sp->stream) == Z_OK); return (deflateReset(&sp->stream) == Z_OK);
} }
static void horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp, static void horizontalDifferenceF(float *ip, tmsize_t n, int stride,
uint16_t *FromLT2) uint16_t *wp, uint16_t *FromLT2)
{ {
int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask; int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
float fltsize = Fltsize; float fltsize = Fltsize;
#define CLAMP(v) \ #define CLAMP(v) \
((v < (float)0.) ? 0 \ ((v < (float)0.) ? 0 \
: (v < (float)2.) ? FromLT2[(int)(v * fltsize)] \ : (v < (float)2.) ? FromLT2[(int)(v * fltsize)] \
: (v > (float)24.2) ? 2047 \ : (v > (float)24.2) \
: LogK1 * log(v * LogK2) + 0.5) ? 2047 \
: (double)LogK1 * log((double)v * (double)LogK2) + 0.5)
mask = CODE_MASK; mask = CODE_MASK;
if (n >= stride) if (n >= stride)
@@ -1143,10 +1211,10 @@ static void horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp,
} }
} }
static void horizontalDifference16(unsigned short *ip, int n, int stride, static void horizontalDifference16(unsigned short *ip, tmsize_t n, int stride,
unsigned short *wp, uint16_t *From14) unsigned short *wp, uint16_t *From14)
{ {
register int r1, g1, b1, a1, r2, g2, b2, a2, mask; int r1, g1, b1, a1, r2, g2, b2, a2, mask;
/* assumption is unsigned pixel values */ /* assumption is unsigned pixel values */
#undef CLAMP #undef CLAMP
@@ -1219,10 +1287,10 @@ static void horizontalDifference16(unsigned short *ip, int n, int stride,
} }
} }
static void horizontalDifference8(unsigned char *ip, int n, int stride, static void horizontalDifference8(unsigned char *ip, tmsize_t n, int stride,
unsigned short *wp, uint16_t *From8) unsigned short *wp, uint16_t *From8)
{ {
register int r1, g1, b1, a1, r2, g2, b2, a2, mask; int r1, g1, b1, a1, r2, g2, b2, a2, mask;
#undef CLAMP #undef CLAMP
#define CLAMP(v) (From8[(v)]) #define CLAMP(v) (From8[(v)])
@@ -1304,7 +1372,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
PixarLogState *sp = PixarLogEncoderState(tif); PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t i; tmsize_t i;
tmsize_t n; tmsize_t n;
int llen; tmsize_t llen;
unsigned short *up; unsigned short *up;
(void)s; (void)s;
@@ -1312,12 +1380,14 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
switch (sp->user_datafmt) switch (sp->user_datafmt)
{ {
case PIXARLOGDATAFMT_FLOAT: case PIXARLOGDATAFMT_FLOAT:
n = cc / sizeof(float); /* XXX float == 32 bits */ n = (tmsize_t)((unsigned long)cc /
sizeof(float)); /* XXX float == 32 bits */
break; break;
case PIXARLOGDATAFMT_16BIT: case PIXARLOGDATAFMT_16BIT:
case PIXARLOGDATAFMT_12BITPICIO: case PIXARLOGDATAFMT_12BITPICIO:
case PIXARLOGDATAFMT_11BITLOG: case PIXARLOGDATAFMT_11BITLOG:
n = cc / sizeof(uint16_t); /* XXX uint16_t == 16 bits */ n = (tmsize_t)((unsigned long)cc /
sizeof(uint16_t)); /* XXX uint16_t == 16 bits */
break; break;
case PIXARLOGDATAFMT_8BIT: case PIXARLOGDATAFMT_8BIT:
case PIXARLOGDATAFMT_8BITABGR: case PIXARLOGDATAFMT_8BITABGR:
@@ -1330,7 +1400,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
return 0; return 0;
} }
llen = sp->stride * td->td_imagewidth; llen = (tmsize_t)sp->stride * td->td_imagewidth;
/* Check against the number of elements (of size uint16_t) of sp->tbuf */ /* Check against the number of elements (of size uint16_t) of sp->tbuf */
if (n > ((tmsize_t)td->td_rowsperstrip * llen)) if (n > ((tmsize_t)td->td_rowsperstrip * llen))
{ {
@@ -1345,17 +1415,17 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
case PIXARLOGDATAFMT_FLOAT: case PIXARLOGDATAFMT_FLOAT:
horizontalDifferenceF((float *)bp, llen, sp->stride, up, horizontalDifferenceF((float *)bp, llen, sp->stride, up,
sp->FromLT2); sp->FromLT2);
bp += llen * sizeof(float); bp += (unsigned long)llen * sizeof(float);
break; break;
case PIXARLOGDATAFMT_16BIT: case PIXARLOGDATAFMT_16BIT:
horizontalDifference16((uint16_t *)bp, llen, sp->stride, up, horizontalDifference16((uint16_t *)bp, llen, sp->stride, up,
sp->From14); sp->From14);
bp += llen * sizeof(uint16_t); bp += (unsigned long)llen * sizeof(uint16_t);
break; break;
case PIXARLOGDATAFMT_8BIT: case PIXARLOGDATAFMT_8BIT:
horizontalDifference8((unsigned char *)bp, llen, sp->stride, up, horizontalDifference8((unsigned char *)bp, llen, sp->stride, up,
sp->From8); sp->From8);
bp += llen * sizeof(unsigned char); bp += (unsigned long)llen * sizeof(unsigned char);
break; break;
default: default:
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -1370,8 +1440,8 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = (uInt)(n * sizeof(uint16_t)); sp->stream.avail_in = (uInt)((unsigned long)n * sizeof(uint16_t));
if ((sp->stream.avail_in / sizeof(uint16_t)) != (uInt)n) if ((sp->stream.avail_in / sizeof(uint16_t)) != (unsigned long)n)
{ {
TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size"); TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
return (0); return (0);
@@ -1562,13 +1632,15 @@ static int PixarLogVSetField(TIFF *tif, uint32_t tag, va_list ap)
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,
SAMPLEFORMAT_IEEEFP); SAMPLEFORMAT_IEEEFP);
break; break;
default:
break;
} }
/* /*
* Must recalculate sizes should bits/sample change. * Must recalculate sizes should bits/sample change.
*/ */
tif->tif_tilesize = tif->tif_dir.td_tilesize =
isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
result = 1; /* NB: pseudo tag */ result = 1; /* NB: pseudo tag */
break; break;
default: default:
@@ -1601,6 +1673,16 @@ static const TIFFField pixarlogFields[] = {
{TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO, {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
FALSE, FALSE, "", NULL}}; FALSE, FALSE, "", NULL}};
static uint64_t PixarLogGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* cf https://zlib.net/zlib_tech.html */
const uint64_t MAX_DEFLATE_RATIO = 1032;
/* security margin as I don't understand what this codec does */
return MAX_DEFLATE_RATIO * (uint64_t)4;
}
int TIFFInitPixarLog(TIFF *tif, int scheme) int TIFFInitPixarLog(TIFF *tif, int scheme)
{ {
static const char module[] = "TIFFInitPixarLog"; static const char module[] = "TIFFInitPixarLog";
@@ -1648,6 +1730,7 @@ int TIFFInitPixarLog(TIFF *tif, int scheme)
tif->tif_encodetile = PixarLogEncode; tif->tif_encodetile = PixarLogEncode;
tif->tif_close = PixarLogClose; tif->tif_close = PixarLogClose;
tif->tif_cleanup = PixarLogCleanup; tif->tif_cleanup = PixarLogCleanup;
tif->tif_getmaxcompressionratio = PixarLogGetMaxCompressionRatio;
/* Override SetField so we can handle our private pseudo-tag */ /* Override SetField so we can handle our private pseudo-tag */
sp->vgetparent = tif->tif_tagmethods.vgetfield; sp->vgetparent = tif->tif_tagmethods.vgetfield;

View File

@@ -30,7 +30,7 @@
#include "tif_predict.h" #include "tif_predict.h"
#include "tiffiop.h" #include "tiffiop.h"
#if defined(__x86_64__) || defined(_M_X64) #if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
#include <emmintrin.h> #include <emmintrin.h>
#endif #endif
@@ -151,6 +151,8 @@ static int PredictorSetupDecode(TIFF *tif)
case 64: case 64:
sp->decodepfunc = horAcc64; sp->decodepfunc = horAcc64;
break; break;
default:
break;
} }
/* /*
* Override default decoding method with one that does the * Override default decoding method with one that does the
@@ -247,6 +249,8 @@ static int PredictorSetupEncode(TIFF *tif)
case 64: case 64:
sp->encodepfunc = horDiff64; sp->encodepfunc = horDiff64;
break; break;
default:
break;
} }
/* /*
* Override default encoding method with one that does the * Override default encoding method with one that does the
@@ -590,7 +594,7 @@ static int fpAcc(TIFF *tif, uint8_t *cp0, tmsize_t cc)
cp = (uint8_t *)cp0; cp = (uint8_t *)cp0;
count = 0; count = 0;
#if defined(__x86_64__) || defined(_M_X64) #if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
if (bps == 4) if (bps == 4)
{ {
/* Optimization of general case */ /* Optimization of general case */
@@ -972,7 +976,7 @@ static int PredictorEncodeRow(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
(int64_t)cc); (int64_t)cc);
return 0; return 0;
} }
memcpy(working_copy, bp, cc); memcpy(working_copy, bp, (size_t)cc);
if (!(*sp->encodepfunc)(tif, working_copy, cc)) if (!(*sp->encodepfunc)(tif, working_copy, cc))
{ {
@@ -1010,7 +1014,7 @@ static int PredictorEncodeTile(TIFF *tif, uint8_t *bp0, tmsize_t cc0,
(int64_t)cc0); (int64_t)cc0);
return 0; return 0;
} }
memcpy(working_copy, bp0, cc0); memcpy(working_copy, bp0, (size_t)cc0);
bp = working_copy; bp = working_copy;
rowsize = sp->rowsize; rowsize = sp->rowsize;
@@ -1098,8 +1102,10 @@ static void PredictorPrintDir(TIFF *tif, FILE *fd, long flags)
case 3: case 3:
fprintf(fd, "floating point predictor "); fprintf(fd, "floating point predictor ");
break; break;
default:
break;
} }
fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor); fprintf(fd, "%d (0x%x)\n", sp->predictor, (unsigned)sp->predictor);
} }
if (sp->printdir) if (sp->printdir)
(*sp->printdir)(tif, fd, flags); (*sp->printdir)(tif, fd, flags);

View File

@@ -118,10 +118,10 @@ static void _TIFFPrintField(FILE *fd, const TIFFField *fip,
if (tv_size == 8) if (tv_size == 8)
fprintf(fd, "%lf", ((double *)raw_data)[j]); fprintf(fd, "%lf", ((double *)raw_data)[j]);
else else
fprintf(fd, "%f", ((float *)raw_data)[j]); fprintf(fd, "%f", (double)((float *)raw_data)[j]);
} }
else if (fip->field_type == TIFF_FLOAT) else if (fip->field_type == TIFF_FLOAT)
fprintf(fd, "%f", ((float *)raw_data)[j]); fprintf(fd, "%f", (double)((float *)raw_data)[j]);
else if (fip->field_type == TIFF_LONG8) else if (fip->field_type == TIFF_LONG8)
fprintf(fd, "%" PRIu64, ((uint64_t *)raw_data)[j]); fprintf(fd, "%" PRIu64, ((uint64_t *)raw_data)[j]);
else if (fip->field_type == TIFF_SLONG8) else if (fip->field_type == TIFF_SLONG8)
@@ -193,8 +193,9 @@ static int _TIFFPrettyPrintField(TIFF *tif, const TIFFField *fip, FILE *fd,
case TIFFTAG_WHITEPOINT: case TIFFTAG_WHITEPOINT:
if (value_count == 2 && fip->field_type == TIFF_RATIONAL) if (value_count == 2 && fip->field_type == TIFF_RATIONAL)
{ {
fprintf(fd, " White Point: %g-%g\n", ((float *)raw_data)[0], fprintf(fd, " White Point: %g-%g\n",
((float *)raw_data)[1]); (double)((float *)raw_data)[0],
(double)((float *)raw_data)[1]);
return 1; return 1;
} }
return 0; return 0;
@@ -232,6 +233,9 @@ static int _TIFFPrettyPrintField(TIFF *tif, const TIFFField *fip, FILE *fd,
return 1; return 1;
} }
return 0; return 0;
default:
break;
} }
return 0; return 0;
@@ -244,8 +248,7 @@ static int _TIFFPrettyPrintField(TIFF *tif, const TIFFField *fip, FILE *fd,
void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags) void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
{ {
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
char *sep; const char *sep;
long l, n;
fprintf(fd, "TIFF Directory at offset 0x%" PRIx64 " (%" PRIu64 ")\n", fprintf(fd, "TIFF Directory at offset 0x%" PRIx64 " (%" PRIu64 ")\n",
tif->tif_diroff, tif->tif_diroff); tif->tif_diroff, tif->tif_diroff);
@@ -286,8 +289,8 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
} }
if (TIFFFieldSet(tif, FIELD_RESOLUTION)) if (TIFFFieldSet(tif, FIELD_RESOLUTION))
{ {
fprintf(fd, " Resolution: %g, %g", td->td_xresolution, fprintf(fd, " Resolution: %g, %g", (double)td->td_xresolution,
td->td_yresolution); (double)td->td_yresolution);
if (TIFFFieldSet(tif, FIELD_RESOLUTIONUNIT)) if (TIFFFieldSet(tif, FIELD_RESOLUTIONUNIT))
{ {
switch (td->td_resolutionunit) switch (td->td_resolutionunit)
@@ -310,7 +313,8 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
fprintf(fd, "\n"); fprintf(fd, "\n");
} }
if (TIFFFieldSet(tif, FIELD_POSITION)) if (TIFFFieldSet(tif, FIELD_POSITION))
fprintf(fd, " Position: %g, %g\n", td->td_xposition, td->td_yposition); fprintf(fd, " Position: %g, %g\n", (double)td->td_xposition,
(double)td->td_yposition);
if (TIFFFieldSet(tif, FIELD_BITSPERSAMPLE)) if (TIFFFieldSet(tif, FIELD_BITSPERSAMPLE))
fprintf(fd, " Bits/Sample: %" PRIu16 "\n", td->td_bitspersample); fprintf(fd, " Bits/Sample: %" PRIu16 "\n", td->td_bitspersample);
if (TIFFFieldSet(tif, FIELD_SAMPLEFORMAT)) if (TIFFFieldSet(tif, FIELD_SAMPLEFORMAT))
@@ -374,7 +378,8 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
} }
} }
} }
if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES) && td->td_extrasamples) if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES) && td->td_extrasamples &&
td->td_sampleinfo)
{ {
uint16_t i; uint16_t i;
fprintf(fd, " Extra Samples: %" PRIu16 "<", td->td_extrasamples); fprintf(fd, " Extra Samples: %" PRIu16 "<", td->td_extrasamples);
@@ -412,7 +417,8 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
i > 0 && cp < td->td_inknames + td->td_inknameslen; i > 0 && cp < td->td_inknames + td->td_inknameslen;
cp = strchr(cp, '\0') + 1, i--) cp = strchr(cp, '\0') + 1, i--)
{ {
size_t max_chars = td->td_inknameslen - (cp - td->td_inknames); size_t max_chars =
(size_t)(td->td_inknameslen - (cp - td->td_inknames));
fputs(sep, fd); fputs(sep, fd);
_TIFFprintAsciiBounded(fd, cp, max_chars); _TIFFprintAsciiBounded(fd, cp, max_chars);
sep = ", "; sep = ", ";
@@ -548,17 +554,25 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
if (TIFFFieldSet(tif, FIELD_PAGENUMBER)) if (TIFFFieldSet(tif, FIELD_PAGENUMBER))
fprintf(fd, " Page Number: %" PRIu16 "-%" PRIu16 "\n", fprintf(fd, " Page Number: %" PRIu16 "-%" PRIu16 "\n",
td->td_pagenumber[0], td->td_pagenumber[1]); td->td_pagenumber[0], td->td_pagenumber[1]);
if (TIFFFieldSet(tif, FIELD_COLORMAP)) if (TIFFFieldSet(tif, FIELD_COLORMAP) && td->td_colormap[0] &&
td->td_colormap[1] && td->td_colormap[2])
{ {
fprintf(fd, " Color Map: "); fprintf(fd, " Color Map: ");
if (flags & TIFFPRINT_COLORMAP) if (flags & TIFFPRINT_COLORMAP)
{ {
fprintf(fd, "\n"); fprintf(fd, "\n");
n = 1L << td->td_bitspersample; if (td->td_bitspersample >= 64)
for (l = 0; l < n; l++) fprintf(fd, " (BitsPerSample too large to print safely)\n");
fprintf(fd, " %5ld: %5" PRIu16 " %5" PRIu16 " %5" PRIu16 "\n", else
l, td->td_colormap[0][l], td->td_colormap[1][l], {
td->td_colormap[2][l]); uint64_t n = 1ULL << td->td_bitspersample;
for (uint64_t l = 0u; l < n; l++)
fprintf(fd,
" %5" PRIu64 ": %5" PRIu16 " %5" PRIu16
" %5" PRIu16 "\n",
l, td->td_colormap[0][l], td->td_colormap[1][l],
td->td_colormap[2][l]);
}
} }
else else
fprintf(fd, "(present)\n"); fprintf(fd, "(present)\n");
@@ -569,26 +583,37 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
fprintf(fd, " Reference Black/White:\n"); fprintf(fd, " Reference Black/White:\n");
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
fprintf(fd, " %2d: %5g %5g\n", i, fprintf(fd, " %2d: %5g %5g\n", i,
td->td_refblackwhite[2 * i + 0], (double)td->td_refblackwhite[2 * i + 0],
td->td_refblackwhite[2 * i + 1]); (double)td->td_refblackwhite[2 * i + 1]);
} }
if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION)) if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION) &&
td->td_transferfunction[0] &&
((td->td_samplesperpixel - td->td_extrasamples > 1 &&
td->td_transferfunction[1] && td->td_transferfunction[2]) ||
td->td_samplesperpixel - td->td_extrasamples <= 1))
{ {
fprintf(fd, " Transfer Function: "); fprintf(fd, " Transfer Function: ");
if (flags & TIFFPRINT_CURVES) if (flags & TIFFPRINT_CURVES)
{ {
fprintf(fd, "\n"); fprintf(fd, "\n");
n = 1L << td->td_bitspersample; if (td->td_bitspersample >= 64)
for (l = 0; l < n; l++) fprintf(fd, " (BitsPerSample too large to print safely)\n");
else
{ {
uint16_t i; uint64_t n = 1ULL << td->td_bitspersample;
fprintf(fd, " %2ld: %5" PRIu16, l, for (uint64_t l = 0; l < n; l++)
td->td_transferfunction[0][l]); {
for (i = 1; uint16_t i;
i < td->td_samplesperpixel - td->td_extrasamples && i < 3; fprintf(fd, " %2" PRIu64 ": %5" PRIu16, l,
i++) td->td_transferfunction[0][l]);
fprintf(fd, " %5" PRIu16, td->td_transferfunction[i][l]); for (i = 1;
fputc('\n', fd); i < td->td_samplesperpixel - td->td_extrasamples &&
i < 3;
i++)
fprintf(fd, " %5" PRIu16,
td->td_transferfunction[i][l]);
fputc('\n', fd);
}
} }
} }
else else
@@ -655,7 +680,7 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
else if (fip->field_readcount == TIFF_SPP) else if (fip->field_readcount == TIFF_SPP)
value_count = td->td_samplesperpixel; value_count = td->td_samplesperpixel;
else else
value_count = fip->field_readcount; value_count = (uint32_t)fip->field_readcount;
if (fip->field_tag == TIFFTAG_DOTRANGE && if (fip->field_tag == TIFFTAG_DOTRANGE &&
strcmp(fip->field_name, "DotRange") == 0) strcmp(fip->field_name, "DotRange") == 0)
{ {
@@ -680,7 +705,8 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
* "set_get_field_type" to determine internal storage size. * "set_get_field_type" to determine internal storage size.
*/ */
int tv_size = TIFFFieldSetGetSize(fip); int tv_size = TIFFFieldSetGetSize(fip);
raw_data = _TIFFmallocExt(tif, tv_size * value_count); raw_data = _TIFFCheckMalloc(tif, value_count, tv_size,
"for tag data");
mem_alloc = 1; mem_alloc = 1;
if (TIFFGetField(tif, tag, raw_data) != 1) if (TIFFGetField(tif, tag, raw_data) != 1)
{ {
@@ -744,7 +770,7 @@ static void _TIFFprintAsciiBounded(FILE *fd, const char *cp, size_t max_chars)
if (*tp) if (*tp)
fprintf(fd, "\\%c", *tp); fprintf(fd, "\\%c", *tp);
else else
fprintf(fd, "\\%03o", *cp & 0xff); fprintf(fd, "\\%03o", (unsigned int)(*cp & 0xff));
} }
} }

View File

@@ -27,6 +27,7 @@
* Scanline-oriented Read Support * Scanline-oriented Read Support
*/ */
#include "tiffiop.h" #include "tiffiop.h"
#include <limits.h>
#include <stdio.h> #include <stdio.h>
int TIFFFillStrip(TIFF *tif, uint32_t strip); int TIFFFillStrip(TIFF *tif, uint32_t strip);
@@ -39,9 +40,6 @@ static tmsize_t TIFFReadRawStrip1(TIFF *tif, uint32_t strip, void *buf,
static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf, static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf,
tmsize_t size, const char *module); tmsize_t size, const char *module);
#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
#define NOTILE ((uint32_t)(-1)) /* undefined state */
#define INITIAL_THRESHOLD (1024 * 1024) #define INITIAL_THRESHOLD (1024 * 1024)
#define THRESHOLD_MULTIPLIER 10 #define THRESHOLD_MULTIPLIER 10
#define MAX_THRESHOLD \ #define MAX_THRESHOLD \
@@ -99,7 +97,9 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
uint8_t *new_rawdata; uint8_t *new_rawdata;
assert((tif->tif_flags & TIFF_MYBUFFER) != 0); assert((tif->tif_flags & TIFF_MYBUFFER) != 0);
tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64( tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64(
(uint64_t)already_read + to_read + rawdata_offset, 1024); (uint64_t)already_read + (uint64_t)to_read +
(uint64_t)rawdata_offset,
1024);
if (tif->tif_rawdatasize == 0) if (tif->tif_rawdatasize == 0)
{ {
TIFFErrorExtR(tif, module, "Invalid buffer size"); TIFFErrorExtR(tif, module, "Invalid buffer size");
@@ -111,7 +111,7 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"No space for data buffer at scanline %" PRIu32, "No space for data buffer at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
_TIFFfreeExt(tif, tif->tif_rawdata); _TIFFfreeExt(tif, tif->tif_rawdata);
tif->tif_rawdata = 0; tif->tif_rawdata = 0;
tif->tif_rawdatasize = 0; tif->tif_rawdatasize = 0;
@@ -127,18 +127,22 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
bytes_read = TIFFReadFile( bytes_read = TIFFReadFile(
tif, tif->tif_rawdata + rawdata_offset + already_read, to_read); tif, tif->tif_rawdata + rawdata_offset + already_read, to_read);
if (bytes_read < 0)
/* Treat read errors as short reads before updating offsets. */
bytes_read = 0;
already_read += bytes_read; already_read += bytes_read;
if (bytes_read != to_read) if (bytes_read != to_read)
{ {
memset(tif->tif_rawdata + rawdata_offset + already_read, 0, memset(
tif->tif_rawdatasize - rawdata_offset - already_read); tif->tif_rawdata + rawdata_offset + already_read, 0,
(size_t)(tif->tif_rawdatasize - rawdata_offset - already_read));
if (is_strip) if (is_strip)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Read error at scanline %" PRIu32 "Read error at scanline %" PRIu32
"; got %" TIFF_SSIZE_FORMAT " bytes, " "; got %" TIFF_SSIZE_FORMAT " bytes, "
"expected %" TIFF_SSIZE_FORMAT, "expected %" TIFF_SSIZE_FORMAT,
tif->tif_row, already_read, size); tif->tif_dir.td_row, already_read, size);
} }
else else
{ {
@@ -147,8 +151,8 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
", tile %" PRIu32 "; " ", tile %" PRIu32 "; "
"got %" TIFF_SSIZE_FORMAT "got %" TIFF_SSIZE_FORMAT
" bytes, expected %" TIFF_SSIZE_FORMAT "", " bytes, expected %" TIFF_SSIZE_FORMAT "",
tif->tif_row, tif->tif_col, strip_or_tile, tif->tif_dir.td_row, tif->tif_dir.td_col,
already_read, size); strip_or_tile, already_read, size);
} }
return 0; return 0;
} }
@@ -160,7 +164,7 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
int restart) int restart)
{ {
static const char module[] = "TIFFFillStripPartial"; static const char module[] = "TIFFFillStripPartial";
register TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
tmsize_t unused_data; tmsize_t unused_data;
uint64_t read_offset; uint64_t read_offset;
tmsize_t to_read; tmsize_t to_read;
@@ -185,7 +189,7 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
{ {
assert(restart); assert(restart);
tif->tif_curstrip = NOSTRIP; tif->tif_dir.td_curstrip = NOSTRIP;
if ((tif->tif_flags & TIFF_MYBUFFER) == 0) if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -214,20 +218,30 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
if (unused_data > 0) if (unused_data > 0)
{ {
assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0); assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0);
memmove(tif->tif_rawdata, tif->tif_rawcp, unused_data); memmove(tif->tif_rawdata, tif->tif_rawcp, (size_t)unused_data);
} }
/* /*
** Seek to the point in the file where more data should be read. ** Seek to the point in the file where more data should be read.
*/ */
read_offset = TIFFGetStrileOffset(tif, strip) + tif->tif_rawdataoff + read_offset = TIFFGetStrileOffset(tif, (uint32_t)strip);
tif->tif_rawdataloaded; if (read_offset > UINT64_MAX - (uint64_t)tif->tif_rawdataoff ||
read_offset + (uint64_t)tif->tif_rawdataoff >
UINT64_MAX - (uint64_t)tif->tif_rawdataloaded)
{
TIFFErrorExtR(tif, module,
"Seek error at scanline %" PRIu32 ", strip %d",
tif->tif_dir.td_row, strip);
return 0;
}
read_offset +=
(uint64_t)tif->tif_rawdataoff + (uint64_t)tif->tif_rawdataloaded;
if (!SeekOK(tif, read_offset)) if (!SeekOK(tif, read_offset))
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Seek error at scanline %" PRIu32 ", strip %d", "Seek error at scanline %" PRIu32 ", strip %d",
tif->tif_row, strip); tif->tif_dir.td_row, strip);
return 0; return 0;
} }
@@ -238,11 +252,13 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
to_read = read_ahead_mod - unused_data; to_read = read_ahead_mod - unused_data;
else else
to_read = tif->tif_rawdatasize - unused_data; to_read = tif->tif_rawdatasize - unused_data;
if ((uint64_t)to_read > TIFFGetStrileByteCount(tif, strip) - if ((uint64_t)to_read > TIFFGetStrileByteCount(tif, (uint32_t)strip) -
tif->tif_rawdataoff - tif->tif_rawdataloaded) (uint64_t)tif->tif_rawdataoff -
(uint64_t)tif->tif_rawdataloaded)
{ {
to_read = (tmsize_t)TIFFGetStrileByteCount(tif, strip) - to_read = (tmsize_t)(TIFFGetStrileByteCount(tif, (uint32_t)strip) -
tif->tif_rawdataoff - tif->tif_rawdataloaded; (uint64_t)tif->tif_rawdataoff -
(uint64_t)tif->tif_rawdataloaded);
} }
assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0); assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0);
@@ -281,16 +297,17 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
/* For JPEG, if there are multiple scans (can generally be known */ /* For JPEG, if there are multiple scans (can generally be known */
/* with the read_ahead used), we need to read the whole strip */ /* with the read_ahead used), we need to read the whole strip */
if (tif->tif_dir.td_compression == COMPRESSION_JPEG && if (tif->tif_dir.td_compression == COMPRESSION_JPEG &&
(uint64_t)tif->tif_rawcc < TIFFGetStrileByteCount(tif, strip)) (uint64_t)tif->tif_rawcc <
TIFFGetStrileByteCount(tif, (uint32_t)strip))
{ {
if (TIFFJPEGIsFullStripRequired(tif)) if (TIFFJPEGIsFullStripRequired(tif))
{ {
return TIFFFillStrip(tif, strip); return TIFFFillStrip(tif, (uint32_t)strip);
} }
} }
#endif #endif
return TIFFStartStrip(tif, strip); return TIFFStartStrip(tif, (uint32_t)strip);
} }
else else
{ {
@@ -308,7 +325,7 @@ static int TIFFFillStripPartial(TIFF *tif, int strip, tmsize_t read_ahead,
*/ */
static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample) static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
{ {
register TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint32_t strip; uint32_t strip;
int whole_strip; int whole_strip;
tmsize_t read_ahead = 0; tmsize_t read_ahead = 0;
@@ -323,8 +340,16 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
td->td_imagelength); td->td_imagelength);
return (0); return (0);
} }
if (td->td_rowsperstrip == 0)
{
TIFFErrorExtR(tif, tif->tif_name,
"Cannot compute strip: RowsPerStrip is zero");
return (0);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{ {
uint64_t sample_offset;
uint64_t strip64;
if (sample >= td->td_samplesperpixel) if (sample >= td->td_samplesperpixel)
{ {
TIFFErrorExtR(tif, tif->tif_name, TIFFErrorExtR(tif, tif->tif_name,
@@ -332,16 +357,26 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
sample, td->td_samplesperpixel); sample, td->td_samplesperpixel);
return (0); return (0);
} }
strip = (uint32_t)sample * td->td_stripsperimage + sample_offset =
row / td->td_rowsperstrip; _TIFFMultiply64(tif, sample, td->td_stripsperimage, "TIFFSeek");
if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
return (0);
strip64 = _TIFFAdd64(tif, sample_offset, row / td->td_rowsperstrip,
"TIFFSeek");
if (strip64 == 0 &&
(sample_offset != 0 || (row / td->td_rowsperstrip) != 0))
return (0);
strip = _TIFFCastUInt64ToUInt32(tif, strip64, "TIFFSeek");
if (strip == 0 && strip64 != 0)
return (0);
} }
else else
strip = row / td->td_rowsperstrip; strip = row / td->td_rowsperstrip;
/* /*
* Do we want to treat this strip as one whole chunk or * Do we want to treat this strip as one whole chunk or
* read it a few lines at a time? * read it a few lines at a time?
*/ */
#if defined(CHUNKY_STRIP_READ_SUPPORT) #if defined(CHUNKY_STRIP_READ_SUPPORT)
whole_strip = TIFFGetStrileByteCount(tif, strip) < 10 || isMapped(tif); whole_strip = TIFFGetStrileByteCount(tif, strip) < 10 || isMapped(tif);
if (td->td_compression == COMPRESSION_LERC || if (td->td_compression == COMPRESSION_LERC ||
@@ -359,14 +394,14 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
/* is some constant value, for example for JPEG tables */ /* is some constant value, for example for JPEG tables */
/* coverity[dead_error_line:SUPPRESS] */ /* coverity[dead_error_line:SUPPRESS] */
if (tif->tif_scanlinesize < TIFF_TMSIZE_T_MAX / 16 && if (tif->tif_dir.td_scanlinesize < TIFF_TMSIZE_T_MAX / 16 &&
tif->tif_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000) tif->tif_dir.td_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000)
{ {
read_ahead = tif->tif_scanlinesize * 16 + 5000; read_ahead = tif->tif_dir.td_scanlinesize * 16 + 5000;
} }
else else
{ {
read_ahead = tif->tif_scanlinesize; read_ahead = tif->tif_dir.td_scanlinesize;
} }
} }
#else #else
@@ -377,7 +412,7 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
* If we haven't loaded this strip, do so now, possibly * If we haven't loaded this strip, do so now, possibly
* only reading the first part. * only reading the first part.
*/ */
if (strip != tif->tif_curstrip) if (strip != tif->tif_dir.td_curstrip)
{ /* different strip, refill */ { /* different strip, refill */
if (whole_strip) if (whole_strip)
@@ -412,7 +447,7 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
} }
#endif #endif
if (row < tif->tif_row) if (row < tif->tif_dir.td_row)
{ {
/* /*
* Moving backwards within the same strip: backup * Moving backwards within the same strip: backup
@@ -425,7 +460,7 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
if (tif->tif_rawdataoff != 0) if (tif->tif_rawdataoff != 0)
{ {
if (!TIFFFillStripPartial(tif, strip, read_ahead, 1)) if (!TIFFFillStripPartial(tif, (int)strip, read_ahead, 1))
return 0; return 0;
} }
else else
@@ -435,7 +470,7 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
} }
} }
if (row != tif->tif_row) if (row != tif->tif_dir.td_row)
{ {
/* /*
* Seek forward to the desired row. * Seek forward to the desired row.
@@ -443,9 +478,9 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
/* TODO: Will this really work with partial buffers? */ /* TODO: Will this really work with partial buffers? */
if (!(*tif->tif_seek)(tif, row - tif->tif_row)) if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
return (0); return (0);
tif->tif_row = row; tif->tif_dir.td_row = row;
} }
return (1); return (1);
@@ -462,20 +497,21 @@ int TIFFReadScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
/* /*
* Decompress desired row into user buffer. * Decompress desired row into user buffer.
*/ */
e = (*tif->tif_decoderow)(tif, (uint8_t *)buf, tif->tif_scanlinesize, e = (*tif->tif_decoderow)(tif, (uint8_t *)buf,
sample); tif->tif_dir.td_scanlinesize, sample);
/* we are now poised at the beginning of the next row */ /* we are now poised at the beginning of the next row */
tif->tif_row = row + 1; tif->tif_dir.td_row = row + 1;
if (e) if (e)
(*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize); (*tif->tif_postdecode)(tif, (uint8_t *)buf,
tif->tif_dir.td_scanlinesize);
} }
else else
{ {
/* See TIFFReadEncodedStrip comment regarding TIFFTAG_FAXFILLFUNC. */ /* See TIFFReadEncodedStrip comment regarding TIFFTAG_FAXFILLFUNC. */
if (buf) if (buf)
memset(buf, 0, (size_t)tif->tif_scanlinesize); memset(buf, 0, (size_t)tif->tif_dir.td_scanlinesize);
} }
return (e > 0 ? 1 : -1); return (e > 0 ? 1 : -1);
} }
@@ -553,9 +589,9 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf,
if (!isFillOrder(tif, td->td_fillorder) && if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits(buf, stripsize); TIFFReverseBits((uint8_t *)buf, stripsize);
(*tif->tif_postdecode)(tif, buf, stripsize); (*tif->tif_postdecode)(tif, (uint8_t *)buf, stripsize);
return (stripsize); return (stripsize);
} }
@@ -569,9 +605,9 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf,
memset(buf, 0, (size_t)stripsize); memset(buf, 0, (size_t)stripsize);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0) if ((*tif->tif_decodestrip)(tif, (uint8_t *)buf, stripsize, plane) <= 0)
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
(*tif->tif_postdecode)(tif, buf, stripsize); (*tif->tif_postdecode)(tif, (uint8_t *)buf, stripsize);
return (stripsize); return (stripsize);
} }
@@ -603,17 +639,39 @@ tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif, uint32_t strip,
if (!TIFFFillStrip(tif, strip)) if (!TIFFFillStrip(tif, strip))
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
*buf = _TIFFmallocExt(tif, bufsizetoalloc); /* Sanity checks to avoid excessive memory allocation */
/* Max compression ratio experimentally determined. Might be fragile...
* Only apply this heuristics to situations where the memory allocation
* would be big, to avoid breaking nominal use cases.
*/
if (bufsizetoalloc > 100 * 1024 * 1024)
{
const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif);
if (maxCompressionRatio > 0 &&
(uint64_t)tif->tif_rawdatasize <
(uint64_t)this_stripsize / maxCompressionRatio)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"Likely invalid strip byte count for strip %u. "
"Uncompressed strip size is %" PRIu64 ", "
"compressed one is %" PRIu64,
strip, (uint64_t)this_stripsize,
(uint64_t)tif->tif_rawdatasize);
return ((tmsize_t)(-1));
}
}
*buf = _TIFFcallocExt(tif, 1, bufsizetoalloc);
if (*buf == NULL) if (*buf == NULL)
{ {
TIFFErrorExtR(tif, TIFFFileName(tif), "No space for strip buffer"); TIFFErrorExtR(tif, TIFFFileName(tif), "No space for strip buffer");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
_TIFFmemset(*buf, 0, bufsizetoalloc);
if ((*tif->tif_decodestrip)(tif, *buf, this_stripsize, plane) <= 0) if ((*tif->tif_decodestrip)(tif, (uint8_t *)*buf, this_stripsize, plane) <=
0)
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
(*tif->tif_postdecode)(tif, *buf, this_stripsize); (*tif->tif_postdecode)(tif, (uint8_t *)*buf, this_stripsize);
return (this_stripsize); return (this_stripsize);
} }
@@ -629,7 +687,7 @@ static tmsize_t TIFFReadRawStrip1(TIFF *tif, uint32_t strip, void *buf,
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Seek error at scanline %" PRIu32 ", strip %" PRIu32, "Seek error at scanline %" PRIu32 ", strip %" PRIu32,
tif->tif_row, strip); tif->tif_dir.td_row, strip);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
cc = TIFFReadFile(tif, buf, size); cc = TIFFReadFile(tif, buf, size);
@@ -639,7 +697,7 @@ static tmsize_t TIFFReadRawStrip1(TIFF *tif, uint32_t strip, void *buf,
"Read error at scanline %" PRIu32 "Read error at scanline %" PRIu32
"; got %" TIFF_SSIZE_FORMAT "; got %" TIFF_SSIZE_FORMAT
" bytes, expected %" TIFF_SSIZE_FORMAT, " bytes, expected %" TIFF_SSIZE_FORMAT,
tif->tif_row, cc, size); tif->tif_dir.td_row, cc, size);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
} }
@@ -670,7 +728,7 @@ static tmsize_t TIFFReadRawStrip1(TIFF *tif, uint32_t strip, void *buf,
"Read error at scanline %" PRIu32 ", strip %" PRIu32 "Read error at scanline %" PRIu32 ", strip %" PRIu32
"; got %" TIFF_SSIZE_FORMAT "; got %" TIFF_SSIZE_FORMAT
" bytes, expected %" TIFF_SSIZE_FORMAT, " bytes, expected %" TIFF_SSIZE_FORMAT,
tif->tif_row, strip, n, size); tif->tif_dir.td_row, strip, n, size);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
_TIFFmemcpy(buf, tif->tif_base + ma, size); _TIFFmemcpy(buf, tif->tif_base + ma, size);
@@ -691,14 +749,14 @@ static tmsize_t TIFFReadRawStripOrTile2(TIFF *tif, uint32_t strip_or_tile,
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Seek error at scanline %" PRIu32 ", strip %" PRIu32, "Seek error at scanline %" PRIu32 ", strip %" PRIu32,
tif->tif_row, strip_or_tile); tif->tif_dir.td_row, strip_or_tile);
} }
else else
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(
"Seek error at row %" PRIu32 ", col %" PRIu32 tif, module,
", tile %" PRIu32, "Seek error at row %" PRIu32 ", col %" PRIu32 ", tile %" PRIu32,
tif->tif_row, tif->tif_col, strip_or_tile); tif->tif_dir.td_row, tif->tif_dir.td_col, strip_or_tile);
} }
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
@@ -774,22 +832,50 @@ int TIFFFillStrip(TIFF *tif, uint32_t strip)
} }
/* To avoid excessive memory allocations: */ /* To avoid excessive memory allocations: */
/* Byte count should normally not be larger than a number of */ const tmsize_t stripsize = TIFFStripSize(tif);
/* times the uncompressed size plus some margin */ if (stripsize > 0)
if (bytecount > 1024 * 1024)
{ {
/* 10 and 4096 are just values that could be adjusted. */ if (bytecount > 1024 * 1024 &&
/* Hopefully they are safe enough for all codecs */ (bytecount - 4096) / 10 > (uint64_t)stripsize)
tmsize_t stripsize = TIFFStripSize(tif);
if (stripsize != 0 && (bytecount - 4096) / 10 > (uint64_t)stripsize)
{ {
/* Byte count should normally not be larger than a number of */
/* times the uncompressed size plus some margin */
/* 10 and 4096 are just values that could be adjusted. */
/* Hopefully they are safe enough for all codecs */
/* What happens next will depend on whether only the bytecount
*/
/* was corrupted to a large value but the strip/tile data is */
/* fine. In that situation most codecs should work fine and */
/* only used part of the tile/strip data. If the strip/tile */
/* data is corrupted too, then codecs will later error out. */
uint64_t newbytecount = (uint64_t)stripsize * 10 + 4096; uint64_t newbytecount = (uint64_t)stripsize * 10 + 4096;
TIFFErrorExtR(tif, module, TIFFWarningExtR(tif, module,
"Too large strip byte count %" PRIu64 "Too large strip byte count %" PRIu64
", strip %" PRIu32 ". Limiting to %" PRIu64, ", strip %" PRIu32 ". Limiting to %" PRIu64,
bytecount, strip, newbytecount); bytecount, strip, newbytecount);
bytecount = newbytecount; bytecount = newbytecount;
} }
else if (stripsize > 100 * 1024 * 1024)
{
/* Max compression ratio experimentally determined. Might be
* fragile... Only apply this heuristics to situations where the
* memory allocation would be big, to avoid breaking nominal use
* cases.
*/
const uint64_t maxCompressionRatio =
TIFFGetMaxCompressionRatio(tif);
if (maxCompressionRatio > 0 &&
bytecount < (uint64_t)stripsize / maxCompressionRatio)
{
TIFFErrorExtR(
tif, module,
"Likely invalid strip byte count for strip %u. "
"Uncompressed strip size is %" PRIu64 ", "
"compressed one is %" PRIu64,
strip, (uint64_t)stripsize, bytecount);
return 0;
}
}
} }
if (isMapped(tif)) if (isMapped(tif))
@@ -818,10 +904,10 @@ int TIFFFillStrip(TIFF *tif, uint32_t strip)
"Read error on strip %" PRIu32 "; " "Read error on strip %" PRIu32 "; "
"got %" PRIu64 " bytes, expected %" PRIu64, "got %" PRIu64 " bytes, expected %" PRIu64,
strip, strip,
NoSanitizeSubUInt64(tif->tif_size, NoSanitizeSubUInt64((uint64_t)tif->tif_size,
TIFFGetStrileOffset(tif, strip)), TIFFGetStrileOffset(tif, strip)),
bytecount); bytecount);
tif->tif_curstrip = NOSTRIP; tif->tif_dir.td_curstrip = NOSTRIP;
return (0); return (0);
} }
} }
@@ -878,7 +964,7 @@ int TIFFFillStrip(TIFF *tif, uint32_t strip)
} }
if (bytecountm > tif->tif_rawdatasize) if (bytecountm > tif->tif_rawdatasize)
{ {
tif->tif_curstrip = NOSTRIP; tif->tif_dir.td_curstrip = NOSTRIP;
if ((tif->tif_flags & TIFF_MYBUFFER) == 0) if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
{ {
TIFFErrorExtR( TIFFErrorExtR(
@@ -889,7 +975,7 @@ int TIFFFillStrip(TIFF *tif, uint32_t strip)
} }
if (tif->tif_flags & TIFF_BUFFERMMAP) if (tif->tif_flags & TIFF_BUFFERMMAP)
{ {
tif->tif_curstrip = NOSTRIP; tif->tif_dir.td_curstrip = NOSTRIP;
tif->tif_rawdata = NULL; tif->tif_rawdata = NULL;
tif->tif_rawdatasize = 0; tif->tif_rawdatasize = 0;
tif->tif_flags &= ~TIFF_BUFFERMMAP; tif->tif_flags &= ~TIFF_BUFFERMMAP;
@@ -954,7 +1040,7 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size)
{ {
static const char module[] = "TIFFReadEncodedTile"; static const char module[] = "TIFFReadEncodedTile";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
tmsize_t tilesize = tif->tif_tilesize; tmsize_t tilesize = tif->tif_dir.td_tilesize;
if (!TIFFCheckRead(tif, 1)) if (!TIFFCheckRead(tif, 1))
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
@@ -976,9 +1062,9 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size)
if (!isFillOrder(tif, td->td_fillorder) && if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits(buf, tilesize); TIFFReverseBits((uint8_t *)buf, tilesize);
(*tif->tif_postdecode)(tif, buf, tilesize); (*tif->tif_postdecode)(tif, (uint8_t *)buf, tilesize);
return (tilesize); return (tilesize);
} }
@@ -1032,7 +1118,7 @@ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF *tif, uint32_t tile,
{ {
static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
tmsize_t tilesize = tif->tif_tilesize; tmsize_t tilesize = tif->tif_dir.td_tilesize;
if (*buf != NULL) if (*buf != NULL)
{ {
@@ -1072,25 +1158,22 @@ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF *tif, uint32_t tile,
* Only apply this heuristics to situations where the memory allocation * Only apply this heuristics to situations where the memory allocation
* would be big, to avoid breaking nominal use cases. * would be big, to avoid breaking nominal use cases.
*/ */
const int maxCompressionRatio = if (bufsizetoalloc > 100 * 1024 * 1024)
td->td_compression == COMPRESSION_ZSTD ? 33000
: td->td_compression == COMPRESSION_JXL
?
/* Evaluated on a 8000x8000 tile */
25000 * (td->td_planarconfig == PLANARCONFIG_CONTIG
? td->td_samplesperpixel
: 1)
: td->td_compression == COMPRESSION_LZMA ? 7000 : 1000;
if (bufsizetoalloc > 100 * 1000 * 1000 &&
tif->tif_rawdatasize < tilesize / maxCompressionRatio)
{ {
TIFFErrorExtR(tif, TIFFFileName(tif), const uint64_t maxCompressionRatio =
"Likely invalid tile byte count for tile %u. " TIFFGetMaxCompressionRatio(tif);
"Uncompressed tile size is %" PRIu64 ", " if (maxCompressionRatio > 0 &&
"compressed one is %" PRIu64, (uint64_t)tif->tif_rawdatasize <
tile, (uint64_t)tilesize, (uint64_t)tilesize / maxCompressionRatio)
(uint64_t)tif->tif_rawdatasize); {
return ((tmsize_t)(-1)); TIFFErrorExtR(tif, TIFFFileName(tif),
"Likely invalid tile byte count for tile %u. "
"Uncompressed tile size is %" PRIu64 ", "
"compressed one is %" PRIu64,
tile, (uint64_t)tilesize,
(uint64_t)tif->tif_rawdatasize);
return ((tmsize_t)(-1));
}
} }
} }
@@ -1129,7 +1212,7 @@ static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf,
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Seek error at row %" PRIu32 ", col %" PRIu32 "Seek error at row %" PRIu32 ", col %" PRIu32
", tile %" PRIu32, ", tile %" PRIu32,
tif->tif_row, tif->tif_col, tile); tif->tif_dir.td_row, tif->tif_dir.td_col, tile);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
cc = TIFFReadFile(tif, buf, size); cc = TIFFReadFile(tif, buf, size);
@@ -1139,7 +1222,7 @@ static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf,
"Read error at row %" PRIu32 ", col %" PRIu32 "Read error at row %" PRIu32 ", col %" PRIu32
"; got %" TIFF_SSIZE_FORMAT "; got %" TIFF_SSIZE_FORMAT
" bytes, expected %" TIFF_SSIZE_FORMAT, " bytes, expected %" TIFF_SSIZE_FORMAT,
tif->tif_row, tif->tif_col, cc, size); tif->tif_dir.td_row, tif->tif_dir.td_col, cc, size);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
} }
@@ -1162,7 +1245,8 @@ static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf,
"Read error at row %" PRIu32 ", col %" PRIu32 "Read error at row %" PRIu32 ", col %" PRIu32
", tile %" PRIu32 "; got %" TIFF_SSIZE_FORMAT ", tile %" PRIu32 "; got %" TIFF_SSIZE_FORMAT
" bytes, expected %" TIFF_SSIZE_FORMAT, " bytes, expected %" TIFF_SSIZE_FORMAT,
tif->tif_row, tif->tif_col, tile, n, size); tif->tif_dir.td_row, tif->tif_dir.td_col, tile, n,
size);
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
_TIFFmemcpy(buf, tif->tif_base + ma, size); _TIFFmemcpy(buf, tif->tif_base + ma, size);
@@ -1229,22 +1313,49 @@ int TIFFFillTile(TIFF *tif, uint32_t tile)
} }
/* To avoid excessive memory allocations: */ /* To avoid excessive memory allocations: */
/* Byte count should normally not be larger than a number of */ const tmsize_t tilesize = TIFFTileSize(tif);
/* times the uncompressed size plus some margin */ if (tilesize > 0)
if (bytecount > 1024 * 1024)
{ {
/* 10 and 4096 are just values that could be adjusted. */ if (bytecount > 1024 * 1024 &&
/* Hopefully they are safe enough for all codecs */ (bytecount - 4096) / 10 > (uint64_t)tilesize)
tmsize_t stripsize = TIFFTileSize(tif);
if (stripsize != 0 && (bytecount - 4096) / 10 > (uint64_t)stripsize)
{ {
uint64_t newbytecount = (uint64_t)stripsize * 10 + 4096; /* Byte count should normally not be larger than a number of */
TIFFErrorExtR(tif, module, /* times the uncompressed size plus some margin */
"Too large tile byte count %" PRIu64 /* 10 and 4096 are just values that could be adjusted. */
", tile %" PRIu32 ". Limiting to %" PRIu64, /* Hopefully they are safe enough for all codecs */
bytecount, tile, newbytecount); /* What happens next will depend on whether only the bytecount
*/
/* was corrupted to a large value but the strip/tile data is */
/* fine. In that situation most codecs should work fine and */
/* only used part of the tile/strip data. If the strip/tile */
/* data is corrupted too, then codecs will later error out. */
uint64_t newbytecount = (uint64_t)tilesize * 10 + 4096;
TIFFWarningExtR(tif, module,
"Too large tile byte count %" PRIu64
", tile %" PRIu32 ". Limiting to %" PRIu64,
bytecount, tile, newbytecount);
bytecount = newbytecount; bytecount = newbytecount;
} }
else if (tilesize > 100 * 1024 * 1024)
{
/* Max compression ratio experimentally determined. Might be
* fragile... Only apply this heuristics to situations where the
* memory allocation would be big, to avoid breaking nominal use
* cases.
*/
const uint64_t maxCompressionRatio =
TIFFGetMaxCompressionRatio(tif);
if (maxCompressionRatio > 0 &&
bytecount < (uint64_t)tilesize / maxCompressionRatio)
{
TIFFErrorExtR(tif, module,
"Likely invalid tile byte count for tile %u. "
"Uncompressed tile size is %" PRIu64 ", "
"compressed one is %" PRIu64,
tile, (uint64_t)tilesize, bytecount);
return 0;
}
}
} }
if (isMapped(tif)) if (isMapped(tif))
@@ -1262,7 +1373,7 @@ int TIFFFillTile(TIFF *tif, uint32_t tile)
TIFFGetStrileOffset(tif, tile) > TIFFGetStrileOffset(tif, tile) >
(uint64_t)tif->tif_size - bytecount) (uint64_t)tif->tif_size - bytecount)
{ {
tif->tif_curtile = NOTILE; tif->tif_dir.td_curtile = NOTILE;
return (0); return (0);
} }
} }
@@ -1312,7 +1423,7 @@ int TIFFFillTile(TIFF *tif, uint32_t tile)
} }
if (bytecountm > tif->tif_rawdatasize) if (bytecountm > tif->tif_rawdatasize)
{ {
tif->tif_curtile = NOTILE; tif->tif_dir.td_curtile = NOTILE;
if ((tif->tif_flags & TIFF_MYBUFFER) == 0) if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
@@ -1323,7 +1434,7 @@ int TIFFFillTile(TIFF *tif, uint32_t tile)
} }
if (tif->tif_flags & TIFF_BUFFERMMAP) if (tif->tif_flags & TIFF_BUFFERMMAP)
{ {
tif->tif_curtile = NOTILE; tif->tif_dir.td_curtile = NOTILE;
tif->tif_rawdata = NULL; tif->tif_rawdata = NULL;
tif->tif_rawdatasize = 0; tif->tif_rawdatasize = 0;
tif->tif_flags &= ~TIFF_BUFFERMMAP; tif->tif_flags &= ~TIFF_BUFFERMMAP;
@@ -1410,7 +1521,7 @@ int TIFFReadBufferSetup(TIFF *tif, void *bp, tmsize_t size)
{ {
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"No space for data buffer at scanline %" PRIu32, "No space for data buffer at scanline %" PRIu32,
tif->tif_row); tif->tif_dir.td_row);
tif->tif_rawdatasize = 0; tif->tif_rawdatasize = 0;
return (0); return (0);
} }
@@ -1431,8 +1542,13 @@ static int TIFFStartStrip(TIFF *tif, uint32_t strip)
return (0); return (0);
tif->tif_flags |= TIFF_CODERSETUP; tif->tif_flags |= TIFF_CODERSETUP;
} }
tif->tif_curstrip = strip; if (td->td_stripsperimage == 0)
tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; {
TIFFErrorExtR(tif, "TIFFStartStrip", "Zero strips per image");
return 0;
}
tif->tif_dir.td_curstrip = strip;
tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
tif->tif_flags &= ~TIFF_BUF4WRITE; tif->tif_flags &= ~TIFF_BUF4WRITE;
if (tif->tif_flags & TIFF_NOREADRAW) if (tif->tif_flags & TIFF_NOREADRAW)
@@ -1456,7 +1572,7 @@ static int TIFFStartStrip(TIFF *tif, uint32_t strip)
*/ */
/* tif_curstrip, we'd call tif_decoderow() on a possibly invalid */ /* tif_curstrip, we'd call tif_decoderow() on a possibly invalid */
/* codec state. */ /* codec state. */
tif->tif_curstrip = NOSTRIP; tif->tif_dir.td_curstrip = NOSTRIP;
return 0; return 0;
} }
return 1; return 1;
@@ -1478,7 +1594,7 @@ static int TIFFStartTile(TIFF *tif, uint32_t tile)
return (0); return (0);
tif->tif_flags |= TIFF_CODERSETUP; tif->tif_flags |= TIFF_CODERSETUP;
} }
tif->tif_curtile = tile; tif->tif_dir.td_curtile = tile;
if (td->td_tilewidth == 0) if (td->td_tilewidth == 0)
{ {
TIFFErrorExtR(tif, module, "Zero tilewidth"); TIFFErrorExtR(tif, module, "Zero tilewidth");
@@ -1490,14 +1606,14 @@ static int TIFFStartTile(TIFF *tif, uint32_t tile)
TIFFErrorExtR(tif, module, "Zero tiles"); TIFFErrorExtR(tif, module, "Zero tiles");
return 0; return 0;
} }
tif->tif_row = (tile % howmany32) * td->td_tilelength; tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength); howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
if (howmany32 == 0) if (howmany32 == 0)
{ {
TIFFErrorExtR(tif, module, "Zero tiles"); TIFFErrorExtR(tif, module, "Zero tiles");
return 0; return 0;
} }
tif->tif_col = (tile % howmany32) * td->td_tilewidth; tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
tif->tif_flags &= ~TIFF_BUF4WRITE; tif->tif_flags &= ~TIFF_BUF4WRITE;
if (tif->tif_flags & TIFF_NOREADRAW) if (tif->tif_flags & TIFF_NOREADRAW)
{ {
@@ -1568,14 +1684,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_flags &= ~TIFF_MYBUFFER;
tif->tif_flags |= TIFF_BUFFERMMAP; tif->tif_flags |= TIFF_BUFFERMMAP;
tif->tif_rawdatasize = insize; tif->tif_rawdatasize = insize;
tif->tif_rawdata = inbuf; tif->tif_rawdata = (uint8_t *)inbuf;
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = insize; tif->tif_rawdataloaded = insize;
if (!isFillOrder(tif, td->td_fillorder) && if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
{ {
TIFFReverseBits(inbuf, insize); TIFFReverseBits((uint8_t *)inbuf, insize);
} }
if (TIFFIsTiled(tif)) if (TIFFIsTiled(tif))
@@ -1632,13 +1748,13 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
if (!isFillOrder(tif, td->td_fillorder) && if (!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
{ {
TIFFReverseBits(inbuf, insize); TIFFReverseBits((uint8_t *)inbuf, insize);
} }
tif->tif_flags = (old_tif_flags & (TIFF_MYBUFFER | TIFF_BUFFERMMAP)) | tif->tif_flags = (old_tif_flags & (TIFF_MYBUFFER | TIFF_BUFFERMMAP)) |
(tif->tif_flags & ~(TIFF_MYBUFFER | TIFF_BUFFERMMAP)); (tif->tif_flags & ~(TIFF_MYBUFFER | TIFF_BUFFERMMAP));
tif->tif_rawdatasize = old_rawdatasize; tif->tif_rawdatasize = old_rawdatasize;
tif->tif_rawdata = old_rawdata; tif->tif_rawdata = (uint8_t *)old_rawdata;
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = 0; tif->tif_rawdataloaded = 0;

View File

@@ -47,6 +47,8 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample)
strip = row / td->td_rowsperstrip; strip = row / td->td_rowsperstrip;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{ {
uint64_t sample_offset;
uint64_t strip64;
if (sample >= td->td_samplesperpixel) if (sample >= td->td_samplesperpixel)
{ {
TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu", TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
@@ -54,7 +56,16 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample)
(unsigned long)td->td_samplesperpixel); (unsigned long)td->td_samplesperpixel);
return (0); return (0);
} }
strip += (uint32_t)sample * td->td_stripsperimage; sample_offset = _TIFFMultiply64(tif, sample, td->td_stripsperimage,
"TIFFComputeStrip");
if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
return (0);
strip64 = _TIFFAdd64(tif, sample_offset, strip, "TIFFComputeStrip");
if (strip64 == 0 && (sample_offset != 0 || strip != 0))
return (0);
strip = _TIFFCastUInt64ToUInt32(tif, strip64, "TIFFComputeStrip");
if (strip == 0 && strip64 != 0)
return (0);
} }
return (strip); return (strip);
} }
@@ -83,14 +94,24 @@ uint32_t TIFFNumberOfStrips(TIFF *tif)
} }
/* /*
* Compute the # bytes in a variable height, row-aligned strip. * Compute the # bytes in a variable height, row-aligned strip if isStrip is
* TRUE, or in a tile if isStrip is FALSE
*/ */
uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows) uint64_t _TIFFStrileSize64(TIFF *tif, uint32_t nrows, int isStrip)
{ {
static const char module[] = "TIFFVStripSize64"; static const char module[] = "_TIFFStrileSize64";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (nrows == (uint32_t)(-1)) if (isStrip)
nrows = td->td_imagelength; {
if (nrows == (uint32_t)(-1))
nrows = td->td_imagelength;
}
else
{
if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
td->td_tiledepth == 0)
return (0);
}
if ((td->td_planarconfig == PLANARCONFIG_CONTIG) && if ((td->td_planarconfig == PLANARCONFIG_CONTIG) &&
(td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif))) (td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
{ {
@@ -125,9 +146,10 @@ uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
ycbcrsubsampling[0], ycbcrsubsampling[1]); ycbcrsubsampling[0], ycbcrsubsampling[1]);
return 0; return 0;
} }
samplingblock_samples = ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2; samplingblock_samples =
samplingblocks_hor = (uint16_t)(ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2);
TIFFhowmany_32(td->td_imagewidth, ycbcrsubsampling[0]); const uint32_t width = isStrip ? td->td_imagewidth : td->td_tilewidth;
samplingblocks_hor = TIFFhowmany_32(width, ycbcrsubsampling[0]);
samplingblocks_ver = TIFFhowmany_32(nrows, ycbcrsubsampling[1]); samplingblocks_ver = TIFFhowmany_32(nrows, ycbcrsubsampling[1]);
samplingrow_samples = _TIFFMultiply64(tif, samplingblocks_hor, samplingrow_samples = _TIFFMultiply64(tif, samplingblocks_hor,
samplingblock_samples, module); samplingblock_samples, module);
@@ -137,8 +159,20 @@ uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
_TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module)); _TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module));
} }
else else
return (_TIFFMultiply64(tif, nrows, TIFFScanlineSize64(tif), module)); return (_TIFFMultiply64(tif, nrows,
isStrip ? TIFFScanlineSize64(tif)
: TIFFTileRowSize64(tif),
module));
} }
/*
* Compute the # bytes in a variable height, row-aligned strip.
*/
uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
{
return _TIFFStrileSize64(tif, nrows, /* isStrip = */ TRUE);
}
tmsize_t TIFFVStripSize(TIFF *tif, uint32_t nrows) tmsize_t TIFFVStripSize(TIFF *tif, uint32_t nrows)
{ {
static const char module[] = "TIFFVStripSize"; static const char module[] = "TIFFVStripSize";
@@ -286,7 +320,7 @@ uint64_t TIFFScanlineSize64(TIFF *tif)
return 0; return 0;
} }
samplingblock_samples = samplingblock_samples =
ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2; (uint16_t)(ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2);
samplingblocks_hor = samplingblocks_hor =
TIFFhowmany_32(td->td_imagewidth, ycbcrsubsampling[0]); TIFFhowmany_32(td->td_imagewidth, ycbcrsubsampling[0]);
samplingrow_samples = _TIFFMultiply64( samplingrow_samples = _TIFFMultiply64(

View File

@@ -32,7 +32,7 @@
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabShort) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabShort)
void TIFFSwabShort(uint16_t *wp) void TIFFSwabShort(uint16_t *wp)
{ {
register unsigned char *cp = (unsigned char *)wp; unsigned char *cp = (unsigned char *)wp;
unsigned char t; unsigned char t;
assert(sizeof(uint16_t) == 2); assert(sizeof(uint16_t) == 2);
t = cp[1]; t = cp[1];
@@ -44,7 +44,7 @@ void TIFFSwabShort(uint16_t *wp)
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong)
void TIFFSwabLong(uint32_t *lp) void TIFFSwabLong(uint32_t *lp)
{ {
register unsigned char *cp = (unsigned char *)lp; unsigned char *cp = (unsigned char *)lp;
unsigned char t; unsigned char t;
assert(sizeof(uint32_t) == 4); assert(sizeof(uint32_t) == 4);
t = cp[3]; t = cp[3];
@@ -59,7 +59,7 @@ void TIFFSwabLong(uint32_t *lp)
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong8) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong8)
void TIFFSwabLong8(uint64_t *lp) void TIFFSwabLong8(uint64_t *lp)
{ {
register unsigned char *cp = (unsigned char *)lp; unsigned char *cp = (unsigned char *)lp;
unsigned char t; unsigned char t;
assert(sizeof(uint64_t) == 8); assert(sizeof(uint64_t) == 8);
t = cp[7]; t = cp[7];
@@ -78,10 +78,10 @@ void TIFFSwabLong8(uint64_t *lp)
#endif #endif
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfShort) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfShort)
void TIFFSwabArrayOfShort(register uint16_t *wp, tmsize_t n) void TIFFSwabArrayOfShort(uint16_t *wp, tmsize_t n)
{ {
register unsigned char *cp; unsigned char *cp;
register unsigned char t; unsigned char t;
assert(sizeof(uint16_t) == 2); assert(sizeof(uint16_t) == 2);
/* XXX unroll loop some */ /* XXX unroll loop some */
while (n-- > 0) while (n-- > 0)
@@ -96,7 +96,7 @@ void TIFFSwabArrayOfShort(register uint16_t *wp, tmsize_t n)
#endif #endif
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfTriples) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfTriples)
void TIFFSwabArrayOfTriples(register uint8_t *tp, tmsize_t n) void TIFFSwabArrayOfTriples(uint8_t *tp, tmsize_t n)
{ {
unsigned char *cp; unsigned char *cp;
unsigned char t; unsigned char t;
@@ -114,10 +114,10 @@ void TIFFSwabArrayOfTriples(register uint8_t *tp, tmsize_t n)
#endif #endif
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong)
void TIFFSwabArrayOfLong(register uint32_t *lp, tmsize_t n) void TIFFSwabArrayOfLong(uint32_t *lp, tmsize_t n)
{ {
register unsigned char *cp; unsigned char *cp;
register unsigned char t; unsigned char t;
assert(sizeof(uint32_t) == 4); assert(sizeof(uint32_t) == 4);
/* XXX unroll loop some */ /* XXX unroll loop some */
while (n-- > 0) while (n-- > 0)
@@ -135,10 +135,10 @@ void TIFFSwabArrayOfLong(register uint32_t *lp, tmsize_t n)
#endif #endif
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong8) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong8)
void TIFFSwabArrayOfLong8(register uint64_t *lp, tmsize_t n) void TIFFSwabArrayOfLong8(uint64_t *lp, tmsize_t n)
{ {
register unsigned char *cp; unsigned char *cp;
register unsigned char t; unsigned char t;
assert(sizeof(uint64_t) == 8); assert(sizeof(uint64_t) == 8);
/* XXX unroll loop some */ /* XXX unroll loop some */
while (n-- > 0) while (n-- > 0)
@@ -164,7 +164,7 @@ void TIFFSwabArrayOfLong8(register uint64_t *lp, tmsize_t n)
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabFloat) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabFloat)
void TIFFSwabFloat(float *fp) void TIFFSwabFloat(float *fp)
{ {
register unsigned char *cp = (unsigned char *)fp; unsigned char *cp = (unsigned char *)fp;
unsigned char t; unsigned char t;
assert(sizeof(float) == 4); assert(sizeof(float) == 4);
t = cp[3]; t = cp[3];
@@ -177,10 +177,10 @@ void TIFFSwabFloat(float *fp)
#endif #endif
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfFloat) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfFloat)
void TIFFSwabArrayOfFloat(register float *fp, tmsize_t n) void TIFFSwabArrayOfFloat(float *fp, tmsize_t n)
{ {
register unsigned char *cp; unsigned char *cp;
register unsigned char t; unsigned char t;
assert(sizeof(float) == 4); assert(sizeof(float) == 4);
/* XXX unroll loop some */ /* XXX unroll loop some */
while (n-- > 0) while (n-- > 0)
@@ -200,7 +200,7 @@ void TIFFSwabArrayOfFloat(register float *fp, tmsize_t n)
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabDouble) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabDouble)
void TIFFSwabDouble(double *dp) void TIFFSwabDouble(double *dp)
{ {
register unsigned char *cp = (unsigned char *)dp; unsigned char *cp = (unsigned char *)dp;
unsigned char t; unsigned char t;
assert(sizeof(double) == 8); assert(sizeof(double) == 8);
t = cp[7]; t = cp[7];
@@ -221,8 +221,8 @@ void TIFFSwabDouble(double *dp)
#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfDouble) #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfDouble)
void TIFFSwabArrayOfDouble(double *dp, tmsize_t n) void TIFFSwabArrayOfDouble(double *dp, tmsize_t n)
{ {
register unsigned char *cp; unsigned char *cp;
register unsigned char t; unsigned char t;
assert(sizeof(double) == 8); assert(sizeof(double) == 8);
/* XXX unroll loop some */ /* XXX unroll loop some */
while (n-- > 0) while (n-- > 0)

View File

@@ -41,7 +41,7 @@
* or 3-bit delta values are used, with the deltas packed * or 3-bit delta values are used, with the deltas packed
* into a single byte. * into a single byte.
*/ */
#define THUNDER_DATA 0x3f /* mask for 6-bit data */ // #define THUNDER_DATA 0x3f /* mask for 6-bit data */
#define THUNDER_CODE 0xc0 /* mask for 2-bit code word */ #define THUNDER_CODE 0xc0 /* mask for 2-bit code word */
/* code values */ /* code values */
#define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */ #define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */
@@ -56,11 +56,11 @@ static const int threebitdeltas[8] = {0, 1, 2, 3, 0, -3, -2, -1};
#define SETPIXEL(op, v) \ #define SETPIXEL(op, v) \
{ \ { \
lastpixel = (v)&0xf; \ lastpixel = (v) & 0xf; \
if (npixels < maxpixels) \ if (npixels < maxpixels) \
{ \ { \
if (npixels++ & 1) \ if (npixels++ & 1) \
*op++ |= lastpixel; \ *op++ |= (uint8_t)lastpixel; \
else \ else \
op[0] = (uint8_t)(lastpixel << 4); \ op[0] = (uint8_t)(lastpixel << 4); \
} \ } \
@@ -85,8 +85,8 @@ static int ThunderSetupDecode(TIFF *tif)
static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels) static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
{ {
static const char module[] = "ThunderDecode"; static const char module[] = "ThunderDecode";
register unsigned char *bp; unsigned char *bp;
register tmsize_t cc; tmsize_t cc;
unsigned int lastpixel; unsigned int lastpixel;
tmsize_t npixels; tmsize_t npixels;
uint8_t *op = op0; uint8_t *op = op0;
@@ -112,7 +112,7 @@ static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
break; break;
if (npixels & 1) if (npixels & 1)
{ {
op[0] |= lastpixel; op[0] |= (uint8_t)lastpixel;
lastpixel = *op++; lastpixel = *op++;
npixels++; npixels++;
n--; n--;
@@ -150,6 +150,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
case THUNDER_RAW: /* raw data */ case THUNDER_RAW: /* raw data */
SETPIXEL(op, n); SETPIXEL(op, n);
break; break;
default:
break;
} }
} }
tif->tif_rawcp = (uint8_t *)bp; tif->tif_rawcp = (uint8_t *)bp;
@@ -161,7 +163,7 @@ static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")", "%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")",
npixels < maxpixels ? "Not enough" : "Too much", npixels < maxpixels ? "Not enough" : "Too much",
(unsigned long)tif->tif_row, (uint64_t)npixels, (unsigned long)tif->tif_dir.td_row, (uint64_t)npixels,
(uint64_t)maxpixels); (uint64_t)maxpixels);
return (0); return (0);
} }
@@ -175,7 +177,7 @@ static int ThunderDecodeRow(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
uint8_t *row = buf; uint8_t *row = buf;
(void)s; (void)s;
if (occ % tif->tif_scanlinesize) if (occ % tif->tif_dir.td_scanlinesize)
{ {
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (0); return (0);
@@ -184,8 +186,8 @@ static int ThunderDecodeRow(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
{ {
if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth))
return (0); return (0);
occ -= tif->tif_scanlinesize; occ -= tif->tif_dir.td_scanlinesize;
row += tif->tif_scanlinesize; row += tif->tif_dir.td_scanlinesize;
} }
return (1); return (1);
} }

View File

@@ -54,12 +54,50 @@ uint32_t TIFFComputeTile(TIFF *tif, uint32_t x, uint32_t y, uint32_t z,
uint32_t xpt = TIFFhowmany_32(td->td_imagewidth, dx); uint32_t xpt = TIFFhowmany_32(td->td_imagewidth, dx);
uint32_t ypt = TIFFhowmany_32(td->td_imagelength, dy); uint32_t ypt = TIFFhowmany_32(td->td_imagelength, dy);
uint32_t zpt = TIFFhowmany_32(td->td_imagedepth, dz); uint32_t zpt = TIFFhowmany_32(td->td_imagedepth, dz);
uint32_t xpt_ypt = _TIFFMultiply32(tif, xpt, ypt, "TIFFComputeTile");
uint32_t xpt_ypt_zpt =
_TIFFMultiply32(tif, xpt_ypt, zpt, "TIFFComputeTile");
uint64_t z_offset;
uint64_t y_offset;
uint64_t tile64;
if ((xpt_ypt == 0 && xpt != 0 && ypt != 0) ||
(xpt_ypt_zpt == 0 && xpt_ypt != 0 && zpt != 0))
return (0);
z_offset = _TIFFMultiply64(tif, xpt_ypt, z / dz, "TIFFComputeTile");
y_offset = _TIFFMultiply64(tif, xpt, y / dy, "TIFFComputeTile");
if ((z_offset == 0 && xpt_ypt != 0 && (z / dz) != 0) ||
(y_offset == 0 && xpt != 0 && (y / dy) != 0))
return (0);
tile64 = _TIFFAdd64(tif, z_offset, y_offset, "TIFFComputeTile");
if (tile64 == 0 && (z_offset != 0 || y_offset != 0))
return (0);
tile64 = _TIFFAdd64(tif, tile64, x / dx, "TIFFComputeTile");
if (tile64 == 0 && (z_offset != 0 || y_offset != 0 || (x / dx) != 0))
return (0);
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
tile = (xpt * ypt * zpt) * s + (xpt * ypt) * (z / dz) + {
xpt * (y / dy) + x / dx; uint64_t sample_offset;
else if (s >= td->td_samplesperpixel)
tile = (xpt * ypt) * (z / dz) + xpt * (y / dy) + x / dx; {
TIFFErrorExtR(
tif, "TIFFComputeTile", "%lu: Sample out of range, max %lu",
(unsigned long)s, (unsigned long)td->td_samplesperpixel);
return (0);
}
sample_offset =
_TIFFMultiply64(tif, xpt_ypt_zpt, s, "TIFFComputeTile");
if (sample_offset == 0 && xpt_ypt_zpt != 0 && s != 0)
return (0);
tile64 = _TIFFAdd64(tif, sample_offset, tile64, "TIFFComputeTile");
if (tile64 == 0 && (sample_offset != 0 || z_offset != 0 ||
y_offset != 0 || (x / dx) != 0))
return (0);
}
tile = _TIFFCastUInt64ToUInt32(tif, tile64, "TIFFComputeTile");
if (tile == 0 && tile64 != 0)
return (0);
} }
return (tile); return (tile);
} }
@@ -187,54 +225,9 @@ tmsize_t TIFFTileRowSize(TIFF *tif)
*/ */
uint64_t TIFFVTileSize64(TIFF *tif, uint32_t nrows) uint64_t TIFFVTileSize64(TIFF *tif, uint32_t nrows)
{ {
static const char module[] = "TIFFVTileSize64"; return _TIFFStrileSize64(tif, nrows, /* isStrip = */ FALSE);
TIFFDirectory *td = &tif->tif_dir;
if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
td->td_tiledepth == 0)
return (0);
if ((td->td_planarconfig == PLANARCONFIG_CONTIG) &&
(td->td_photometric == PHOTOMETRIC_YCBCR) &&
(td->td_samplesperpixel == 3) && (!isUpSampled(tif)))
{
/*
* Packed YCbCr data contain one Cb+Cr for every
* HorizontalSampling*VerticalSampling Y values.
* Must also roundup width and height when calculating
* since images that are not a multiple of the
* horizontal/vertical subsampling area include
* YCbCr data for the extended image.
*/
uint16_t ycbcrsubsampling[2];
uint16_t samplingblock_samples;
uint32_t samplingblocks_hor;
uint32_t samplingblocks_ver;
uint64_t samplingrow_samples;
uint64_t samplingrow_size;
TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
ycbcrsubsampling + 0, ycbcrsubsampling + 1);
if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 &&
ycbcrsubsampling[0] != 4) ||
(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 &&
ycbcrsubsampling[1] != 4))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)",
ycbcrsubsampling[0], ycbcrsubsampling[1]);
return 0;
}
samplingblock_samples = ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2;
samplingblocks_hor =
TIFFhowmany_32(td->td_tilewidth, ycbcrsubsampling[0]);
samplingblocks_ver = TIFFhowmany_32(nrows, ycbcrsubsampling[1]);
samplingrow_samples = _TIFFMultiply64(tif, samplingblocks_hor,
samplingblock_samples, module);
samplingrow_size = TIFFhowmany8_64(_TIFFMultiply64(
tif, samplingrow_samples, td->td_bitspersample, module));
return (
_TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module));
}
else
return (_TIFFMultiply64(tif, nrows, TIFFTileRowSize64(tif), module));
} }
tmsize_t TIFFVTileSize(TIFF *tif, uint32_t nrows) tmsize_t TIFFVTileSize(TIFF *tif, uint32_t nrows)
{ {
static const char module[] = "TIFFVTileSize"; static const char module[] = "TIFFVTileSize";

View File

@@ -77,10 +77,10 @@ static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size)
return (tmsize_t)-1; return (tmsize_t)-1;
} }
fdh.h = fd; fdh.h = fd;
for (bytes_read = 0; bytes_read < bytes_total; bytes_read += count) for (bytes_read = 0; bytes_read < bytes_total; bytes_read += (size_t)count)
{ {
char *buf_offset = (char *)buf + bytes_read; char *buf_offset = (char *)buf + bytes_read;
size_t io_size = bytes_total - bytes_read; size_t io_size = (size_t)(bytes_total - bytes_read);
if (io_size > TIFF_IO_MAX) if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX; io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */ /* Below is an obvious false positive of Coverity Scan */
@@ -108,10 +108,11 @@ static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size)
return (tmsize_t)-1; return (tmsize_t)-1;
} }
fdh.h = fd; fdh.h = fd;
for (bytes_written = 0; bytes_written < bytes_total; bytes_written += count) for (bytes_written = 0; bytes_written < bytes_total;
bytes_written += (size_t)count)
{ {
const char *buf_offset = (char *)buf + bytes_written; const char *buf_offset = (char *)buf + bytes_written;
size_t io_size = bytes_total - bytes_written; size_t io_size = (size_t)(bytes_total - bytes_written);
if (io_size > TIFF_IO_MAX) if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX; io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */ /* Below is an obvious false positive of Coverity Scan */
@@ -174,7 +175,7 @@ static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize)
(void *)mmap(0, (size_t)sizem, PROT_READ, MAP_SHARED, fdh.fd, 0); (void *)mmap(0, (size_t)sizem, PROT_READ, MAP_SHARED, fdh.fd, 0);
if (*pbase != (void *)-1) if (*pbase != (void *)-1)
{ {
*psize = (tmsize_t)sizem; *psize = (toff_t)sizem;
return (1); return (1);
} }
} }
@@ -184,7 +185,7 @@ static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize)
static void _tiffUnmapProc(thandle_t fd, void *base, toff_t size) static void _tiffUnmapProc(thandle_t fd, void *base, toff_t size)
{ {
(void)fd; (void)fd;
(void)munmap(base, (off_t)size); (void)munmap(base, (size_t)size);
} }
#else /* !HAVE_MMAP */ #else /* !HAVE_MMAP */
static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize) static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize)
@@ -362,7 +363,8 @@ int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c)
return (memcmp(p1, p2, (size_t)c)); return (memcmp(p1, p2, (size_t)c));
} }
static void unixWarningHandler(const char *module, const char *fmt, va_list ap) static void TIFF_ATTRIBUTE((__format__(__printf__, 2, 0)))
unixWarningHandler(const char *module, const char *fmt, va_list ap)
{ {
if (module != NULL) if (module != NULL)
fprintf(stderr, "%s: ", module); fprintf(stderr, "%s: ", module);
@@ -372,7 +374,8 @@ static void unixWarningHandler(const char *module, const char *fmt, va_list ap)
} }
TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler; TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler;
static void unixErrorHandler(const char *module, const char *fmt, va_list ap) static void TIFF_ATTRIBUTE((__format__(__printf__, 2, 0)))
unixErrorHandler(const char *module, const char *fmt, va_list ap)
{ {
if (module != NULL) if (module != NULL)
fprintf(stderr, "%s: ", module); fprintf(stderr, "%s: ", module);

View File

@@ -84,15 +84,16 @@ static int TWebPDatasetWriter(const uint8_t *data, size_t data_size,
if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize) if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize)
{ {
TIFFErrorExtR( TIFFErrorExtR(tif, module,
tif, module, "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.", "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.",
(size_t)(tif->tif_rawcc + data_size - tif->tif_rawdatasize)); (size_t)((uint64_t)tif->tif_rawcc + (uint64_t)data_size -
(uint64_t)tif->tif_rawdatasize));
return 0; return 0;
} }
else else
{ {
_TIFFmemcpy(tif->tif_rawcp, data, data_size); _TIFFmemcpy(tif->tif_rawcp, data, (tmsize_t)data_size);
tif->tif_rawcc += data_size; tif->tif_rawcc += (tmsize_t)data_size;
tif->tif_rawcp += data_size; tif->tif_rawcp += data_size;
return 1; return 1;
} }
@@ -116,7 +117,7 @@ static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
return 0; return 0;
} }
memcpy(sp->pBuffer + sp->buffer_offset, bp, cc); memcpy(sp->pBuffer + sp->buffer_offset, bp, (size_t)cc);
sp->buffer_offset += (unsigned)cc; sp->buffer_offset += (unsigned)cc;
return 1; return 1;
@@ -141,7 +142,7 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to " "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error", "previous error",
tif->tif_row); tif->tif_dir.td_row);
return 0; return 0;
} }
@@ -158,7 +159,7 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
else else
{ {
segment_width = td->td_imagewidth; segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row; segment_height = td->td_imagelength - tif->tif_dir.td_row;
if (segment_height > td->td_rowsperstrip) if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip; segment_height = td->td_rowsperstrip;
} }
@@ -246,7 +247,7 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
sp->pBuffer = NULL; sp->pBuffer = NULL;
} }
sp->pBuffer = _TIFFmallocExt(tif, buffer_size); sp->pBuffer = (uint8_t *)_TIFFmallocExt(tif, buffer_size);
if (!sp->pBuffer) if (!sp->pBuffer)
{ {
TIFFErrorExtR(tif, module, "Cannot allocate buffer"); TIFFErrorExtR(tif, module, "Cannot allocate buffer");
@@ -262,10 +263,10 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
WebPInitDecBuffer(&sp->sDecBuffer); WebPInitDecBuffer(&sp->sDecBuffer);
sp->sDecBuffer.is_external_memory = 1; sp->sDecBuffer.is_external_memory = 1;
sp->sDecBuffer.width = segment_width; sp->sDecBuffer.width = (int)segment_width;
sp->sDecBuffer.height = segment_height; sp->sDecBuffer.height = (int)segment_height;
sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer; sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer;
sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; sp->sDecBuffer.u.RGBA.stride = (int)(segment_width * sp->nSamples);
sp->sDecBuffer.u.RGBA.size = buffer_size; sp->sDecBuffer.u.RGBA.size = buffer_size;
if (sp->nSamples > 3) if (sp->nSamples > 3)
@@ -298,7 +299,7 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
return 0; return 0;
} }
status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc); status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, (size_t)tif->tif_rawcc);
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
{ {
@@ -345,7 +346,7 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} }
else else
{ {
memcpy(op, buf + (sp->last_y * stride), occ); memcpy(op, buf + (sp->last_y * stride), (size_t)occ);
} }
tif->tif_rawcp += tif->tif_rawcc; tif->tif_rawcp += tif->tif_rawcc;
@@ -465,7 +466,7 @@ static int TWebPPreDecode(TIFF *tif, uint16_t s)
else else
{ {
segment_width = td->td_imagewidth; segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row; segment_height = td->td_imagelength - tif->tif_dir.td_row;
if (segment_height > td->td_rowsperstrip) if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip; segment_height = td->td_rowsperstrip;
} }
@@ -601,7 +602,7 @@ static int TWebPPreEncode(TIFF *tif, uint16_t s)
else else
{ {
segment_width = td->td_imagewidth; segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row; segment_height = td->td_imagelength - tif->tif_dir.td_row;
if (segment_height > td->td_rowsperstrip) if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip; segment_height = td->td_rowsperstrip;
} }
@@ -623,7 +624,7 @@ static int TWebPPreEncode(TIFF *tif, uint16_t s)
sp->pBuffer = NULL; sp->pBuffer = NULL;
} }
sp->pBuffer = _TIFFmallocExt(tif, sp->buffer_size); sp->pBuffer = (uint8_t *)_TIFFmallocExt(tif, sp->buffer_size);
if (!sp->pBuffer) if (!sp->pBuffer)
{ {
TIFFErrorExtR(tif, module, "Cannot allocate buffer"); TIFFErrorExtR(tif, module, "Cannot allocate buffer");
@@ -631,8 +632,8 @@ static int TWebPPreEncode(TIFF *tif, uint16_t s)
} }
sp->buffer_offset = 0; sp->buffer_offset = 0;
sp->sPicture.width = segment_width; sp->sPicture.width = (int)segment_width;
sp->sPicture.height = segment_height; sp->sPicture.height = (int)segment_height;
sp->sPicture.writer = TWebPDatasetWriter; sp->sPicture.writer = TWebPDatasetWriter;
sp->sPicture.custom_ptr = tif; sp->sPicture.custom_ptr = tif;
@@ -708,9 +709,11 @@ static int TWebPPostEncode(TIFF *tif)
case VP8_ENC_ERROR_USER_ABORT: case VP8_ENC_ERROR_USER_ABORT:
pszErrorMsg = "User interrupted"; pszErrorMsg = "User interrupted";
break; break;
case VP8_ENC_OK:
case VP8_ENC_ERROR_LAST:
default: default:
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"WebPEncode returned an unknown error code: %d", "WebPEncode returned an unknown error code: %u",
sp->sPicture.error_code); sp->sPicture.error_code);
pszErrorMsg = "Unknown WebP error type."; pszErrorMsg = "Unknown WebP error type.";
break; break;
@@ -776,7 +779,7 @@ static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap)
{ {
case TIFFTAG_WEBP_LEVEL: case TIFFTAG_WEBP_LEVEL:
sp->quality_level = (int)va_arg(ap, int); sp->quality_level = (int)va_arg(ap, int);
if (sp->quality_level <= 0 || sp->quality_level > 100.0f) if (sp->quality_level <= 0 || sp->quality_level > 100)
{ {
TIFFWarningExtR(tif, module, TIFFWarningExtR(tif, module,
"WEBP_LEVEL should be between 1 and 100"); "WEBP_LEVEL should be between 1 and 100");
@@ -844,6 +847,17 @@ static const TIFFField TWebPFields[] = {
FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless", NULL}, FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless", NULL},
}; };
static uint64_t TWebPGetMaxCompressionRatio(TIFF *tif)
{
/* See README_for_libtiff_developpers.md for raw data used to estimate
* the maximum compression rate. */
/* lossy compression: */
/* return (tif->tif_dir.td_samplesperpixel == 4) ? 2199 : 1685; */
/* lossless compression: */
return (tif->tif_dir.td_samplesperpixel == 4) ? 104194 : 78146;
}
int TIFFInitWebP(TIFF *tif, int scheme) int TIFFInitWebP(TIFF *tif, int scheme)
{ {
static const char module[] = "TIFFInitWebP"; static const char module[] = "TIFFInitWebP";
@@ -907,6 +921,7 @@ int TIFFInitWebP(TIFF *tif, int scheme)
tif->tif_encodestrip = TWebPEncode; tif->tif_encodestrip = TWebPEncode;
tif->tif_encodetile = TWebPEncode; tif->tif_encodetile = TWebPEncode;
tif->tif_cleanup = TWebPCleanup; tif->tif_cleanup = TWebPCleanup;
tif->tif_getmaxcompressionratio = TWebPGetMaxCompressionRatio;
return 1; return 1;
bad: bad:

View File

@@ -5,6 +5,7 @@
* Permission to use, copy, modify, distribute, and sell this software and * Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided * its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in * that (i) the above copyright notices and this permission notice appear in
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of * all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or * Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written * publicity relating to the software without the specific, prior written
@@ -72,7 +73,7 @@ static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size)
DWORD o; DWORD o;
tmsize_t p; tmsize_t p;
ma = (uint8_t *)buf; ma = (uint8_t *)buf;
mb = size; mb = (uint64_t)size;
p = 0; p = 0;
while (mb > 0) while (mb > 0)
{ {
@@ -101,7 +102,7 @@ static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size)
DWORD o; DWORD o;
tmsize_t p; tmsize_t p;
ma = (uint8_t *)buf; ma = (uint8_t *)buf;
mb = size; mb = (uint64_t)size;
p = 0; p = 0;
while (mb > 0) while (mb > 0)
{ {
@@ -123,7 +124,7 @@ static uint64_t _tiffSeekProc(thandle_t fd, uint64_t off, int whence)
{ {
LARGE_INTEGER offli; LARGE_INTEGER offli;
DWORD dwMoveMethod; DWORD dwMoveMethod;
offli.QuadPart = off; offli.QuadPart = (LONGLONG)off;
switch (whence) switch (whence)
{ {
case SEEK_SET: case SEEK_SET:
@@ -140,11 +141,11 @@ static uint64_t _tiffSeekProc(thandle_t fd, uint64_t off, int whence)
break; break;
} }
offli.LowPart = offli.LowPart =
SetFilePointer(fd, offli.LowPart, &offli.HighPart, dwMoveMethod); SetFilePointer(fd, (LONG)offli.LowPart, &offli.HighPart, dwMoveMethod);
if ((offli.LowPart == INVALID_SET_FILE_POINTER) && if ((offli.LowPart == INVALID_SET_FILE_POINTER) &&
(GetLastError() != NO_ERROR)) (GetLastError() != NO_ERROR))
offli.QuadPart = 0; offli.QuadPart = 0;
return (offli.QuadPart); return ((uint64_t)offli.QuadPart);
} }
static int _tiffCloseProc(thandle_t fd) { return (CloseHandle(fd) ? 0 : -1); } static int _tiffCloseProc(thandle_t fd) { return (CloseHandle(fd) ? 0 : -1); }
@@ -153,7 +154,7 @@ static uint64_t _tiffSizeProc(thandle_t fd)
{ {
LARGE_INTEGER m; LARGE_INTEGER m;
if (GetFileSizeEx(fd, &m)) if (GetFileSizeEx(fd, &m))
return (m.QuadPart); return ((uint64_t)m.QuadPart);
else else
return (0); return (0);
} }
@@ -343,7 +344,7 @@ TIFF *TIFFOpenWExt(const wchar_t *name, const char *mode, TIFFOpenOptions *opts)
NULL); NULL);
if (fd == INVALID_HANDLE_VALUE) if (fd == INVALID_HANDLE_VALUE)
{ {
_TIFFErrorEarly(opts, NULL, module, "%S: Cannot open", name); _TIFFErrorEarly(opts, NULL, module, "%ls: Cannot open", name);
return ((TIFF *)0); return ((TIFF *)0);
} }

View File

@@ -30,7 +30,7 @@
#include "tiffiop.h" #include "tiffiop.h"
#include <stdio.h> #include <stdio.h>
#define STRIPINCR 20 /* expansion factor on strip array */ #define NOSTRIP ((uint32_t)(-1)) /* undefined state */
#define WRITECHECKSTRIPS(tif, module) \ #define WRITECHECKSTRIPS(tif, module) \
(((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module)) (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module))
@@ -38,7 +38,7 @@
(((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module)) (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module))
#define BUFFERCHECK(tif) \ #define BUFFERCHECK(tif) \
((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \
TIFFWriteBufferSetup((tif), NULL, (tmsize_t)-1)) TIFFWriteBufferSetup((tif), NULL, (tmsize_t)(-1)))
static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module); static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module);
static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data, static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
@@ -47,7 +47,7 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample) int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
{ {
static const char module[] = "TIFFWriteScanline"; static const char module[] = "TIFFWriteScanline";
register TIFFDirectory *td; TIFFDirectory *td;
int status, imagegrew = 0; int status, imagegrew = 0;
uint32_t strip; uint32_t strip;
@@ -82,8 +82,16 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
/* /*
* Calculate strip and check for crossings. * Calculate strip and check for crossings.
*/ */
if (td->td_rowsperstrip == 0)
{
TIFFErrorExtR(tif, module,
"Cannot compute strip: RowsPerStrip is zero");
return (-1);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{ {
uint64_t sample_offset;
uint64_t strip64;
if (sample >= td->td_samplesperpixel) if (sample >= td->td_samplesperpixel)
{ {
TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu", TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
@@ -91,7 +99,18 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
(unsigned long)td->td_samplesperpixel); (unsigned long)td->td_samplesperpixel);
return (-1); return (-1);
} }
strip = sample * td->td_stripsperimage + row / td->td_rowsperstrip; sample_offset =
_TIFFMultiply64(tif, sample, td->td_stripsperimage, module);
if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
return (-1);
strip64 =
_TIFFAdd64(tif, sample_offset, row / td->td_rowsperstrip, module);
if (strip64 == 0 &&
(sample_offset != 0 || (row / td->td_rowsperstrip) != 0))
return (-1);
strip = _TIFFCastUInt64ToUInt32(tif, strip64, module);
if (strip == 0 && strip64 != 0)
return (-1);
} }
else else
strip = row / td->td_rowsperstrip; strip = row / td->td_rowsperstrip;
@@ -104,14 +123,14 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
*/ */
if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
return (-1); return (-1);
if (strip != tif->tif_curstrip) if (strip != tif->tif_dir.td_curstrip)
{ {
/* /*
* Changing strips -- flush any data present. * Changing strips -- flush any data present.
*/ */
if (!TIFFFlushData(tif)) if (!TIFFFlushData(tif))
return (-1); return (-1);
tif->tif_curstrip = strip; tif->tif_dir.td_curstrip = strip;
/* /*
* Watch out for a growing image. The value of strips/image * Watch out for a growing image. The value of strips/image
* will initially be 1 (since it can't be deduced until the * will initially be 1 (since it can't be deduced until the
@@ -125,7 +144,8 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
TIFFErrorExtR(tif, module, "Zero strips per image"); TIFFErrorExtR(tif, module, "Zero strips per image");
return (-1); return (-1);
} }
tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_dir.td_row =
(strip % td->td_stripsperimage) * td->td_rowsperstrip;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
{ {
if (!(*tif->tif_setupencode)(tif)) if (!(*tif->tif_setupencode)(tif))
@@ -148,35 +168,35 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
* beginning of a strip (or that we can randomly * beginning of a strip (or that we can randomly
* access the data -- i.e. no encoding). * access the data -- i.e. no encoding).
*/ */
if (row != tif->tif_row) if (row != tif->tif_dir.td_row)
{ {
if (row < tif->tif_row) if (row < tif->tif_dir.td_row)
{ {
/* /*
* Moving backwards within the same strip: * Moving backwards within the same strip:
* backup to the start and then decode * backup to the start and then decode
* forward (below). * forward (below).
*/ */
tif->tif_row = tif->tif_dir.td_row =
(strip % td->td_stripsperimage) * td->td_rowsperstrip; (strip % td->td_stripsperimage) * td->td_rowsperstrip;
tif->tif_rawcp = tif->tif_rawdata; tif->tif_rawcp = tif->tif_rawdata;
} }
/* /*
* Seek forward to the desired row. * Seek forward to the desired row.
*/ */
if (!(*tif->tif_seek)(tif, row - tif->tif_row)) if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
return (-1); return (-1);
tif->tif_row = row; tif->tif_dir.td_row = row;
} }
/* swab if needed - note that source buffer will be altered */ /* swab if needed - note that source buffer will be altered */
tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_scanlinesize); tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_dir.td_scanlinesize);
status = (*tif->tif_encoderow)(tif, (uint8_t *)buf, tif->tif_scanlinesize, status = (*tif->tif_encoderow)(tif, (uint8_t *)buf,
sample); tif->tif_dir.td_scanlinesize, sample);
/* we are now poised at the beginning of the next row */ /* we are now poised at the beginning of the next row */
tif->tif_row = row + 1; tif->tif_dir.td_row = row + 1;
return (status); return (status);
} }
@@ -188,7 +208,21 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile) static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
{ {
static const char module[] = "_TIFFReserveLargeEnoughWriteBuffer";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (td->td_stripbytecount_p == NULL)
{
TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
return 0;
}
if (strip_or_tile == NOSTRIP || strip_or_tile >= td->td_nstrips)
{
TIFFErrorExtR(tif, module, "Strip/tile number not valid");
return 0;
}
if (td->td_stripbytecount_p[strip_or_tile] > 0) if (td->td_stripbytecount_p[strip_or_tile] > 0)
{ {
/* The +1 is to ensure at least one extra bytes */ /* The +1 is to ensure at least one extra bytes */
@@ -254,7 +288,7 @@ tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curstrip = strip; tif->tif_dir.td_curstrip = strip;
/* this informs TIFFAppendToStrip() we have changed or reset strip */ /* this informs TIFFAppendToStrip() we have changed or reset strip */
tif->tif_curoff = 0; tif->tif_curoff = 0;
@@ -273,7 +307,7 @@ tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
return ((tmsize_t)-1); return ((tmsize_t)-1);
} }
tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
{ {
if (!(*tif->tif_setupencode)(tif)) if (!(*tif->tif_setupencode)(tif))
@@ -362,9 +396,9 @@ tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
return ((tmsize_t)-1); return ((tmsize_t)-1);
} }
if (tif->tif_curstrip != strip) if (tif->tif_dir.td_curstrip != strip)
{ {
tif->tif_curstrip = strip; tif->tif_dir.td_curstrip = strip;
/* this informs TIFFAppendToStrip() we have changed or reset strip */ /* this informs TIFFAppendToStrip() we have changed or reset strip */
tif->tif_curoff = 0; tif->tif_curoff = 0;
@@ -375,7 +409,7 @@ tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
TIFFErrorExtR(tif, module, "Zero strips per image"); TIFFErrorExtR(tif, module, "Zero strips per image");
return ((tmsize_t)-1); return ((tmsize_t)-1);
} }
tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
: (tmsize_t)-1); : (tmsize_t)-1);
} }
@@ -437,7 +471,7 @@ tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curtile = tile; tif->tif_dir.td_curtile = tile;
/* this informs TIFFAppendToStrip() we have changed or reset tile */ /* this informs TIFFAppendToStrip() we have changed or reset tile */
tif->tif_curoff = 0; tif->tif_curoff = 0;
@@ -460,14 +494,14 @@ tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
TIFFErrorExtR(tif, module, "Zero tiles"); TIFFErrorExtR(tif, module, "Zero tiles");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
tif->tif_row = (tile % howmany32) * td->td_tilelength; tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
if (howmany32 == 0) if (howmany32 == 0)
{ {
TIFFErrorExtR(tif, module, "Zero tiles"); TIFFErrorExtR(tif, module, "Zero tiles");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
tif->tif_col = (tile % howmany32) * td->td_tilewidth; tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
{ {
@@ -482,8 +516,8 @@ tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
* done so that callers can pass in some large number * done so that callers can pass in some large number
* (e.g. -1) and have the tile size used instead. * (e.g. -1) and have the tile size used instead.
*/ */
if (cc < 1 || cc > tif->tif_tilesize) if (cc < 1 || cc > tif->tif_dir.td_tilesize)
cc = tif->tif_tilesize; cc = tif->tif_dir.td_tilesize;
/* shortcut to avoid an extra memcpy() */ /* shortcut to avoid an extra memcpy() */
if (td->td_compression == COMPRESSION_NONE) if (td->td_compression == COMPRESSION_NONE)
@@ -588,8 +622,10 @@ int TIFFSetupStrips(TIFF *tif)
* Place data at the end-of-file * Place data at the end-of-file
* (by setting offsets to zero). * (by setting offsets to zero).
*/ */
_TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips * sizeof(uint64_t)); _TIFFmemset(td->td_stripoffset_p, 0,
_TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips * sizeof(uint64_t)); (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
_TIFFmemset(td->td_stripbytecount_p, 0,
(tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
return (1); return (1);
@@ -644,14 +680,14 @@ int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
} }
if (isTiled(tif)) if (isTiled(tif))
{ {
tif->tif_tilesize = TIFFTileSize(tif); tif->tif_dir.td_tilesize = TIFFTileSize(tif);
if (tif->tif_tilesize == 0) if (tif->tif_dir.td_tilesize == 0)
return (0); return (0);
} }
else else
tif->tif_tilesize = (tmsize_t)(-1); tif->tif_dir.td_tilesize = (tmsize_t)(-1);
tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
if (tif->tif_scanlinesize == 0) if (tif->tif_dir.td_scanlinesize == 0)
return (0); return (0);
tif->tif_flags |= TIFF_BEENWRITING; tif->tif_flags |= TIFF_BEENWRITING;
@@ -689,7 +725,7 @@ int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
} }
if (size == (tmsize_t)(-1)) if (size == (tmsize_t)(-1))
{ {
size = (isTiled(tif) ? tif->tif_tilesize : TIFFStripSize(tif)); size = (isTiled(tif) ? tif->tif_dir.td_tilesize : TIFFStripSize(tif));
/* Adds 10% margin for cases where compression would expand a bit */ /* Adds 10% margin for cases where compression would expand a bit */
if (size < TIFF_TMSIZE_T_MAX - size / 10) if (size < TIFF_TMSIZE_T_MAX - size / 10)
@@ -732,26 +768,31 @@ static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
assert(td->td_planarconfig == PLANARCONFIG_CONTIG); assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
new_stripoffset = (uint64_t *)_TIFFreallocExt( new_stripoffset = (uint64_t *)_TIFFreallocExt(
tif, td->td_stripoffset_p, (td->td_nstrips + delta) * sizeof(uint64_t)); tif, td->td_stripoffset_p,
(tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
sizeof(uint64_t)));
/*
* Update td_stripoffset_p immediately so the old pointer is not left
* dangling if the second realloc fails.
*/
if (new_stripoffset)
td->td_stripoffset_p = new_stripoffset;
new_stripbytecount = (uint64_t *)_TIFFreallocExt( new_stripbytecount = (uint64_t *)_TIFFreallocExt(
tif, td->td_stripbytecount_p, tif, td->td_stripbytecount_p,
(td->td_nstrips + delta) * sizeof(uint64_t)); (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
sizeof(uint64_t)));
if (new_stripbytecount)
td->td_stripbytecount_p = new_stripbytecount;
if (new_stripoffset == NULL || new_stripbytecount == NULL) if (new_stripoffset == NULL || new_stripbytecount == NULL)
{ {
if (new_stripoffset)
_TIFFfreeExt(tif, new_stripoffset);
if (new_stripbytecount)
_TIFFfreeExt(tif, new_stripbytecount);
td->td_nstrips = 0; td->td_nstrips = 0;
TIFFErrorExtR(tif, module, "No space to expand strip arrays"); TIFFErrorExtR(tif, module, "No space to expand strip arrays");
return (0); return (0);
} }
td->td_stripoffset_p = new_stripoffset;
td->td_stripbytecount_p = new_stripbytecount;
_TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0, _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
delta * sizeof(uint64_t)); (tmsize_t)((size_t)delta * sizeof(uint64_t)));
_TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0, _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
delta * sizeof(uint64_t)); (tmsize_t)((size_t)delta * sizeof(uint64_t)));
td->td_nstrips += delta; td->td_nstrips += delta;
tif->tif_flags |= TIFF_DIRTYDIRECT; tif->tif_flags |= TIFF_DIRTYDIRECT;
@@ -769,6 +810,23 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
uint64_t m; uint64_t m;
int64_t old_byte_count = -1; int64_t old_byte_count = -1;
/* Some security checks */
if (td->td_stripoffset_p == NULL)
{
TIFFErrorExtR(tif, module, "Strip offset array pointer is NULL");
return (0);
}
if (td->td_stripbytecount_p == NULL)
{
TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
return (0);
}
if (strip == NOSTRIP)
{
TIFFErrorExtR(tif, module, "Strip number not valid (NOSTRIP)");
return (0);
}
if (tif->tif_curoff == 0) if (tif->tif_curoff == 0)
tif->tif_lastvalidoff = 0; tif->tif_lastvalidoff = 0;
@@ -790,7 +848,7 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
if (!SeekOK(tif, td->td_stripoffset_p[strip])) if (!SeekOK(tif, td->td_stripoffset_p[strip]))
{ {
TIFFErrorExtR(tif, module, "Seek error at scanline %lu", TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
return (0); return (0);
} }
@@ -812,11 +870,11 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
/* /*
* We are starting a fresh strip/tile, so set the size to zero. * We are starting a fresh strip/tile, so set the size to zero.
*/ */
old_byte_count = td->td_stripbytecount_p[strip]; old_byte_count = (int64_t)td->td_stripbytecount_p[strip];
td->td_stripbytecount_p[strip] = 0; td->td_stripbytecount_p[strip] = 0;
} }
m = tif->tif_curoff + cc; m = tif->tif_curoff + (uint64_t)cc;
if (!(tif->tif_flags & TIFF_BIGTIFF)) if (!(tif->tif_flags & TIFF_BIGTIFF))
m = (uint32_t)m; m = (uint32_t)m;
if ((m < tif->tif_curoff) || (m < (uint64_t)cc)) if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
@@ -850,7 +908,7 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
offsetRead = td->td_stripoffset_p[strip]; offsetRead = td->td_stripoffset_p[strip];
offsetWrite = TIFFSeekFile(tif, 0, SEEK_END); offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
m = offsetWrite + toCopy + cc; m = offsetWrite + (uint64_t)toCopy + (uint64_t)cc;
if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m) if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
{ {
TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded"); TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
@@ -872,13 +930,15 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
/* Move data written by previous calls to us at end of file */ /* Move data written by previous calls to us at end of file */
while (toCopy > 0) while (toCopy > 0)
{ {
tmsize_t chunkSize =
toCopy < (uint64_t)tempSize ? (tmsize_t)toCopy : tempSize;
if (!SeekOK(tif, offsetRead)) if (!SeekOK(tif, offsetRead))
{ {
TIFFErrorExtR(tif, module, "Seek error"); TIFFErrorExtR(tif, module, "Seek error");
_TIFFfreeExt(tif, temp); _TIFFfreeExt(tif, temp);
return (0); return (0);
} }
if (!ReadOK(tif, temp, tempSize)) if (!ReadOK(tif, temp, chunkSize))
{ {
TIFFErrorExtR(tif, module, "Cannot read"); TIFFErrorExtR(tif, module, "Cannot read");
_TIFFfreeExt(tif, temp); _TIFFfreeExt(tif, temp);
@@ -890,32 +950,32 @@ static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
_TIFFfreeExt(tif, temp); _TIFFfreeExt(tif, temp);
return (0); return (0);
} }
if (!WriteOK(tif, temp, tempSize)) if (!WriteOK(tif, temp, chunkSize))
{ {
TIFFErrorExtR(tif, module, "Cannot write"); TIFFErrorExtR(tif, module, "Cannot write");
_TIFFfreeExt(tif, temp); _TIFFfreeExt(tif, temp);
return (0); return (0);
} }
offsetRead += tempSize; offsetRead += (uint64_t)chunkSize;
offsetWrite += tempSize; offsetWrite += (uint64_t)chunkSize;
td->td_stripbytecount_p[strip] += tempSize; td->td_stripbytecount_p[strip] += (uint64_t)chunkSize;
toCopy -= tempSize; toCopy -= (uint64_t)chunkSize;
} }
_TIFFfreeExt(tif, temp); _TIFFfreeExt(tif, temp);
/* Append the data of this call */ /* Append the data of this call */
offsetWrite += cc; offsetWrite += (uint64_t)cc;
m = offsetWrite; m = offsetWrite;
} }
if (!WriteOK(tif, data, cc)) if (!WriteOK(tif, data, cc))
{ {
TIFFErrorExtR(tif, module, "Write error at scanline %lu", TIFFErrorExtR(tif, module, "Write error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
return (0); return (0);
} }
tif->tif_curoff = m; tif->tif_curoff = m;
td->td_stripbytecount_p[strip] += cc; td->td_stripbytecount_p[strip] += (uint64_t)cc;
if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count) if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
tif->tif_flags |= TIFF_DIRTYSTRIP; tif->tif_flags |= TIFF_DIRTYSTRIP;
@@ -935,9 +995,10 @@ int TIFFFlushData1(TIFF *tif)
if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc); TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
if (!TIFFAppendToStrip( if (!TIFFAppendToStrip(tif,
tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, isTiled(tif) ? tif->tif_dir.td_curtile
tif->tif_rawdata, tif->tif_rawcc)) : tif->tif_dir.td_curstrip,
tif->tif_rawdata, tif->tif_rawcc))
{ {
/* We update those variables even in case of error since there's */ /* We update those variables even in case of error since there's */
/* code that doesn't really check the return code of this */ /* code that doesn't really check the return code of this */

View File

@@ -159,7 +159,8 @@ static int ZIPPreDecode(TIFF *tif, uint16_t s)
we need to simplify this code to reflect a ZLib that is likely updated we need to simplify this code to reflect a ZLib that is likely updated
to deal with 8byte memory sizes, though this code will respond to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = TIFF_CLAMP_UINT64_TO_INT32_MAX(tif->tif_rawcc); sp->stream.avail_in =
TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawcc);
if (inflateReset(&sp->stream) == Z_OK) if (inflateReset(&sp->stream) == Z_OK)
{ {
sp->read_error = 0; sp->read_error = 0;
@@ -183,7 +184,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to " "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error", "previous error",
tif->tif_row); tif->tif_dir.td_row);
return 0; return 0;
} }
@@ -210,7 +211,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} }
else else
{ {
uint32_t strip_height = td->td_imagelength - tif->tif_row; uint32_t strip_height = td->td_imagelength - tif->tif_dir.td_row;
if (strip_height > td->td_rowsperstrip) if (strip_height > td->td_rowsperstrip)
strip_height = td->td_rowsperstrip; strip_height = td->td_rowsperstrip;
if (TIFFVStripSize64(tif, strip_height) != (uint64_t)occ) if (TIFFVStripSize64(tif, strip_height) != (uint64_t)occ)
@@ -254,7 +255,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{ {
memset(op, 0, (size_t)occ); memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu", TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
sp->read_error = 1; sp->read_error = 1;
return 0; return 0;
} }
@@ -275,8 +276,9 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
do do
{ {
int state; int state;
uInt avail_in_before = TIFF_CLAMP_UINT64_TO_INT32_MAX(tif->tif_rawcc); uInt avail_in_before =
uInt avail_out_before = TIFF_CLAMP_UINT64_TO_INT32_MAX(occ); TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawcc);
uInt avail_out_before = TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)occ);
sp->stream.avail_in = avail_in_before; sp->stream.avail_in = avail_in_before;
sp->stream.avail_out = avail_out_before; sp->stream.avail_out = avail_out_before;
state = inflate(&sp->stream, Z_PARTIAL_FLUSH); state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
@@ -288,7 +290,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{ {
memset(sp->stream.next_out, 0, (size_t)occ); memset(sp->stream.next_out, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s", TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s",
(unsigned long)tif->tif_row, SAFE_MSG(sp)); (unsigned long)tif->tif_dir.td_row, SAFE_MSG(sp));
sp->read_error = 1; sp->read_error = 1;
return (0); return (0);
} }
@@ -305,7 +307,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %lu (short %" PRIu64 "Not enough data at scanline %lu (short %" PRIu64
" bytes)", " bytes)",
(unsigned long)tif->tif_row, (uint64_t)occ); (unsigned long)tif->tif_dir.td_row, (uint64_t)occ);
memset(sp->stream.next_out, 0, (size_t)occ); memset(sp->stream.next_out, 0, (size_t)occ);
sp->read_error = 1; sp->read_error = 1;
return (0); return (0);
@@ -411,7 +413,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
} }
else else
{ {
uint32_t strip_height = td->td_imagelength - tif->tif_row; uint32_t strip_height = td->td_imagelength - tif->tif_dir.td_row;
if (strip_height > td->td_rowsperstrip) if (strip_height > td->td_rowsperstrip)
strip_height = td->td_rowsperstrip; strip_height = td->td_rowsperstrip;
if (TIFFVStripSize64(tif, strip_height) != (uint64_t)cc) if (TIFFVStripSize64(tif, strip_height) != (uint64_t)cc)
@@ -463,11 +465,11 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
if (nCompressedBytes == 0) if (nCompressedBytes == 0)
{ {
TIFFErrorExtR(tif, module, "Encoder error at scanline %lu", TIFFErrorExtR(tif, module, "Encoder error at scanline %lu",
(unsigned long)tif->tif_row); (unsigned long)tif->tif_dir.td_row);
return 0; return 0;
} }
tif->tif_rawcc = nCompressedBytes; tif->tif_rawcc = (tmsize_t)nCompressedBytes;
if (!TIFFFlushData1(tif)) if (!TIFFFlushData1(tif))
return 0; return 0;
@@ -485,7 +487,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
appropriately even before we simplify it */ appropriately even before we simplify it */
do do
{ {
uInt avail_in_before = TIFF_CLAMP_UINT64_TO_INT32_MAX(cc); uInt avail_in_before = TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)cc);
sp->stream.avail_in = avail_in_before; sp->stream.avail_in = avail_in_before;
if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
{ {
@@ -499,7 +501,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
return 0; return 0;
sp->stream.next_out = tif->tif_rawdata; sp->stream.next_out = tif->tif_rawdata;
sp->stream.avail_out = sp->stream.avail_out =
TIFF_CLAMP_UINT64_TO_INT32_MAX(tif->tif_rawdatasize); TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawdatasize);
} }
cc -= (avail_in_before - sp->stream.avail_in); cc -= (avail_in_before - sp->stream.avail_in);
} while (cc > 0); } while (cc > 0);
@@ -682,7 +684,7 @@ static const TIFFField zipFields[] = {
static void *TIFF_zalloc(void *opaque, unsigned int items, unsigned int size) static void *TIFF_zalloc(void *opaque, unsigned int items, unsigned int size)
{ {
static const char module[] = "TIFF_zalloc"; static const char module[] = "TIFF_zalloc";
TIFF *tif = opaque; TIFF *tif = (TIFF *)opaque;
if (items > ~(size_t)0 / size) if (items > ~(size_t)0 / size)
{ {
@@ -698,6 +700,13 @@ static void TIFF_zfree(void *opaque, void *ptr)
_TIFFfreeExt((TIFF *)opaque, ptr); _TIFFfreeExt((TIFF *)opaque, ptr);
} }
static uint64_t ZIPGetMaxCompressionRatio(TIFF *tif)
{
(void)tif;
/* cf https://zlib.net/zlib_tech.html */
return 1032;
}
int TIFFInitZIP(TIFF *tif, int scheme) int TIFFInitZIP(TIFF *tif, int scheme)
{ {
static const char module[] = "TIFFInitZIP"; static const char module[] = "TIFFInitZIP";
@@ -764,6 +773,7 @@ int TIFFInitZIP(TIFF *tif, int scheme)
tif->tif_encodestrip = ZIPEncode; tif->tif_encodestrip = ZIPEncode;
tif->tif_encodetile = ZIPEncode; tif->tif_encodetile = ZIPEncode;
tif->tif_cleanup = ZIPCleanup; tif->tif_cleanup = ZIPCleanup;
tif->tif_getmaxcompressionratio = ZIPGetMaxCompressionRatio;
/* /*
* Setup predictor setup. * Setup predictor setup.
*/ */

View File

@@ -159,13 +159,13 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos); memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos);
TIFFErrorExtR(tif, module, TIFFErrorExtR(tif, module,
"Not enough data at scanline %lu (short %lu bytes)", "Not enough data at scanline %lu (short %lu bytes)",
(unsigned long)tif->tif_row, (unsigned long)tif->tif_dir.td_row,
(unsigned long)((size_t)occ - out_buffer.pos)); (unsigned long)((size_t)occ - out_buffer.pos));
return 0; return 0;
} }
tif->tif_rawcp += in_buffer.pos; tif->tif_rawcp += in_buffer.pos;
tif->tif_rawcc -= in_buffer.pos; tif->tif_rawcc -= (tmsize_t)in_buffer.pos;
return 1; return 1;
} }
@@ -287,7 +287,7 @@ static int ZSTDPostEncode(TIFF *tif)
} }
if (sp->out_buffer.pos > 0) if (sp->out_buffer.pos > 0)
{ {
tif->tif_rawcc = sp->out_buffer.pos; tif->tif_rawcc = (tmsize_t)sp->out_buffer.pos;
if (!TIFFFlushData1(tif)) if (!TIFFFlushData1(tif))
return 0; return 0;
sp->out_buffer.dst = tif->tif_rawcp; sp->out_buffer.dst = tif->tif_rawcp;

View File

@@ -125,13 +125,13 @@ typedef void *thandle_t; /* client data handle */
*/ */
/* reference white */ /* reference white */
#define D65_X0 (95.0470F) #define D65_X0 (95.0470f)
#define D65_Y0 (100.0F) #define D65_Y0 (100.0f)
#define D65_Z0 (108.8827F) #define D65_Z0 (108.8827f)
#define D50_X0 (96.4250F) #define D50_X0 (96.4250f)
#define D50_Y0 (100.0F) #define D50_Y0 (100.0f)
#define D50_Z0 (82.4680F) #define D50_Z0 (82.4680f)
/* Structure for holding information about a display device. */ /* Structure for holding information about a display device. */
@@ -254,7 +254,7 @@ struct _TIFFRGBAImage
* Macros for extracting components from the * Macros for extracting components from the
* packed ABGR form returned by TIFFReadRGBAImage. * packed ABGR form returned by TIFFReadRGBAImage.
*/ */
#define TIFFGetR(abgr) ((abgr)&0xff) #define TIFFGetR(abgr) ((abgr) & 0xff)
#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) #define TIFFGetG(abgr) (((abgr) >> 8) & 0xff)
#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) #define TIFFGetB(abgr) (((abgr) >> 16) & 0xff)
#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) #define TIFFGetA(abgr) (((abgr) >> 24) & 0xff)
@@ -269,7 +269,7 @@ struct _TIFFRGBAImage
typedef int (*TIFFInitMethod)(TIFF *, int); typedef int (*TIFFInitMethod)(TIFF *, int);
typedef struct typedef struct
{ {
char *name; const char *name;
uint16_t scheme; uint16_t scheme;
TIFFInitMethod init; TIFFInitMethod init;
} TIFFCodec; } TIFFCodec;
@@ -584,6 +584,7 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
tmsize_t cc); tmsize_t cc);
extern tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, extern tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data,
tmsize_t cc); tmsize_t cc);
extern uint64_t TIFFGetMaxCompressionRatio(TIFF *tif);
extern int TIFFDataWidth( extern int TIFFDataWidth(
TIFFDataType); /* table of tag datatype widths within TIFF file. */ TIFFDataType); /* table of tag datatype widths within TIFF file. */
extern void TIFFSetWriteOffset(TIFF *tif, toff_t off); extern void TIFFSetWriteOffset(TIFF *tif, toff_t off);
@@ -659,7 +660,7 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
unsigned short field_bit; /* bit in fieldsset bit vector */ unsigned short field_bit; /* bit in fieldsset bit vector */
unsigned char field_oktochange; /* if true, can change while writing */ unsigned char field_oktochange; /* if true, can change while writing */
unsigned char field_passcount; /* if true, pass dir count on set */ unsigned char field_passcount; /* if true, pass dir count on set */
char *field_name; /* ASCII name */ const char *field_name; /* ASCII name */
} TIFFFieldInfo; } TIFFFieldInfo;
extern int TIFFMergeFieldInfo(TIFF *, const TIFFFieldInfo[], uint32_t); extern int TIFFMergeFieldInfo(TIFF *, const TIFFFieldInfo[], uint32_t);

View File

@@ -38,6 +38,7 @@
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#include <math.h>
#include <string.h> #include <string.h>
#ifdef HAVE_ASSERT_H #ifdef HAVE_ASSERT_H
@@ -94,6 +95,7 @@ typedef int (*TIFFSeekMethod)(TIFF *, uint32_t);
typedef void (*TIFFPostMethod)(TIFF *tif, uint8_t *buf, tmsize_t size); typedef void (*TIFFPostMethod)(TIFF *tif, uint8_t *buf, tmsize_t size);
typedef uint32_t (*TIFFStripMethod)(TIFF *, uint32_t); typedef uint32_t (*TIFFStripMethod)(TIFF *, uint32_t);
typedef void (*TIFFTileMethod)(TIFF *, uint32_t *, uint32_t *); typedef void (*TIFFTileMethod)(TIFF *, uint32_t *, uint32_t *);
typedef uint64_t (*TIFFGetMaxCompressionRatioMethod)(TIFF *);
struct TIFFOffsetAndDirNumber struct TIFFOffsetAndDirNumber
{ {
@@ -143,13 +145,18 @@ struct tiff
0x800000U /* read buffer (tif_rawdata) points into mmap() memory */ 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */
#define TIFF_DEFERSTRILELOAD \ #define TIFF_DEFERSTRILELOAD \
0x1000000U /* defer strip/tile offset/bytecount array loading. */ 0x1000000U /* defer strip/tile offset/bytecount array loading. */
#define TIFF_LAZYSTRILELOAD \ #define TIFF_LAZYSTRILELOAD_DONE \
0x2000000U /* lazy/ondemand loading of strip/tile offset/bytecount values. \ 0x2000000U /* set when lazy/ondemand loading of strip/tile \
Only used if TIFF_DEFERSTRILELOAD is set and in read-only \ offset/bytecount values has been done. Only used if \
mode */ TIFF_DEFERSTRILELOAD is set and in read-only mode */
#define TIFF_CHOPPEDUPARRAYS \ #define TIFF_CHOPPEDUPARRAYS \
0x4000000U /* set when allocChoppedUpStripArrays() has modified strip \ 0x4000000U /* set when allocChoppedUpStripArrays() has modified strip \
array */ array */
#define TIFF_LAZYSTRILELOAD_ASKED \
0x8000000U /* set when lazy/ondemand loading of strip/tile \
offset/bytecount values has been requested on opening ('O' \
flag) */
uint64_t tif_diroff; /* file offset of current directory */ uint64_t tif_diroff; /* file offset of current directory */
uint64_t tif_nextdiroff; /* file offset of following directory */ uint64_t tif_nextdiroff; /* file offset of following directory */
uint64_t tif_lastdiroff; /* file offset of last directory written so far */ uint64_t tif_lastdiroff; /* file offset of last directory written so far */
@@ -162,7 +169,6 @@ struct tiff
tif_customdir; /* custom IFDs are separated from the main ones */ tif_customdir; /* custom IFDs are separated from the main ones */
TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */ TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */
uint16_t tif_header_size; /* file's header block and its length */ 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, /* There are IFDs in the file and an "active" IFD in memory,
* from which fields are "set" and "get". * from which fields are "set" and "get".
@@ -184,7 +190,6 @@ struct tiff
* - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'. * - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'.
* - 0 means 'empty file opened for writing, but no IFD written yet' */ * - 0 means 'empty file opened for writing, but no IFD written yet' */
tdir_t tif_curdircount; 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_curoff; /* current offset for read/write */
uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in
place. Used only by TIFFAppendToStrip() */ place. Used only by TIFFAppendToStrip() */
@@ -192,10 +197,6 @@ struct tiff
/* SubIFD support */ /* SubIFD support */
uint16_t tif_nsubifd; /* remaining subifds to write */ uint16_t tif_nsubifd; /* remaining subifds to write */
uint64_t tif_subifdoff; /* offset for patching SubIFD link */ uint64_t tif_subifdoff; /* offset for patching SubIFD link */
/* tiling support */
uint32_t tif_col; /* current column (offset by row too) */
uint32_t tif_curtile; /* current tile for read/write */
tmsize_t tif_tilesize; /* # of bytes in a tile */
/* compression scheme hooks */ /* compression scheme hooks */
int tif_decodestatus; int tif_decodestatus;
TIFFBoolMethod tif_fixuptags; /* called in TIFFReadDirectory */ TIFFBoolMethod tif_fixuptags; /* called in TIFFReadDirectory */
@@ -216,10 +217,10 @@ struct tiff
TIFFVoidMethod tif_cleanup; /* cleanup state routine */ TIFFVoidMethod tif_cleanup; /* cleanup state routine */
TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */ TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */
TIFFTileMethod tif_deftilesize; /* calculate/constrain tile size */ TIFFTileMethod tif_deftilesize; /* calculate/constrain tile size */
uint8_t *tif_data; /* compression scheme private data */ /* returns maximum compression ratio for current compression method */
TIFFGetMaxCompressionRatioMethod tif_getmaxcompressionratio;
uint8_t *tif_data; /* compression scheme private data */
/* input/output buffering */ /* input/output buffering */
tmsize_t tif_scanlinesize; /* # of bytes in a scanline */
tmsize_t tif_scanlineskew; /* scanline skew for reading strips */
uint8_t *tif_rawdata; /* raw data buffer */ uint8_t *tif_rawdata; /* raw data buffer */
tmsize_t tif_rawdatasize; /* # of bytes in raw data buffer */ tmsize_t tif_rawdatasize; /* # of bytes in raw data buffer */
tmsize_t tif_rawdataoff; /* rawdata offset within strip */ tmsize_t tif_rawdataoff; /* rawdata offset within strip */
@@ -295,13 +296,15 @@ struct TIFFOpenOptions
* Default Read/Seek/Write definitions. * Default Read/Seek/Write definitions.
*/ */
#ifndef ReadOK #ifndef ReadOK
#define ReadOK(tif, buf, size) (TIFFReadFile((tif), (buf), (size)) == (size)) #define ReadOK(tif, buf, size) \
(TIFFReadFile((tif), (buf), (size)) == (tmsize_t)(size))
#endif #endif
#ifndef SeekOK #ifndef SeekOK
#define SeekOK(tif, off) _TIFFSeekOK(tif, off) #define SeekOK(tif, off) _TIFFSeekOK(tif, off)
#endif #endif
#ifndef WriteOK #ifndef WriteOK
#define WriteOK(tif, buf, size) (TIFFWriteFile((tif), (buf), (size)) == (size)) #define WriteOK(tif, buf, size) \
(TIFFWriteFile((tif), (buf), (size)) == (tmsize_t)(size))
#endif #endif
/* NB: the uint32_t casts are to silence certain ANSI-C compilers */ /* NB: the uint32_t casts are to silence certain ANSI-C compilers */
@@ -315,19 +318,19 @@ struct TIFFOpenOptions
(((uint32_t)(x) / (uint32_t)(y)) + \ (((uint32_t)(x) / (uint32_t)(y)) + \
((((uint32_t)(x) % (uint32_t)(y)) != 0) ? 1 : 0)) ((((uint32_t)(x) % (uint32_t)(y)) != 0) ? 1 : 0))
#define TIFFhowmany8_32(x) \ #define TIFFhowmany8_32(x) \
(((x)&0x07) ? ((uint32_t)(x) >> 3) + 1 : (uint32_t)(x) >> 3) (((x) & 0x07) ? ((uint32_t)(x) >> 3) + 1 : (uint32_t)(x) >> 3)
#define TIFFroundup_32(x, y) (TIFFhowmany_32(x, y) * (y)) #define TIFFroundup_32(x, y) ((uint32_t)(TIFFhowmany_32(x, y) * (uint32_t)(y)))
#define TIFFhowmany_64(x, y) \ #define TIFFhowmany_64(x, y) \
((((uint64_t)(x)) + (((uint64_t)(y)) - 1)) / ((uint64_t)(y))) ((((uint64_t)(x)) + (((uint64_t)(y)) - 1)) / ((uint64_t)(y)))
#define TIFFhowmany8_64(x) \ #define TIFFhowmany8_64(x) \
(((x)&0x07) ? ((uint64_t)(x) >> 3) + 1 : (uint64_t)(x) >> 3) (((x) & 0x07) ? ((uint64_t)(x) >> 3) + 1 : (uint64_t)(x) >> 3)
#define TIFFroundup_64(x, y) (TIFFhowmany_64(x, y) * (y)) #define TIFFroundup_64(x, y) ((uint64_t)(TIFFhowmany_64(x, y) * (uint64_t)(y)))
/* Safe multiply which returns zero if there is an *unsigned* integer overflow. /* Safe multiply which returns zero if there is an *unsigned* integer overflow.
* This macro is not safe for *signed* integer types */ * This macro is not safe for *signed* integer types */
#define TIFFSafeMultiply(t, v, m) \ #define TIFFSafeMultiply(t, v, m) \
((((t)(m) != (t)0) && (((t)(((v) * (m)) / (m))) == (t)(v))) \ ((((t)(m) != (t)0) && (((t)((((t)(v)) * ((t)(m))) / ((t)(m)))) == (t)(v))) \
? (t)((v) * (m)) \ ? (t)(((t)(v)) * ((t)(m))) \
: (t)0) : (t)0)
#define TIFFmax(A, B) ((A) > (B) ? (A) : (B)) #define TIFFmax(A, B) ((A) > (B) ? (A) : (B))
@@ -335,6 +338,10 @@ struct TIFFOpenOptions
#define TIFFArrayCount(a) (sizeof(a) / sizeof((a)[0])) #define TIFFArrayCount(a) (sizeof(a) / sizeof((a)[0]))
/* Float/double equality macros that suppress -Wfloat-equal warnings */
#define TIFF_FLOAT_EQ(x, y) (!(fabsf((x) - (y)) > 0.0f))
#define TIFF_DOUBLE_EQ(x, y) (!(fabs((x) - (y)) > 0.0))
/* /*
Support for large files. Support for large files.
@@ -355,7 +362,7 @@ struct TIFFOpenOptions
*/ */
#if defined(HAVE_FSEEKO) #if defined(HAVE_FSEEKO)
#define fseek(stream, offset, whence) fseeko(stream, offset, whence) #define fseek(stream, offset, whence) fseeko(stream, offset, whence)
#define ftell(stream, offset, whence) ftello(stream, offset, whence) #define ftell(stream) ftello(stream)
#endif #endif
#endif #endif
#if defined(_WIN32) && \ #if defined(_WIN32) && \
@@ -459,9 +466,18 @@ extern "C"
extern uint32_t _TIFFMultiply32(TIFF *, uint32_t, uint32_t, const char *); extern uint32_t _TIFFMultiply32(TIFF *, uint32_t, uint32_t, const char *);
extern uint64_t _TIFFMultiply64(TIFF *, uint64_t, uint64_t, const char *); extern uint64_t _TIFFMultiply64(TIFF *, uint64_t, uint64_t, const char *);
extern uint64_t _TIFFAdd64(TIFF *, uint64_t, uint64_t, const char *);
extern tmsize_t _TIFFMultiplySSize(TIFF *, tmsize_t, tmsize_t, extern tmsize_t _TIFFMultiplySSize(TIFF *, tmsize_t, tmsize_t,
const char *); const char *);
extern tmsize_t _TIFFAddSSize(TIFF *, tmsize_t, tmsize_t, const char *);
extern tmsize_t _TIFFCastUInt64ToSSize(TIFF *, uint64_t, const char *); extern tmsize_t _TIFFCastUInt64ToSSize(TIFF *, uint64_t, const char *);
extern uint32_t _TIFFCastUInt64ToUInt32(TIFF *, uint64_t, const char *);
extern uint64_t _TIFFComputeRowSize64(TIFF *, uint32_t, uint16_t, uint16_t,
const char *);
extern tmsize_t _TIFFComputeRowOffset(TIFF *, tmsize_t rowstride, uint32_t,
const char *);
extern uint64_t _TIFFComputeBitOffset(TIFF *, uint32_t, uint16_t, uint16_t,
const char *);
extern void *_TIFFCheckMalloc(TIFF *, tmsize_t, tmsize_t, const char *); extern void *_TIFFCheckMalloc(TIFF *, tmsize_t, tmsize_t, const char *);
extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t, extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t,
const char *); const char *);
@@ -471,6 +487,8 @@ extern "C"
extern void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif); extern void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif);
extern uint64_t _TIFFStrileSize64(TIFF *tif, uint32_t nrows, int isStrip);
extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif, extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif,
uint32_t strip, uint32_t strip,
void **buf, void **buf,