diff --git a/SPECS/libtiff/CVE-2026-52490.patch b/SPECS/libtiff/CVE-2026-52490.patch new file mode 100644 index 00000000000..0b9362c6c7c --- /dev/null +++ b/SPECS/libtiff/CVE-2026-52490.patch @@ -0,0 +1,9680 @@ +From 50db4d92931cd679572619072d1fe8c242091fa0 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Thu, 27 Aug 2026 02:24:45 +0000 +Subject: [PATCH] Harden integer size and offset calculations in libtiff, + tools, and contrib + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://gitlab.com/libtiff/libtiff/-/commit/b04e935cb6242f22cc8b63c99a372cf3ea825e4e.patch +--- + archive/tools/ppm2tiff.c | 5 +- + archive/tools/ppm2tiff.c.rej | 35 + + archive/tools/raw2tiff.c | 63 +- + archive/tools/raw2tiff.c.rej | 205 +++ + archive/tools/rgb2ycbcr.c | 55 +- + archive/tools/rgb2ycbcr.c.rej | 106 ++ + archive/tools/thumbnail.c | 34 +- + archive/tools/thumbnail.c.rej | 61 + + archive/tools/tiff2bw.c | 20 +- + archive/tools/tiff2rgba.c | 41 +- + archive/tools/tiff2rgba.c.rej | 267 +++ + archive/tools/tiff_tools.c | 50 + + archive/tools/tiff_tools.h | 21 + + archive/tools/tiffcmp.c.rej | 40 + + archive/tools/tiffcrop.c | 1032 ++++++++++-- + archive/tools/tiffcrop.c.rej | 2413 +++++++++++++++++++++++++++ + archive/tools/tiffgt.c | 8 +- + archive/tools/tiffgt.c.rej | 31 + + archive/tools/tiffmedian.c | 1 + + archive/tools/tiffmedian.c.rej | 23 + + contrib/addtiffo/tif_overview.c | 67 +- + contrib/addtiffo/tif_overview.c.rej | 991 +++++++++++ + contrib/addtiffo/tif_ovrcache.c | 1 + + contrib/addtiffo/tif_ovrcache.c.rej | 376 +++++ + contrib/iptcutil/iptcutil.c | 2 + + contrib/iptcutil/iptcutil.c.rej | 33 + + libtiff/tif_aux.c | 88 + + libtiff/tif_aux.c.rej | 47 + + libtiff/tif_dir.c | 10 +- + libtiff/tif_dir.c.rej | 15 + + libtiff/tif_dirwrite.c.rej | 139 ++ + libtiff/tif_print.c.rej | 62 + + libtiff/tif_read.c | 22 +- + libtiff/tif_strip.c | 2 + + libtiff/tif_strip.c.rej | 21 + + libtiff/tif_tile.c.rej | 53 + + libtiff/tif_write.c | 21 +- + libtiff/tiffiop.h | 9 + + tools/CMakeLists.txt.rej | 31 + + tools/Makefile.am.rej | 58 + + tools/tiffcp.c | 95 +- + tools/tiffcp.c.rej | 321 ++++ + tools/tiffdump.c | 17 +- + tools/tiffdump.c.rej | 52 + + tools/tiffinfo.c | 64 +- + tools/tiffinfo.c.rej | 75 + + tools/tiffset.c | 17 +- + tools/tiffset.c.rej | 13 + + tools/tiffsplit.c | 1 + + tools/tiffsplit.c.rej | 28 + + tools/unsupported/tiff2pdf.c | 268 ++- + tools/unsupported/tiff2pdf.c.rej | 265 +++ + tools/unsupported/tiff2ps.c | 27 +- + tools/unsupported/tiff2ps.c.rej | 155 ++ + 54 files changed, 7681 insertions(+), 276 deletions(-) + create mode 100644 archive/tools/ppm2tiff.c.rej + create mode 100644 archive/tools/raw2tiff.c.rej + create mode 100644 archive/tools/rgb2ycbcr.c.rej + create mode 100644 archive/tools/thumbnail.c.rej + create mode 100644 archive/tools/tiff2rgba.c.rej + create mode 100644 archive/tools/tiff_tools.c + create mode 100644 archive/tools/tiff_tools.h + create mode 100644 archive/tools/tiffcmp.c.rej + create mode 100644 archive/tools/tiffcrop.c.rej + create mode 100644 archive/tools/tiffgt.c.rej + create mode 100644 archive/tools/tiffmedian.c.rej + create mode 100644 contrib/addtiffo/tif_overview.c.rej + create mode 100644 contrib/addtiffo/tif_ovrcache.c.rej + create mode 100644 contrib/iptcutil/iptcutil.c.rej + create mode 100644 libtiff/tif_aux.c.rej + create mode 100644 libtiff/tif_dir.c.rej + create mode 100644 libtiff/tif_dirwrite.c.rej + create mode 100644 libtiff/tif_print.c.rej + create mode 100644 libtiff/tif_strip.c.rej + create mode 100644 libtiff/tif_tile.c.rej + create mode 100644 tools/CMakeLists.txt.rej + create mode 100644 tools/Makefile.am.rej + create mode 100644 tools/tiffcp.c.rej + create mode 100644 tools/tiffdump.c.rej + create mode 100644 tools/tiffinfo.c.rej + create mode 100644 tools/tiffset.c.rej + create mode 100644 tools/tiffsplit.c.rej + create mode 100644 tools/unsupported/tiff2pdf.c.rej + create mode 100644 tools/unsupported/tiff2ps.c.rej + +diff --git a/archive/tools/ppm2tiff.c b/archive/tools/ppm2tiff.c +index e64e26d..8fee2e2 100644 +--- a/archive/tools/ppm2tiff.c ++++ b/archive/tools/ppm2tiff.c +@@ -26,6 +26,7 @@ + #include "tif_config.h" + + #include ++#include + #include + #include + #include +@@ -184,6 +185,8 @@ int main(int argc, char *argv[]) + uint16_t spp = 1; + uint16_t bpp = 8; + void (*pack_func)(unsigned char *buf, unsigned int smpls, uint16_t bps); ++ tmsize_t sample_count = 0; ++ unsigned int pack_samples = 0; + TIFF *out; + FILE *in; + unsigned int w, h, prec, row; +@@ -440,7 +443,7 @@ int main(int argc, char *argv[]) + fprintf(stderr, "%s: scanline %u: Read error.\n", infile, row); + break; + } +- pack_func(buf, w * spp, bpp); ++ pack_func(buf, pack_samples, bpp); + if (TIFFWriteScanline(out, buf, row, 0) < 0) + break; + } +diff --git a/archive/tools/ppm2tiff.c.rej b/archive/tools/ppm2tiff.c.rej +new file mode 100644 +index 0000000..3347c66 +--- /dev/null ++++ b/archive/tools/ppm2tiff.c.rej +@@ -0,0 +1,35 @@ ++diff a/archive/tools/ppm2tiff.c b/archive/tools/ppm2tiff.c (rejected hunks) ++@@ -389,18 +392,29 @@ int main(int argc, char *argv[]) ++ default: ++ break; ++ } +++ sample_count = multiply_ms(spp, w); +++ if (sample_count == 0 || sample_count > UINT_MAX) +++ { +++ fprintf(stderr, "%s: sample count overflow\n", infile); +++ TIFFClose(out); +++ exit(EXIT_FAILURE); +++ } +++ pack_samples = (unsigned int)sample_count; +++ ++ if (pbm) ++ { ++- /* if round-up overflows, result will be zero, OK */ ++- linebytes = (multiply_ms(spp, w) + (8 - 1)) / 8; +++ if (sample_count > TIFF_TMSIZE_T_MAX - (8 - 1)) +++ linebytes = 0; +++ else +++ linebytes = (sample_count + (8 - 1)) / 8; ++ } ++ else if (bpp <= 8) ++ { ++- linebytes = multiply_ms(spp, w); +++ linebytes = sample_count; ++ } ++ else ++ { ++- linebytes = multiply_ms(2 * spp, w); +++ linebytes = multiply_ms(2, sample_count); ++ } ++ if (rowsperstrip == (uint32_t)-1) ++ { +diff --git a/archive/tools/raw2tiff.c b/archive/tools/raw2tiff.c +index 307e4be..fef44d4 100644 +--- a/archive/tools/raw2tiff.c ++++ b/archive/tools/raw2tiff.c +@@ -101,10 +101,10 @@ int main(int argc, char *argv[]) + int fd; + char *outfilename = NULL; + TIFF *out; +- uint32_t temp_limit_check = 0; /* temp for integer overflow checking*/ +- + uint32_t row, col, band; + int c; ++ int row_ok; ++ uint64_t depth64; + unsigned char *buf = NULL, *buf1 = NULL; + #if !HAVE_DECL_OPTARG + extern int optind; +@@ -330,17 +330,38 @@ int main(int argc, char *argv[]) + } + TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + +- _TIFF_lseek_f(fd, hdr_size, SEEK_SET); /* Skip the file header */ ++ _TIFF_lseek_f(fd, (_TIFF_off_t)hdr_size, ++ SEEK_SET); /* Skip the file header */ + for (row = 0; row < length; row++) + { ++ row_ok = 1; + switch (interleaving) + { + case BAND: /* band interleaved data */ + for (band = 0; band < nbands; band++) + { +- if (_TIFF_lseek_f( +- fd, hdr_size + (length * band + row) * linebytes, +- SEEK_SET) == (_TIFF_off_t)-1) ++ uint64_t band_rows64 = ++ _TIFFMultiply64(out, length, band, "band file offset"); ++ uint64_t band_row64 = ++ _TIFFAdd64(out, band_rows64, row, "band file offset"); ++ uint64_t data_offset64 = _TIFFMultiply64( ++ out, band_row64, linebytes, "band file offset"); ++ uint64_t seek_offset64 = ++ _TIFFAdd64(out, (uint64_t)hdr_size, data_offset64, ++ "band file offset"); ++ if ((band_rows64 == 0 && length != 0 && band != 0) || ++ (band_row64 == 0 && (band_rows64 != 0 || row != 0)) || ++ (data_offset64 == 0 && ++ (band_row64 != 0 && linebytes != 0)) || ++ (seek_offset64 == 0 && ++ ((uint64_t)hdr_size != 0 || data_offset64 != 0))) ++ { ++ fprintf(stderr, "Too large image size specified.\n"); ++ row_ok = 0; ++ break; ++ } ++ if (_TIFF_lseek_f(fd, (_TIFF_off_t)seek_offset64, ++ SEEK_SET) == (_TIFF_off_t)-1) + { + fprintf(stderr, + "%s: %s: scanline %" PRIu32 ": seek error.\n", +@@ -374,6 +395,12 @@ int main(int argc, char *argv[]) + swapBytesInScanline(buf1, width, dtype); + break; + } ++ if (!row_ok) ++ { ++ close(fd); ++ TIFFClose(out); ++ return (EXIT_FAILURE); ++ } + + if (TIFFWriteScanline(out, buf1, row, 0) < 0) + { +@@ -471,7 +498,18 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, + { + if (imagesize % w == 0) + { +- scanlinesize = w * depth; ++ { ++ uint64_t scanlinesize64 = ++ _TIFFMultiply64(NULL, w, depth64, "scanline size"); ++ scanlinesize = _TIFFCastUInt64ToUInt32(NULL, scanlinesize64, ++ "scanline size"); ++ if (scanlinesize64 == 0 || scanlinesize == 0) ++ { ++ fprintf(stderr, "scanline size overflow.\n"); ++ fail = 1; ++ break; ++ } ++ } + h = imagesize / w; + if (h < 2) + continue; +@@ -543,8 +581,15 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, + } + else + { +- if (filestat.st_size < +- (_TIFF_off_t)(hdr_size + (*width) * (*length) * nbands * depth)) ++ uint64_t needed_size64 = ++ _TIFFMultiply64(NULL, *width, *length, "input image size"); ++ needed_size64 = ++ _TIFFMultiply64(NULL, needed_size64, nbands, "input image size"); ++ needed_size64 = ++ _TIFFMultiply64(NULL, needed_size64, depth64, "input image size"); ++ needed_size64 = _TIFFAdd64(NULL, (uint64_t)hdr_size, needed_size64, ++ "input image size"); ++ if (needed_size64 == 0 || (uint64_t)filestat.st_size < needed_size64) + { + fprintf(stderr, "Input file too small.\n"); + return -1; +diff --git a/archive/tools/raw2tiff.c.rej b/archive/tools/raw2tiff.c.rej +new file mode 100644 +index 0000000..16fc2fc +--- /dev/null ++++ b/archive/tools/raw2tiff.c.rej +@@ -0,0 +1,205 @@ ++diff a/archive/tools/raw2tiff.c b/archive/tools/raw2tiff.c (rejected hunks) ++@@ -236,36 +236,37 @@ int main(int argc, char *argv[]) ++ return (EXIT_FAILURE); ++ } ++ ++- if ((depth <= 0) || ((uint32_t)depth > (UINT_MAX / nbands))) ++- { ++- fprintf(stderr, "Too large nbands value specified.\n"); ++- close(fd); ++- return (EXIT_FAILURE); ++- } ++- ++- temp_limit_check = (uint32_t)depth * nbands; ++- ++- if (!temp_limit_check || length > (UINT_MAX / temp_limit_check)) +++ if (hdr_size < 0) ++ { ++- fprintf(stderr, "Too large length size specified.\n"); +++ fprintf(stderr, "Invalid header size specified.\n"); ++ close(fd); ++ return (EXIT_FAILURE); ++ } ++- temp_limit_check = temp_limit_check * length; ++ ++- if (!temp_limit_check || width > (UINT_MAX / temp_limit_check)) +++ if (depth <= 0) ++ { ++- fprintf(stderr, "Too large width size specified.\n"); +++ fprintf(stderr, "Too large nbands value specified.\n"); ++ close(fd); ++ return (EXIT_FAILURE); ++ } ++- temp_limit_check = temp_limit_check * width; +++ depth64 = (uint64_t)depth; ++ ++- if (!temp_limit_check || hdr_size > (UINT_MAX - temp_limit_check)) ++ { ++- fprintf(stderr, "Too large header size specified.\n"); ++- close(fd); ++- return (EXIT_FAILURE); +++ uint64_t image_size64 = +++ _TIFFMultiply64(NULL, depth64, nbands, "input image size"); +++ uint64_t total_size64; +++ image_size64 = +++ _TIFFMultiply64(NULL, image_size64, length, "input image size"); +++ image_size64 = +++ _TIFFMultiply64(NULL, image_size64, width, "input image size"); +++ total_size64 = _TIFFAdd64(NULL, (uint64_t)hdr_size, image_size64, +++ "input image size"); +++ if (image_size64 == 0 || total_size64 == 0 || total_size64 > UINT_MAX) +++ { +++ fprintf(stderr, "Too large image size specified.\n"); +++ close(fd); +++ return (EXIT_FAILURE); +++ } ++ } ++ ++ if (outfilename == NULL) ++@@ -344,23 +345,54 @@ int main(int argc, char *argv[]) ++ switch (interleaving) ++ { ++ case BAND: /* band interleaved data */ ++- linebytes = (uint32_t)depth * width; +++ { +++ uint64_t linebytes64 = +++ _TIFFMultiply64(out, depth64, width, "scanline size"); +++ linebytes = +++ _TIFFCastUInt64ToUInt32(out, linebytes64, "scanline size"); +++ if (linebytes64 == 0 || linebytes == 0) +++ { +++ fprintf(stderr, "Too large image size specified.\n"); +++ close(fd); +++ TIFFClose(out); +++ return (EXIT_FAILURE); +++ } ++ buf = (unsigned char *)_TIFFmalloc(linebytes); ++ break; +++ } ++ case PIXEL: /* pixel interleaved data */ ++ default: ++- linebytes = (uint32_t)depth * width * nbands; +++ { +++ uint64_t linebytes64 = +++ _TIFFMultiply64(out, depth64, width, "scanline size"); +++ linebytes64 = +++ _TIFFMultiply64(out, linebytes64, nbands, "scanline size"); +++ linebytes = +++ _TIFFCastUInt64ToUInt32(out, linebytes64, "scanline size"); +++ if (linebytes64 == 0 || linebytes == 0) +++ { +++ fprintf(stderr, "Too large image size specified.\n"); +++ close(fd); +++ TIFFClose(out); +++ return (EXIT_FAILURE); +++ } ++ break; +++ } ++ } ++- if ((uint32_t)depth > (UINT_MAX / width) || ++- ((uint32_t)depth * width) > (UINT_MAX / nbands)) ++ { ++- fprintf(stderr, "Too large image size specified.\n"); ++- close(fd); ++- TIFFClose(out); ++- return (EXIT_FAILURE); +++ uint64_t bufsize64 = +++ _TIFFMultiply64(out, depth64, width, "input buffer size"); +++ bufsize64 = +++ _TIFFMultiply64(out, bufsize64, nbands, "input buffer size"); +++ bufsize = _TIFFCastUInt64ToUInt32(out, bufsize64, "input buffer size"); +++ if (bufsize64 == 0 || bufsize == 0) +++ { +++ fprintf(stderr, "Too large image size specified.\n"); +++ close(fd); +++ TIFFClose(out); +++ return (EXIT_FAILURE); +++ } ++ } ++- bufsize = (uint32_t)depth * width * nbands; ++ buf1 = (unsigned char *)_TIFFmalloc(bufsize); ++ ++ rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); ++@@ -397,8 +450,38 @@ int main(int argc, char *argv[]) ++ if (swab) /* Swap bytes if needed */ ++ swapBytesInScanline(buf, width, dtype); ++ for (col = 0; col < width; col++) ++- memcpy(buf1 + (col * nbands + band) * (size_t)depth, ++- buf + col * (size_t)depth, (size_t)depth); +++ { +++ uint64_t sample_index64 = +++ _TIFFMultiply64(out, col, nbands, "sample offset"); +++ uint64_t dst_sample64 = _TIFFAdd64( +++ out, sample_index64, band, "sample offset"); +++ uint64_t dst_offset64 = _TIFFMultiply64( +++ out, dst_sample64, depth64, "sample offset"); +++ uint64_t src_offset64 = +++ _TIFFMultiply64(out, col, depth64, "sample offset"); +++ tmsize_t dst_offset = _TIFFCastUInt64ToSSize( +++ out, dst_offset64, "sample offset"); +++ tmsize_t src_offset = _TIFFCastUInt64ToSSize( +++ out, src_offset64, "sample offset"); +++ if ((sample_index64 == 0 && col != 0 && nbands != 0) || +++ (dst_sample64 == 0 && +++ (sample_index64 != 0 || band != 0)) || +++ (dst_offset64 == 0 && +++ (dst_sample64 != 0 && depth64 != 0)) || +++ (src_offset64 == 0 && col != 0 && depth64 != 0) || +++ (dst_offset == 0 && dst_offset64 != 0) || +++ (src_offset == 0 && src_offset64 != 0)) +++ { +++ fprintf(stderr, +++ "Too large image size specified.\n"); +++ row_ok = 0; +++ break; +++ } +++ memcpy(buf1 + dst_offset, buf + src_offset, +++ (size_t)depth); +++ } +++ if (!row_ok) +++ break; ++ } ++ break; ++ case PIXEL: /* pixel interleaved data */ ++@@ -473,6 +562,7 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, ++ _TIFF_stat_s filestat; ++ uint32_t w, h, scanlinesize, imagesize; ++ uint32_t depth = (uint32_t)TIFFDataWidth(dtype); +++ uint64_t depth64 = (uint64_t)depth; ++ double cor_coef = 0, tmp; ++ ++ if (_TIFF_fstat_f(fd, &filestat) == -1) ++@@ -487,6 +577,12 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, ++ return -1; ++ } ++ +++ if (depth == 0) +++ { +++ fprintf(stderr, "Invalid sample data type.\n"); +++ return -1; +++ } +++ ++ if (((filestat.st_size - hdr_size) / nbands / depth) > UINT32_MAX) ++ { ++ fprintf(stderr, "Too large image size calculated.\n"); ++@@ -541,9 +648,17 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, ++ buf2 = (char *)_TIFFmalloc(scanlinesize); ++ do ++ { ++- if (_TIFF_lseek_f(fd, ++- hdr_size + (uint32_t)((h - 1) / 2) * ++- scanlinesize, +++ uint64_t seek_row = (uint32_t)((h - 1) / 2); +++ uint64_t data_offset64 = _TIFFMultiply64( +++ NULL, seek_row, scanlinesize, "scanline file offset"); +++ uint64_t seek_offset64 = +++ _TIFFAdd64(NULL, (uint64_t)hdr_size, data_offset64, +++ "scanline file offset"); +++ if ((data_offset64 == 0 && seek_row != 0 && +++ scanlinesize != 0) || +++ (seek_offset64 == 0 && +++ ((uint64_t)hdr_size != 0 || data_offset64 != 0)) || +++ _TIFF_lseek_f(fd, (_TIFF_off_t)seek_offset64, ++ SEEK_SET) == (_TIFF_off_t)-1) ++ { ++ fprintf(stderr, "seek error.\n"); +diff --git a/archive/tools/rgb2ycbcr.c b/archive/tools/rgb2ycbcr.c +index d4eabbb..00d6f19 100644 +--- a/archive/tools/rgb2ycbcr.c ++++ b/archive/tools/rgb2ycbcr.c +@@ -224,12 +224,60 @@ static void cvtClump(unsigned char *op, uint32_t *raster, uint32_t ch, + * Convert a strip of RGB data to YCbCr and + * sample to generate the output data. + */ +-static void cvtStrip(unsigned char *op, uint32_t *raster, uint32_t nrows, +- uint32_t width) ++static int checkedRoundup32(TIFF *tif, uint32_t *result, uint32_t value, ++ uint16_t multiple, const char *where) ++{ ++ uint64_t rounded64; ++ uint32_t rounded32; ++ ++ if (multiple == 0) ++ return 0; ++ rounded64 = _TIFFAdd64(tif, value, (uint64_t)multiple - 1U, where); ++ if (rounded64 == 0 && value != 0) ++ return 0; ++ rounded64 = _TIFFMultiply64(tif, rounded64 / multiple, multiple, where); ++ rounded32 = _TIFFCastUInt64ToUInt32(tif, rounded64, where); ++ if ((rounded64 == 0 && value != 0) || (rounded32 == 0 && rounded64 != 0)) ++ return 0; ++ *result = rounded32; ++ return 1; ++} ++ ++static tmsize_t computeYCbCrStripSize(TIFF *tif, uint32_t rows, uint32_t width, ++ const char *where) ++{ ++ uint64_t luma64 = _TIFFMultiply64(tif, rows, width, where); ++ uint64_t subsampling64 = ++ _TIFFMultiply64(tif, horizSubSampling, vertSubSampling, where); ++ uint64_t chroma_samples64; ++ uint64_t chroma64; ++ uint64_t total64; ++ tmsize_t total; ++ ++ if ((luma64 == 0 && rows != 0 && width != 0) || subsampling64 == 0) ++ return 0; ++ chroma_samples64 = luma64 / subsampling64; ++ chroma64 = _TIFFMultiply64(tif, chroma_samples64, 2, where); ++ total64 = _TIFFAdd64(tif, luma64, chroma64, where); ++ total = _TIFFCastUInt64ToSSize(tif, total64, where); ++ if ((chroma64 == 0 && chroma_samples64 != 0) || ++ (total64 == 0 && (luma64 != 0 || chroma64 != 0)) || ++ (total == 0 && total64 != 0)) ++ return 0; ++ return total; ++} ++ ++static int cvtStrip(TIFF *tif, unsigned char *op, uint32_t *raster, ++ uint32_t nrows, uint32_t width) + { + uint32_t x; + int clumpSize = vertSubSampling * horizSubSampling + 2; + uint32_t *tp; ++ tmsize_t row_advance = ++ _TIFFComputeRowOffset(tif, width, vertSubSampling, "raster row offset"); ++ ++ if (row_advance == 0 && width != 0 && vertSubSampling != 0) ++ return 0; + + for (; nrows >= vertSubSampling; nrows -= vertSubSampling) + { +@@ -245,7 +293,7 @@ static void cvtStrip(unsigned char *op, uint32_t *raster, uint32_t nrows, + cvtClump(op, tp, vertSubSampling, x, width); + op += clumpSize; + } +- raster -= vertSubSampling * width; ++ raster -= row_advance; + } + if (nrows > 0) + { +@@ -259,6 +307,7 @@ static void cvtStrip(unsigned char *op, uint32_t *raster, uint32_t nrows, + if (x > 0) + cvtClump(op, tp, nrows, x, width); + } ++ return 1; + } + + static int cvtRaster(TIFF *tif, uint32_t *raster, uint32_t width, +diff --git a/archive/tools/rgb2ycbcr.c.rej b/archive/tools/rgb2ycbcr.c.rej +new file mode 100644 +index 0000000..56800b6 +--- /dev/null ++++ b/archive/tools/rgb2ycbcr.c.rej +@@ -0,0 +1,106 @@ ++diff a/archive/tools/rgb2ycbcr.c b/archive/tools/rgb2ycbcr.c (rejected hunks) ++@@ -277,24 +326,51 @@ static int cvtRaster(TIFF *tif, uint32_t *raster, uint32_t width, ++ tstrip_t strip = 0; ++ tsize_t cc, acc; ++ unsigned char *buf; ++- uint32_t rwidth = roundup(width, horizSubSampling); ++- uint32_t rheight = roundup(height, vertSubSampling); ++- uint32_t nrows = (rowsperstrip > rheight ? rheight : rowsperstrip); ++- uint32_t rnrows = roundup(nrows, vertSubSampling); ++- ++- cc = (tsize_t)rnrows * rwidth + ++- 2 * ((tsize_t)rnrows * rwidth / ++- ((uint32_t)horizSubSampling * vertSubSampling)); +++ uint32_t rwidth; +++ uint32_t rheight; +++ uint32_t nrows; +++ uint32_t rnrows; +++ +++ if (!checkedRoundup32(tif, &rwidth, width, horizSubSampling, +++ "rounded raster width") || +++ !checkedRoundup32(tif, &rheight, height, vertSubSampling, +++ "rounded raster height")) +++ return 0; +++ nrows = (rowsperstrip > rheight ? rheight : rowsperstrip); +++ if (nrows == 0) +++ return 0; +++ if (!checkedRoundup32(tif, &rnrows, nrows, vertSubSampling, +++ "rounded strip height")) +++ return 0; +++ +++ cc = computeYCbCrStripSize(tif, rnrows, rwidth, "YCbCr strip size"); +++ if (cc == 0) +++ return 0; ++ buf = (unsigned char *)_TIFFmalloc(cc); ++ // FIXME unchecked malloc ++ for (y = height; (int32_t)y > 0; y -= nrows) ++ { ++ uint32_t nr = (y > nrows ? nrows : y); ++- cvtStrip(buf, raster + (y - 1) * width, nr, width); ++- nr = roundup(nr, vertSubSampling); ++- acc = (tsize_t)nr * rwidth + ++- 2 * ((tsize_t)nr * rwidth / ++- ((uint32_t)horizSubSampling * vertSubSampling)); +++ tmsize_t raster_offset = +++ _TIFFComputeRowOffset(tif, width, y - 1, "raster row offset"); +++ if ((raster_offset == 0 && y != 1 && width != 0) || +++ !cvtStrip(tif, buf, raster + raster_offset, nr, width)) +++ { +++ _TIFFfree(buf); +++ return 0; +++ } +++ if (!checkedRoundup32(tif, &nr, nr, vertSubSampling, +++ "rounded strip height")) +++ { +++ _TIFFfree(buf); +++ return 0; +++ } +++ acc = computeYCbCrStripSize(tif, nr, rwidth, "YCbCr strip size"); +++ if (acc == 0) +++ { +++ _TIFFfree(buf); +++ return 0; +++ } ++ if (!TIFFWriteEncodedStrip(tif, strip++, buf, acc)) ++ { ++ _TIFFfree(buf); ++@@ -314,15 +390,19 @@ static int tiffcvt(TIFF *in, TIFF *out) ++ char *stringv; ++ uint32_t longv; ++ int result; ++- size_t pixel_count; +++ uint64_t pixel_count64; +++ tmsize_t pixel_count; ++ ++ TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); ++ TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); ++- pixel_count = (size_t)width * height; +++ pixel_count64 = +++ _TIFFMultiply64(in, width, height, "raster buffer pixel count"); +++ pixel_count = +++ _TIFFCastUInt64ToSSize(in, pixel_count64, "raster buffer pixel count"); ++ ++ /* Check for integer overflow or implausibly large image dimensions. */ ++- if (!width || !height || SIZE_MAX / width < height || ++- pixel_count > (size_t)(INT32_MAX / sizeof(uint32_t))) +++ if (!width || !height || pixel_count == 0 || +++ pixel_count > (tmsize_t)(INT32_MAX / sizeof(uint32_t))) ++ { ++ TIFFError(TIFFFileName(in), ++ "Malformed input file; " ++@@ -332,12 +412,12 @@ static int tiffcvt(TIFF *in, TIFF *out) ++ return 0; ++ } ++ ++- raster = (uint32_t *)_TIFFCheckMalloc(in, (tmsize_t)pixel_count, ++- sizeof(uint32_t), "raster buffer"); +++ raster = (uint32_t *)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32_t), +++ "raster buffer"); ++ if (raster == 0) ++ { ++ TIFFError(TIFFFileName(in), ++- "Failed to allocate buffer (%" TIFF_SIZE_FORMAT +++ "Failed to allocate buffer (%" TIFF_SSIZE_FORMAT ++ " elements of %" TIFF_SIZE_FORMAT " each)", ++ pixel_count, sizeof(uint32_t)); ++ return (0); +diff --git a/archive/tools/thumbnail.c b/archive/tools/thumbnail.c +index 237d99e..d9f1e2b 100644 +--- a/archive/tools/thumbnail.c ++++ b/archive/tools/thumbnail.c +@@ -651,8 +651,17 @@ static void setImage1(const uint8_t *br, uint32_t rw, uint32_t rh) + { + const uint8_t *rows[256]; + uint32_t nrows = 1; +- fprintf(stderr, "bpr=%d, sy=%d, bpr*sy=%d\n", bpr, sy, bpr * sy); +- rows[0] = br + bpr * sy; ++ tmsize_t row_offset = _TIFFComputeRowOffset(NULL, bpr, (uint32_t)sy, ++ "thumbnail row offset"); ++ if (row_offset == 0 && sy != 0 && bpr != 0) ++ { ++ TIFFError("thumbnail", ++ "Integer overflow detected while calculating row offset"); ++ exit(EXIT_FAILURE); ++ } ++ fprintf(stderr, "bpr=%d, sy=%d, bpr*sy=%" TIFF_SSIZE_FORMAT "\n", bpr, ++ sy, row_offset); ++ rows[0] = br + row_offset; + err += step; + while (err >= limit) + { +@@ -715,7 +724,16 @@ static int generateThumbnail(TIFF *in, TIFF *out) + for (s = 0; s < ns; s++) + { + (void)TIFFReadEncodedStrip(in, s, rp, -1); +- rp += rps * rowsize; ++ { ++ tmsize_t strip_offset = ++ _TIFFComputeRowOffset(in, rowsize, rps, "strip buffer offset"); ++ if (strip_offset == 0 && rps != 0 && rowsize != 0) ++ { ++ _TIFFfree(raster); ++ return 0; ++ } ++ rp += strip_offset; ++ } + } + TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric); + setupCmap(); +@@ -737,8 +755,14 @@ static int generateThumbnail(TIFF *in, TIFF *out) + cpTag(in, out, TIFFTAG_HOSTCOMPUTER, (uint16_t)-1, TIFF_ASCII); + diroff[0] = 0UL; + TIFFSetField(out, TIFFTAG_SUBIFD, 1, diroff); +- return (TIFFWriteEncodedStrip(out, 0, thumbnail, tnw * tnh) != -1 && +- TIFFWriteDirectory(out) != -1); ++ { ++ uint32_t thumbsize = ++ _TIFFMultiply32(out, tnw, tnh, "thumbnail strip size"); ++ if (thumbsize == 0) ++ return 0; ++ return (TIFFWriteEncodedStrip(out, 0, thumbnail, thumbsize) != -1 && ++ TIFFWriteDirectory(out) != -1); ++ } + } + + const char *usage_info[] = { +diff --git a/archive/tools/thumbnail.c.rej b/archive/tools/thumbnail.c.rej +new file mode 100644 +index 0000000..767bb15 +--- /dev/null ++++ b/archive/tools/thumbnail.c.rej +@@ -0,0 +1,61 @@ ++diff a/archive/tools/thumbnail.c b/archive/tools/thumbnail.c (rejected hunks) ++@@ -565,11 +565,19 @@ static void setupCmap(void) ++ ++ static void initScale(void) ++ { ++- src0 = (uint8_t *)_TIFFmalloc(sizeof(uint8_t) * tnw); ++- src1 = (uint8_t *)_TIFFmalloc(sizeof(uint8_t) * tnw); ++- src2 = (uint8_t *)_TIFFmalloc(sizeof(uint8_t) * tnw); ++- rowoff = ++- (uint32_t *)_TIFFmalloc((tmsize_t)(sizeof(uint32_t) * (size_t)tnw)); +++ src0 = +++ (uint8_t *)_TIFFCheckMalloc(NULL, tnw, sizeof(uint8_t), "scale table"); +++ src1 = +++ (uint8_t *)_TIFFCheckMalloc(NULL, tnw, sizeof(uint8_t), "scale table"); +++ src2 = +++ (uint8_t *)_TIFFCheckMalloc(NULL, tnw, sizeof(uint8_t), "scale table"); +++ rowoff = (uint32_t *)_TIFFCheckMalloc(NULL, tnw, sizeof(uint32_t), +++ "scale table"); +++ if (src0 == NULL || src1 == NULL || src2 == NULL || rowoff == NULL) +++ { +++ TIFFError("thumbnail", "Can't allocate space for scale tables"); +++ exit(EXIT_FAILURE); +++ } ++ filterWidth = 0; ++ stepDstWidth = stepSrcWidth = 0; ++ setupBitsTables(); ++@@ -703,7 +720,18 @@ static void setImage1(const uint8_t *br, uint32_t rw, uint32_t rh) ++ * would leave err >= limit and cause it to grow by ++ * (step - 255*limit) each outer iteration, overflowing. */ ++ if (nrows < 256) ++- rows[nrows++] = br + bpr * sy; +++ { +++ row_offset = _TIFFComputeRowOffset(NULL, bpr, (uint32_t)sy, +++ "thumbnail row offset"); +++ if (row_offset == 0 && sy != 0 && bpr != 0) +++ { +++ TIFFError("thumbnail", +++ "Integer overflow detected while calculating " +++ "row offset"); +++ exit(EXIT_FAILURE); +++ } +++ rows[nrows++] = br + row_offset; +++ } ++ } ++ } ++ setrow(row, nrows, rows); ++@@ -736,12 +764,12 @@ static int generateThumbnail(TIFF *in, TIFF *out) ++ if (spp != 1 || bps != 1) ++ return 0; ++ rowsize = TIFFScanlineSize(in); ++- if ((uint64_t)rowsize * sh + 3 > INT32_MAX) +++ rastersize = _TIFFMultiplySSize(in, rowsize, sh, "raster buffer size"); +++ if (rastersize == 0 || (uint64_t)rastersize > (uint64_t)INT32_MAX - 3U) ++ { ++ TIFFError(TIFFFileName(in), "Image is too large to fit in memory"); ++ return 0; ++ } ++- rastersize = sh * rowsize; ++ fprintf(stderr, "rastersize=%u\n", (unsigned int)rastersize); ++ /* +3 : add a few guard bytes since setrow() can read a bit */ ++ /* outside buffer */ +diff --git a/archive/tools/tiff2bw.c b/archive/tools/tiff2bw.c +index 51f50ca..c4286a0 100644 +--- a/archive/tools/tiff2bw.c ++++ b/archive/tools/tiff2bw.c +@@ -311,10 +311,24 @@ int main(int argc, char *argv[]) + for (row = 0; row < h; row++) + { + for (s = 0; s < 3; s++) +- if (TIFFReadScanline(in, inbuf + s * rowsize, row, s) < 0) ++ { ++ tmsize_t plane_offset = _TIFFComputeRowOffset( ++ in, rowsize, s, "sample plane offset"); ++ if ((plane_offset == 0 && s != 0 && rowsize != 0) || ++ TIFFReadScanline(in, inbuf + plane_offset, row, s) < 0) + goto tiff2bw_error; +- compresssep(outbuf, inbuf, inbuf + rowsize, inbuf + 2 * rowsize, +- w); ++ } ++ { ++ tmsize_t plane1_offset = _TIFFComputeRowOffset( ++ in, rowsize, 1, "sample plane offset"); ++ tmsize_t plane2_offset = _TIFFComputeRowOffset( ++ in, rowsize, 2, "sample plane offset"); ++ if ((plane1_offset == 0 && rowsize != 0) || ++ (plane2_offset == 0 && rowsize != 0)) ++ goto tiff2bw_error; ++ compresssep(outbuf, inbuf, inbuf + plane1_offset, ++ inbuf + plane2_offset, w); ++ } + if (TIFFWriteScanline(out, outbuf, row, 0) < 0) + break; + } +diff --git a/archive/tools/tiff2rgba.c b/archive/tools/tiff2rgba.c +index 693fc81..f60ad7f 100644 +--- a/archive/tools/tiff2rgba.c ++++ b/archive/tools/tiff2rgba.c +@@ -33,6 +33,7 @@ + #include + #endif + ++#include "tiff_tools.h" + #include "tiffio.h" + #include "tiffiop.h" + +@@ -174,7 +175,7 @@ static int cvt_by_tile(TIFF *in, TIFF *out) + uint32_t row, col; + uint32_t *wrk_line; + int ok = 1; +- uint32_t rastersize, wrk_linesize; ++ tmsize_t raster_pixels, rastersize, wrk_linesize; + + TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); +@@ -245,7 +246,7 @@ static int cvt_by_tile(TIFF *in, TIFF *out) + * we should rearrange it here. + */ + #if HOST_BIGENDIAN +- TIFFSwabArrayOfLong(raster, tile_width * tile_height); ++ TIFFSwabArrayOfLong(raster, raster_pixels); + #endif + + /* +@@ -256,21 +257,35 @@ static int cvt_by_tile(TIFF *in, TIFF *out) + { + uint32_t *top_line, *bottom_line; + +- top_line = raster + tile_width * i_row; +- bottom_line = raster + tile_width * (tile_height - i_row - 1); ++ tmsize_t top_offset = _TIFFComputeRowOffset( ++ in, tile_width, i_row, "tile row offset"); ++ uint32_t bottom_row = tile_height - i_row - 1; ++ tmsize_t bottom_offset = _TIFFComputeRowOffset( ++ in, tile_width, bottom_row, "tile row offset"); ++ if ((top_offset == 0 && i_row != 0) || ++ (bottom_offset == 0 && bottom_row != 0)) ++ { ++ ok = 0; ++ break; ++ } ++ ++ top_line = raster + top_offset; ++ bottom_line = raster + bottom_offset; + +- _TIFFmemcpy(wrk_line, top_line, 4 * tile_width); +- _TIFFmemcpy(top_line, bottom_line, 4 * tile_width); +- _TIFFmemcpy(bottom_line, wrk_line, 4 * tile_width); ++ _TIFFmemcpy(wrk_line, top_line, wrk_linesize); ++ _TIFFmemcpy(top_line, bottom_line, wrk_linesize); ++ _TIFFmemcpy(bottom_line, wrk_line, wrk_linesize); + } + ++ if (!ok) ++ break; ++ + /* + * Write out the result in a tile. + */ + + if (TIFFWriteEncodedTile(out, TIFFComputeTile(out, col, row, 0, 0), +- raster, +- 4 * tile_width * tile_height) == -1) ++ raster, rastersize) == -1) + { + ok = 0; + break; +@@ -292,7 +307,7 @@ static int cvt_by_strip(TIFF *in, TIFF *out) + uint32_t row; + uint32_t *wrk_line; + int ok = 1; +- uint32_t rastersize, wrk_linesize; ++ tmsize_t raster_pixels, rastersize, wrk_linesize; + + TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); +@@ -359,7 +374,7 @@ static int cvt_by_strip(TIFF *in, TIFF *out) + * we should rearrange it here. + */ + #if HOST_BIGENDIAN +- TIFFSwabArrayOfLong(raster, width * rowsperstrip); ++ TIFFSwabArrayOfLong(raster, raster_pixels); + #endif + + /* +@@ -472,7 +487,7 @@ static int cvt_whole_image(TIFF *in, TIFF *out) + * we should rearrange it here. + */ + #if HOST_BIGENDIAN +- TIFFSwabArrayOfLong(raster, width * height); ++ TIFFSwabArrayOfLong(raster, pixel_count); + #endif + + /* +@@ -480,7 +495,7 @@ static int cvt_whole_image(TIFF *in, TIFF *out) + */ + if (no_alpha) + { +- size_t count = pixel_count; ++ tmsize_t count = pixel_count; + unsigned char *src, *dst; + + src = dst = (unsigned char *)raster; +diff --git a/archive/tools/tiff2rgba.c.rej b/archive/tools/tiff2rgba.c.rej +new file mode 100644 +index 0000000..4e61c59 +--- /dev/null ++++ b/archive/tools/tiff2rgba.c.rej +@@ -0,0 +1,267 @@ ++diff a/archive/tools/tiff2rgba.c b/archive/tools/tiff2rgba.c (rejected hunks) ++@@ -73,7 +74,6 @@ int main(int argc, char *argv[]) ++ { ++ TIFF *in, *out; ++ int c; ++- long v; ++ #if !HAVE_DECL_OPTARG ++ extern int optind; ++ extern char *optarg; ++@@ -83,10 +83,8 @@ int main(int argc, char *argv[]) ++ switch (c) ++ { ++ case 'M': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ break; ++ case 'b': ++ process_by_block = 1; ++@@ -214,14 +212,12 @@ static int cvt_by_tile(TIFF *in, TIFF *out) ++ /* ++ * Allocate tile buffer ++ */ ++- rastersize = ++- (uint32_t)((size_t)tile_width * tile_height * sizeof(uint32_t)); ++- if (tile_width != (rastersize / tile_height) / sizeof(uint32_t)) ++- { ++- TIFFError(TIFFFileName(in), ++- "Integer overflow when calculating raster buffer"); +++ raster_pixels = _TIFFMultiplySSize(in, (tmsize_t)tile_width, +++ (tmsize_t)tile_height, "raster buffer"); +++ rastersize = _TIFFMultiplySSize(in, raster_pixels, sizeof(uint32_t), +++ "raster buffer"); +++ if (raster_pixels == 0 || rastersize == 0) ++ exit(EXIT_FAILURE); ++- } ++ raster = (uint32_t *)_TIFFmalloc(rastersize); ++ if (raster == 0) ++ { ++@@ -233,13 +229,10 @@ static int cvt_by_tile(TIFF *in, TIFF *out) ++ * Allocate a scanline buffer for swapping during the vertical ++ * mirroring pass. ++ */ ++- wrk_linesize = (uint32_t)(tile_width * sizeof(uint32_t)); ++- if (tile_width != wrk_linesize / sizeof(uint32_t)) ++- { ++- TIFFError(TIFFFileName(in), ++- "Integer overflow when calculating wrk_line buffer"); +++ wrk_linesize = _TIFFMultiplySSize(in, (tmsize_t)tile_width, +++ sizeof(uint32_t), "wrk_line buffer"); +++ if (wrk_linesize == 0) ++ exit(EXIT_FAILURE); ++- } ++ wrk_line = (uint32_t *)_TIFFmalloc(wrk_linesize); ++ if (!wrk_line) ++ { ++@@ -341,13 +348,12 @@ static int cvt_by_strip(TIFF *in, TIFF *out) ++ /* ++ * Allocate strip buffer ++ */ ++- rastersize = (uint32_t)((size_t)width * rowsperstrip * sizeof(uint32_t)); ++- if (width != (rastersize / rowsperstrip) / sizeof(uint32_t)) ++- { ++- TIFFError(TIFFFileName(in), ++- "Integer overflow when calculating raster buffer"); +++ raster_pixels = +++ _TIFFMultiplySSize(in, width, rowsperstrip, "raster buffer"); +++ rastersize = _TIFFMultiplySSize(in, raster_pixels, sizeof(uint32_t), +++ "raster buffer"); +++ if (raster_pixels == 0 || rastersize == 0) ++ exit(EXIT_FAILURE); ++- } ++ raster = (uint32_t *)_TIFFmalloc(rastersize); ++ if (raster == 0) ++ { ++@@ -359,13 +365,10 @@ static int cvt_by_strip(TIFF *in, TIFF *out) ++ * Allocate a scanline buffer for swapping during the vertical ++ * mirroring pass. ++ */ ++- wrk_linesize = (uint32_t)(width * sizeof(uint32_t)); ++- if (width != wrk_linesize / sizeof(uint32_t)) ++- { ++- TIFFError(TIFFFileName(in), ++- "Integer overflow when calculating wrk_line buffer"); +++ wrk_linesize = +++ _TIFFMultiplySSize(in, width, sizeof(uint32_t), "wrk_line buffer"); +++ if (wrk_linesize == 0) ++ exit(EXIT_FAILURE); ++- } ++ wrk_line = (uint32_t *)_TIFFmalloc(wrk_linesize); ++ if (!wrk_line) ++ { ++@@ -411,25 +414,44 @@ static int cvt_by_strip(TIFF *in, TIFF *out) ++ for (i_row = 0; i_row < rows_to_write / 2; i_row++) ++ { ++ uint32_t *top_line, *bottom_line; +++ uint32_t bottom_row = (uint32_t)(rows_to_write - i_row - 1); +++ tmsize_t top_offset = _TIFFComputeRowOffset( +++ in, width, (uint32_t)i_row, "raster row offset"); +++ tmsize_t bottom_offset = _TIFFComputeRowOffset( +++ in, width, bottom_row, "raster row offset"); +++ +++ if ((top_offset == 0 && i_row != 0) || +++ (bottom_offset == 0 && bottom_row != 0)) +++ { +++ ok = 0; +++ break; +++ } ++ ++- top_line = raster + width * (uint32_t)i_row; ++- bottom_line = ++- raster + width * (uint32_t)(rows_to_write - i_row - 1); +++ top_line = raster + top_offset; +++ bottom_line = raster + bottom_offset; ++ ++- _TIFFmemcpy(wrk_line, top_line, 4 * width); ++- _TIFFmemcpy(top_line, bottom_line, 4 * width); ++- _TIFFmemcpy(bottom_line, wrk_line, 4 * width); +++ _TIFFmemcpy(wrk_line, top_line, wrk_linesize); +++ _TIFFmemcpy(top_line, bottom_line, wrk_linesize); +++ _TIFFmemcpy(bottom_line, wrk_line, wrk_linesize); ++ } ++ +++ if (!ok) +++ break; +++ ++ /* ++ * Write out the result in a strip ++ */ ++- ++- if (TIFFWriteEncodedStrip(out, row / rowsperstrip, raster, ++- 4 * (uint32_t)rows_to_write * width) == -1) ++ { ++- ok = 0; ++- break; +++ tmsize_t write_size = _TIFFMultiplySSize(in, (tmsize_t)wrk_linesize, +++ (tmsize_t)rows_to_write, +++ "strip write buffer size"); +++ if (write_size == 0 || +++ TIFFWriteEncodedStrip(out, row / rowsperstrip, raster, +++ write_size) == -1) +++ { +++ ok = 0; +++ break; +++ } ++ } ++ } ++ ++@@ -453,14 +475,14 @@ static int cvt_whole_image(TIFF *in, TIFF *out) ++ uint32_t *raster; /* retrieve RGBA image */ ++ uint32_t width, height; /* image width & height */ ++ uint32_t row; ++- size_t pixel_count; +++ uint64_t pixel_count64; +++ tmsize_t pixel_count; +++ tmsize_t raster_bytes; ++ ++ TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); ++ TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); ++- pixel_count = (size_t)width * height; ++ ++- /* XXX: Check the integer overflow. */ ++- if (!width || !height || SIZE_MAX / width < height) +++ if (!width || !height) ++ { ++ TIFFError( ++ TIFFFileName(in), ++@@ -469,27 +491,41 @@ static int cvt_whole_image(TIFF *in, TIFF *out) ++ width, height); ++ return 0; ++ } ++- if (maxMalloc != 0 && ++- (tmsize_t)pixel_count * (tmsize_t)sizeof(uint32_t) > maxMalloc) +++ +++ pixel_count64 = _TIFFMultiply64(in, width, height, "raster buffer size"); +++ if (pixel_count64 == 0) +++ return 0; +++ +++ pixel_count = +++ _TIFFCastUInt64ToSSize(in, pixel_count64, "raster buffer size"); +++ if (pixel_count == 0) +++ return 0; +++ +++ raster_bytes = _TIFFMultiplySSize(in, pixel_count, sizeof(uint32_t), +++ "raster buffer size"); +++ if (raster_bytes == 0) +++ return 0; +++ +++ if (maxMalloc != 0 && raster_bytes > maxMalloc) ++ { ++ TIFFError(TIFFFileName(in), ++ "Raster size %" TIFF_SIZE_FORMAT ++ " over memory limit (%" TIFF_SSIZE_FORMAT "), try -b option.", ++- pixel_count * sizeof(uint32_t), maxMalloc); +++ (size_t)raster_bytes, maxMalloc); ++ return 0; ++ } ++ ++ rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); ++ TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); ++ ++- raster = (uint32_t *)_TIFFCheckMalloc(in, (tmsize_t)pixel_count, ++- sizeof(uint32_t), "raster buffer"); +++ raster = (uint32_t *)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32_t), +++ "raster buffer"); ++ if (raster == 0) ++ { ++ TIFFError(TIFFFileName(in), ++ "Failed to allocate buffer (%" TIFF_SIZE_FORMAT ++ " elements of %" TIFF_SIZE_FORMAT " each)", ++- pixel_count, sizeof(uint32_t)); +++ (size_t)pixel_count, sizeof(uint32_t)); ++ return (0); ++ } ++ ++@@ -548,26 +584,44 @@ static int cvt_whole_image(TIFF *in, TIFF *out) ++ unsigned char *raster_strip; ++ int rows_to_write; ++ int bytes_per_pixel; +++ tmsize_t raster_rowbytes; +++ tmsize_t raster_offset; +++ tmsize_t write_size; ++ ++ if (no_alpha) ++ { ++- raster_strip = ((unsigned char *)raster) + 3 * row * width; ++ bytes_per_pixel = 3; ++ } ++ else ++ { ++- raster_strip = (unsigned char *)(raster + row * width); ++ bytes_per_pixel = 4; ++ } +++ raster_rowbytes = _TIFFMultiplySSize( +++ in, (tmsize_t)width, bytes_per_pixel, "raster row size"); +++ if (raster_rowbytes == 0) +++ { +++ _TIFFfree(raster); +++ return 0; +++ } +++ raster_offset = _TIFFComputeRowOffset(in, raster_rowbytes, row, +++ "raster row offset"); +++ if (raster_offset == 0 && row != 0) +++ { +++ _TIFFfree(raster); +++ return 0; +++ } +++ raster_strip = ((unsigned char *)raster) + raster_offset; ++ ++ if (row + rowsperstrip > height) ++ rows_to_write = (int)(height - row); ++ else ++ rows_to_write = (int)rowsperstrip; ++ ++- if (TIFFWriteEncodedStrip(out, row / rowsperstrip, raster_strip, ++- (tmsize_t)bytes_per_pixel * rows_to_write * ++- width) == -1) +++ write_size = _TIFFMultiplySSize(in, raster_rowbytes, rows_to_write, +++ "strip write buffer size"); +++ if (write_size == 0 || +++ TIFFWriteEncodedStrip(out, row / rowsperstrip, raster_strip, +++ write_size) == -1) ++ { ++ _TIFFfree(raster); ++ return 0; +diff --git a/archive/tools/tiff_tools.c b/archive/tools/tiff_tools.c +new file mode 100644 +index 0000000..760c052 +--- /dev/null ++++ b/archive/tools/tiff_tools.c +@@ -0,0 +1,50 @@ ++/* ++ * Shared helpers for libtiff command line tools. ++ */ ++ ++#include "tiff_tools.h" ++#include "tif_config.h" ++#include "tiffiop.h" ++ ++#include ++#include ++#include ++ ++int TIFFToolsParseMemoryLimitMiB(const char *arg, tmsize_t *limit) ++{ ++ char *end = NULL; ++ const char *p; ++ unsigned long long value; ++ uint64_t bytes; ++ tmsize_t limit_value; ++ ++ if (arg == NULL || limit == NULL) ++ return 0; ++ ++ p = arg; ++ while (*p != '\0' && isspace((unsigned char)*p)) ++ ++p; ++ if (*p == '-') ++ return 0; ++ ++ errno = 0; ++ value = strtoull(p, &end, 0); ++ ++ while (*end != '\0' && isspace((unsigned char)*end)) ++ ++end; ++ ++ if (errno != 0 || end == p || *end != '\0') ++ return 0; ++ ++ bytes = ++ _TIFFMultiply64(NULL, (uint64_t)value, 1024U * 1024U, "memory limit"); ++ if (bytes == 0 && value != 0) ++ return 0; ++ ++ limit_value = _TIFFCastUInt64ToSSize(NULL, bytes, "memory limit"); ++ if (limit_value == 0 && bytes != 0) ++ return 0; ++ ++ *limit = limit_value; ++ return 1; ++} +diff --git a/archive/tools/tiff_tools.h b/archive/tools/tiff_tools.h +new file mode 100644 +index 0000000..9c0177f +--- /dev/null ++++ b/archive/tools/tiff_tools.h +@@ -0,0 +1,21 @@ ++/* ++ * Shared helpers for libtiff command line tools. ++ */ ++ ++#ifndef TIFF_TOOLS_H ++#define TIFF_TOOLS_H ++ ++#include "tiffio.h" ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++ int TIFFToolsParseMemoryLimitMiB(const char *arg, tmsize_t *limit); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/archive/tools/tiffcmp.c.rej b/archive/tools/tiffcmp.c.rej +new file mode 100644 +index 0000000..e785ba1 +--- /dev/null ++++ b/archive/tools/tiffcmp.c.rej +@@ -0,0 +1,40 @@ ++diff a/archive/tools/tiffcmp.c b/archive/tools/tiffcmp.c (rejected hunks) ++@@ -220,13 +220,18 @@ static int tiffcmp(TIFF *tif1, TIFF *tif2) ++ separate_size = size1; ++ } ++ ++- if (contig_size < (tsize_t)imagewidth * samplesperpixel || ++- separate_size < (tsize_t)imagewidth) ++ { ++- fprintf( ++- stderr, ++- "Inconsistent scanline size for mixed planar configuration\n"); ++- goto bad; +++ tmsize_t contig_min = +++ _TIFFMultiplySSize(tif1, imagewidth, samplesperpixel, +++ "mixed planar scanline size"); +++ if (contig_min == 0 && imagewidth != 0 && samplesperpixel != 0) +++ goto bad; +++ if (contig_size < contig_min || separate_size < (tsize_t)imagewidth) +++ { +++ fprintf(stderr, "Inconsistent scanline size for mixed planar " +++ "configuration\n"); +++ goto bad; +++ } ++ } ++ } ++ #define pack(a, b) ((a) << 8) | (b) ++@@ -730,8 +735,12 @@ static int CheckShortArrayTag(TIFF *tif1, TIFF *tif2, int tag, const char *name) ++ { ++ const char *sep; ++ uint16_t i; +++ tmsize_t array_bytes = _TIFFMultiplySSize( +++ tif1, n1, sizeof(uint16_t), "short array tag size"); ++ ++- if (memcmp(a1, a2, n1 * sizeof(uint16_t)) == 0) +++ if (array_bytes == 0 && n1 != 0) +++ return (0); +++ if (memcmp(a1, a2, (size_t)array_bytes) == 0) ++ return (1); ++ printf("%s: value mismatch, <%" PRIu16 ":", name, n1); ++ sep = ""; +diff --git a/archive/tools/tiffcrop.c b/archive/tools/tiffcrop.c +index 998c6ab..058bc91 100644 +--- a/archive/tools/tiffcrop.c ++++ b/archive/tools/tiffcrop.c +@@ -129,6 +129,7 @@ + + #include "libport.h" + #include "tif_config.h" ++#include "tiff_tools.h" + #include "tiffiop.h" + + #include +@@ -448,16 +449,17 @@ struct image_data + struct pagedef + { + char name[16]; +- double width; /* width in pixels */ +- double length; /* length in pixels */ +- double hmargin; /* margins to subtract from width of sections */ +- double vmargin; /* margins to subtract from height of sections */ +- double hres; /* horizontal resolution for output */ +- double vres; /* vertical resolution for output */ +- uint32_t mode; /* bitmask of modifiers to page format */ +- uint16_t res_unit; /* resolution unit for output image */ +- unsigned int rows; /* number of section rows */ +- unsigned int cols; /* number of section cols */ ++ double width; /* width in pixels */ ++ double length; /* length in pixels */ ++ double hmargin; /* margins to subtract from width of sections */ ++ double vmargin; /* margins to subtract from height of sections */ ++ double hres; /* horizontal resolution for output */ ++ double vres; /* vertical resolution for output */ ++ uint32_t mode; /* bitmask of modifiers to page format */ ++ uint16_t res_unit; /* resolution unit for output image */ ++ unsigned int rows; /* number of section rows */ ++ unsigned int cols; /* number of section cols */ ++ uint32_t total_sections; + unsigned int orient; /* portrait, landscape, seascape, auto */ + }; + +@@ -509,6 +511,15 @@ static int writeBufferToSeparateStrips(TIFF *, uint8_t *, uint32_t, uint32_t, + tsample_t, struct dump_opts *); + static int writeBufferToSeparateTiles(TIFF *, uint8_t *, uint32_t, uint32_t, + tsample_t, struct dump_opts *); ++static int computeBitOffset32(uint32_t *, uint32_t, uint16_t, uint16_t, ++ const char *); ++static int computeSampleBitOffset32(uint32_t *, uint32_t, tsample_t, uint16_t, ++ uint16_t, const char *); ++static int computeRowSize32(uint32_t *, uint32_t, uint16_t, uint16_t, ++ const char *); ++static int computePaddedSize(tmsize_t *, tmsize_t, const char *); ++static int computeCropBufferSize32(uint32_t *, uint32_t, uint32_t, uint16_t, ++ uint16_t, const char *); + static int extractContigSamplesToBuffer(uint8_t *, uint8_t *, uint32_t, + uint32_t, tsample_t, uint16_t, uint16_t, + struct dump_opts *); +@@ -697,7 +708,7 @@ static tmsize_t maxMalloc = DEFAULT_MAX_MALLOC; + */ + static void *limitMalloc(tmsize_t s) + { +- if (maxMalloc && (s > maxMalloc)) ++ if (s < 0 || (maxMalloc && (s > maxMalloc))) + { + fprintf(stderr, + "MemoryLimitError: allocation of %" PRIu64 +@@ -942,7 +953,7 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, + uint32_t trailing_bits, prev_trailing_bits; + tmsize_t tile_rowsize = TIFFTileRowSize(in); + tmsize_t src_offset, dst_offset; +- uint32_t row_offset, col_offset; ++ tmsize_t row_offset, col_offset; + uint8_t *bufp = (uint8_t *)buf; + unsigned char *src = NULL; + unsigned char *dst = NULL; +@@ -1022,9 +1033,48 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, + return status; + } + +- row_offset = row * dst_rowsize; +- col_offset = ((col * bps * spp) + 7) / 8; +- bufp = buf + row_offset + col_offset; ++ row_offset = ++ _TIFFComputeRowOffset(in, dst_rowsize, row, "row offset"); ++ { ++ uint64_t col_bits = ++ _TIFFComputeBitOffset(in, col, spp, bps, "column offset"); ++ uint64_t col_offset64 = TIFFhowmany8_64(col_bits); ++ col_offset = ++ _TIFFCastUInt64ToSSize(in, col_offset64, "column offset"); ++ if ((col_bits == 0 && col != 0) || ++ (col_offset == 0 && col_offset64 != 0)) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "column offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ } ++ if (row_offset == 0 && row != 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating row " ++ "offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ { ++ tmsize_t total_offset = ++ _TIFFAddSSize(in, row_offset, col_offset, "buffer offset"); ++ if (total_offset == 0 && (row_offset != 0 || col_offset != 0)) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "buffer offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ bufp = buf + total_offset; ++ } + + if (col + tw > imagewidth) + ncol = imagewidth - col; +@@ -1041,10 +1091,25 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, + { + for (trow = 0; trow < nrow; trow++) + { +- src_offset = trow * tile_rowsize; +- _TIFFmemcpy(bufp, tilebuf + src_offset, +- (ncol * spp * bps) / 8); +- bufp += (imagewidth * bps * spp) / 8; ++ tmsize_t copy_bytes; ++ uint64_t copy_bytes64; ++ src_offset = _TIFFComputeRowOffset(in, tile_rowsize, trow, ++ "tile row offset"); ++ copy_bytes64 = _TIFFComputeRowSize64(in, ncol, spp, bps, ++ "tile copy size"); ++ copy_bytes = _TIFFCastUInt64ToSSize(in, copy_bytes64, ++ "tile copy size"); ++ if ((src_offset == 0 && trow != 0) || copy_bytes == 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "tile copy size"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ _TIFFmemcpy(bufp, tilebuf + src_offset, copy_bytes); ++ bufp += dst_rowsize; + } + } + else +@@ -1052,15 +1117,62 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, + /* Bit depths not a multiple of 8 and/or extract fewer than spp + * samples */ + prev_trailing_bits = trailing_bits = 0; +- trailing_bits = (ncol * bps * spp) % 8; ++ { ++ uint64_t tile_bits = _TIFFComputeBitOffset( ++ in, ncol, spp, bps, "tile trailing bits"); ++ if (tile_bits == 0 && ncol != 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "tile trailing bits"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ trailing_bits = (uint32_t)(tile_bits % 8); ++ } + + /* for (trow = 0; tl < nrow; trow++) */ + for (trow = 0; trow < nrow; trow++) + { +- src_offset = trow * tile_rowsize; ++ src_offset = _TIFFComputeRowOffset(in, tile_rowsize, trow, ++ "tile row offset"); ++ if (src_offset == 0 && trow != 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "tile row offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } + src = tilebuf + src_offset; +- dst_offset = (row + trow) * (tmsize_t)dst_rowsize; +- dst = buf + dst_offset + col_offset; ++ dst_offset = _TIFFComputeRowOffset( ++ in, dst_rowsize, row + trow, "row offset"); ++ if (dst_offset == 0 && (row + trow) != 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "row offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ { ++ tmsize_t total_offset = _TIFFAddSSize( ++ in, dst_offset, col_offset, "buffer offset"); ++ if (total_offset == 0 && ++ (dst_offset != 0 || col_offset != 0)) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow detected while " ++ "calculating buffer offset"); ++ status = 0; ++ _TIFFfree(tilebuf); ++ return status; ++ } ++ dst = buf + total_offset; ++ } + switch (shift_width) + { + case 0: +@@ -1160,7 +1272,8 @@ static int readSeparateTilesIntoBuffer(TIFF *in, uint8_t *obuf, + uint16_t bytes_per_sample; + uint32_t row, col; /* Current row and col of image */ + uint32_t nrow, ncol; /* Number of rows and cols in current tile */ +- uint32_t row_offset, col_offset; /* Output buffer offsets */ ++ tmsize_t row_offset, col_offset; /* Output buffer offsets */ ++ tmsize_t dst_rowsize; + tsize_t tbytes = 0, tilesize = TIFFTileSize(in); + tsample_t s; + uint8_t *bufp = (uint8_t *)obuf; +@@ -1223,9 +1336,45 @@ static int readSeparateTilesIntoBuffer(TIFF *in, uint8_t *obuf, + else + ncol = tw; + +- row_offset = row * (((imagewidth * spp * bps) + 7) / 8); +- col_offset = ((col * spp * bps) + 7) / 8; +- bufp = obuf + row_offset + col_offset; ++ row_offset = ++ _TIFFComputeRowOffset(in, dst_rowsize, row, "row offset"); ++ { ++ uint64_t col_bits = ++ _TIFFComputeBitOffset(in, col, spp, bps, "column offset"); ++ uint64_t col_offset64 = TIFFhowmany8_64(col_bits); ++ col_offset = ++ _TIFFCastUInt64ToSSize(in, col_offset64, "column offset"); ++ if ((col_bits == 0 && col != 0) || ++ (col_offset == 0 && col_offset64 != 0)) ++ { ++ TIFFError("readSeparateTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "column offset"); ++ status = 0; ++ break; ++ } ++ } ++ if (row_offset == 0 && row != 0) ++ { ++ TIFFError("readSeparateTilesIntoBuffer", ++ "Integer overflow detected while calculating row " ++ "offset"); ++ status = 0; ++ break; ++ } ++ { ++ tmsize_t total_offset = ++ _TIFFAddSSize(in, row_offset, col_offset, "buffer offset"); ++ if (total_offset == 0 && (row_offset != 0 || col_offset != 0)) ++ { ++ TIFFError("readSeparateTilesIntoBuffer", ++ "Integer overflow detected while calculating " ++ "buffer offset"); ++ status = 0; ++ break; ++ } ++ bufp = obuf + total_offset; ++ } + + if ((bps % 8) == 0) + { +@@ -1239,7 +1388,13 @@ static int readSeparateTilesIntoBuffer(TIFF *in, uint8_t *obuf, + } + else + { +- bytes_per_pixel = ((bps * spp) + 7) / 8; ++ uint32_t bytes_per_pixel32; ++ if (computeRowSize32(&bytes_per_pixel32, 1, spp, bps, __func__)) ++ { ++ status = 0; ++ break; ++ } ++ bytes_per_pixel = (int)bytes_per_pixel32; + if (bytes_per_pixel < (bytes_per_sample + 1)) + shift_width = bytes_per_pixel; + else +@@ -1440,11 +1595,13 @@ static int writeBufferToContigTiles(TIFF *out, uint8_t *buf, + uint16_t bps; + uint32_t tl, tw; + uint32_t row, col, nrow, ncol; +- uint32_t src_rowsize, col_offset; ++ uint32_t src_rowsize; ++ tmsize_t col_offset; + tmsize_t tile_rowsize = TIFFTileRowSize(out); + uint8_t *bufp = (uint8_t *)buf; + tsize_t tile_buffsize = 0; + tsize_t tilesize = TIFFTileSize(out); ++ tmsize_t padded_tile_buffsize; + unsigned char *tilebuf = NULL; + + if (!TIFFGetField(out, TIFFTAG_TILELENGTH, &tl) || +@@ -1505,8 +1662,39 @@ static int writeBufferToContigTiles(TIFF *out, uint8_t *buf, + else + ncol = tw; + +- col_offset = (((col * bps * spp) + 7) / 8); +- bufp = buf + (row * src_rowsize) + col_offset; ++ { ++ uint64_t col_bits = ++ _TIFFComputeBitOffset(out, col, spp, bps, "column offset"); ++ uint64_t col_offset64 = TIFFhowmany8_64(col_bits); ++ tmsize_t row_offset = ++ _TIFFComputeRowOffset(out, src_rowsize, row, "row offset"); ++ col_offset = ++ _TIFFCastUInt64ToSSize(out, col_offset64, "column offset"); ++ if ((col_bits == 0 && col != 0) || ++ (col_offset == 0 && col_offset64 != 0) || ++ (row_offset == 0 && row != 0)) ++ { ++ TIFFError(TIFFFileName(out), ++ "Error, integer overflow when computing tile " ++ "buffer offset"); ++ _TIFFfree(tilebuf); ++ return 1; ++ } ++ { ++ tmsize_t total_offset = _TIFFAddSSize( ++ out, row_offset, col_offset, "tile buffer offset"); ++ if (total_offset == 0 && ++ (row_offset != 0 || col_offset != 0)) ++ { ++ TIFFError(TIFFFileName(out), ++ "Error, integer overflow when computing tile " ++ "buffer offset"); ++ _TIFFfree(tilebuf); ++ return 1; ++ } ++ bufp = buf + total_offset; ++ } ++ } + if (extractContigSamplesToTileBuffer(tilebuf, bufp, nrow, ncol, + imagewidth, tw, 0, spp, spp, + bps, dump) > 0) +@@ -1584,8 +1772,39 @@ static int writeBufferToSeparateTiles(TIFF *out, uint8_t *buf, + else + ncol = tw; + +- col_offset = (((col * bps * spp) + 7) / 8); +- bufp = buf + (row * src_rowsize) + col_offset; ++ { ++ uint64_t col_bits = ++ _TIFFComputeBitOffset(out, col, spp, bps, "column offset"); ++ uint64_t col_offset64 = TIFFhowmany8_64(col_bits); ++ tmsize_t row_offset = ++ _TIFFComputeRowOffset(out, src_rowsize, row, "row offset"); ++ col_offset = ++ _TIFFCastUInt64ToSSize(out, col_offset64, "column offset"); ++ if ((col_bits == 0 && col != 0) || ++ (col_offset == 0 && col_offset64 != 0) || ++ (row_offset == 0 && row != 0)) ++ { ++ TIFFError(TIFFFileName(out), ++ "Error, integer overflow when computing tile " ++ "buffer offset"); ++ _TIFFfree(obuf); ++ return 1; ++ } ++ { ++ tmsize_t total_offset = _TIFFAddSSize( ++ out, row_offset, col_offset, "tile buffer offset"); ++ if (total_offset == 0 && ++ (row_offset != 0 || col_offset != 0)) ++ { ++ TIFFError(TIFFFileName(out), ++ "Error, integer overflow when computing tile " ++ "buffer offset"); ++ _TIFFfree(obuf); ++ return 1; ++ } ++ bufp = buf + total_offset; ++ } ++ } + + for (s = 0; s < spp; s++) + { +@@ -2404,6 +2623,17 @@ void process_command_opts(int argc, char *argv[], char *mp, char *mode, + "%d", MAX_SECTIONS); + exit(EXIT_FAILURE); + } ++ { ++ uint64_t total_sections64 = _TIFFMultiply64( ++ NULL, page->cols, page->rows, "subdivision count"); ++ page->total_sections = _TIFFCastUInt64ToUInt32( ++ NULL, total_sections64, "subdivision count"); ++ if (total_sections64 == 0 || page->total_sections == 0) ++ { ++ TIFFError("No subdivisions", "%u", 0U); ++ exit(EXIT_FAILURE); ++ } ++ } + page->mode |= PAGE_MODE_ROWSCOLS; + break; + case 'U': /* units for measurements and offsets */ +@@ -3168,6 +3398,103 @@ static int dump_buffer(FILE *dumpfile, int format, uint32_t rows, + return (0); + } + ++static int computeBitOffset32(uint32_t *offset, uint32_t col, uint16_t spp, ++ uint16_t bps, const char *where) ++{ ++ uint64_t offset64 = _TIFFComputeBitOffset(NULL, col, spp, bps, where); ++ uint32_t offset32 = _TIFFCastUInt64ToUInt32(NULL, offset64, "bit offset"); ++ ++ if ((offset64 == 0 && col != 0 && spp != 0 && bps != 0) || ++ (offset32 == 0 && offset64 != 0)) ++ { ++ TIFFError(where, ++ "Integer overflow detected while calculating bit offset"); ++ return (1); ++ } ++ *offset = offset32; ++ return (0); ++} ++ ++static int computeSampleBitOffset32(uint32_t *offset, uint32_t col, ++ tsample_t sample, uint16_t spp, ++ uint16_t bps, const char *where) ++{ ++ uint64_t base_offset64 = _TIFFComputeBitOffset(NULL, col, spp, bps, where); ++ uint64_t sample_offset64 = _TIFFMultiply64(NULL, sample, bps, where); ++ uint64_t offset64 = _TIFFAdd64(NULL, base_offset64, sample_offset64, where); ++ uint32_t offset32 = _TIFFCastUInt64ToUInt32(NULL, offset64, where); ++ ++ if ((base_offset64 == 0 && col != 0 && spp != 0 && bps != 0) || ++ (sample_offset64 == 0 && sample != 0 && bps != 0) || ++ (offset64 == 0 && (base_offset64 != 0 || sample_offset64 != 0)) || ++ (offset32 == 0 && offset64 != 0)) ++ { ++ TIFFError(where, ++ "Integer overflow detected while calculating sample bit " ++ "offset"); ++ return (1); ++ } ++ *offset = offset32; ++ return (0); ++} ++ ++/* ++ * Several legacy tiffcrop paths store row sizes and offsets in uint32_t. ++ * Keep those data types to avoid broader behavioral changes, but compute ++ * intermediate values with checked helpers and range-check before narrowing. ++ */ ++static int computeRowSize32(uint32_t *row_size, uint32_t width, uint16_t spp, ++ uint16_t bps, const char *where) ++{ ++ uint64_t row_size64 = _TIFFComputeRowSize64(NULL, width, spp, bps, where); ++ uint32_t row_size32 = _TIFFCastUInt64ToUInt32(NULL, row_size64, "row size"); ++ ++ if (row_size64 == 0 || row_size32 == 0) ++ { ++ TIFFError(where, ++ "Integer overflow detected while calculating row size"); ++ return (1); ++ } ++ *row_size = row_size32; ++ return (0); ++} ++ ++static int computePaddedSize(tmsize_t *padded_size, tmsize_t size, ++ const char *where) ++{ ++ tmsize_t checked_size = ++ _TIFFAddSSize(NULL, size, NUM_BUFF_OVERSIZE_BYTES, where); ++ if (checked_size == 0) ++ { ++ TIFFError(where, ++ "Integer overflow detected while calculating padded buffer " ++ "size"); ++ return (1); ++ } ++ *padded_size = checked_size; ++ return (0); ++} ++ ++static int computeCropBufferSize32(uint32_t *buffer_size, uint32_t width, ++ uint32_t length, uint16_t spp, uint16_t bps, ++ const char *where) ++{ ++ uint64_t row_size64 = _TIFFComputeRowSize64(NULL, width, spp, bps, where); ++ uint64_t rows64 = (uint64_t)length + 1U; ++ uint64_t size64 = _TIFFMultiply64(NULL, row_size64, rows64, where); ++ uint32_t size32 = _TIFFCastUInt64ToUInt32(NULL, size64, where); ++ ++ if (row_size64 == 0 || size64 == 0 || (size32 == 0 && size64 != 0)) ++ { ++ TIFFError(where, ++ "Integer overflow detected while calculating crop buffer " ++ "size"); ++ return (1); ++ } ++ *buffer_size = size32; ++ return (0); ++} ++ + /* Extract one or more samples from an interleaved buffer. If count == 1, + * only the sample plane indicated by sample will be extracted. If count > 1, + * count samples beginning at sample will be extracted. Portions of a +@@ -3305,7 +3632,8 @@ static int extractContigSamples8bits(uint8_t *in, uint8_t *out, uint32_t cols, + buff1 = buff2 = 0; + for (col = start; col < end; col++) + { /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -3398,7 +3726,8 @@ static int extractContigSamples16bits(uint8_t *in, uint8_t *out, uint32_t cols, + + for (col = start; col < end; col++) + { /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -3501,7 +3830,8 @@ static int extractContigSamples24bits(uint8_t *in, uint8_t *out, uint32_t cols, + for (col = start; col < end; col++) + { + /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -3627,7 +3957,8 @@ static int extractContigSamples32bits(uint8_t *in, uint8_t *out, uint32_t cols, + for (col = start; col < end; col++) + { + /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -3746,7 +4077,8 @@ static int extractContigSamplesShifted8bits(uint8_t *in, uint8_t *out, + buff1 = buff2 = 0; + for (col = start; col < end; col++) + { /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -3955,7 +4287,8 @@ static int extractContigSamplesShifted24bits(uint8_t *in, uint8_t *out, + for (col = start; col < end; col++) + { + /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -4072,7 +4405,8 @@ static int extractContigSamplesShifted32bits(uint8_t *in, uint8_t *out, + for (col = start; col < end; col++) + { + /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps * spp; ++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) ++ return (1); + for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); + sindex++) + { +@@ -4175,8 +4509,16 @@ static int extractContigSamplesToBuffer(uint8_t *out, uint8_t *in, + } + for (row = 0; row < rows; row++) + { +- src_offset = row * src_rowsize; +- dst_offset = row * dst_rowsize; ++ tmsize_t src_offset = ++ _TIFFComputeRowOffset(NULL, src_rowsize, row, "source row offset"); ++ tmsize_t dst_offset = _TIFFComputeRowOffset(NULL, dst_rowsize, row, ++ "destination row offset"); ++ if ((src_offset == 0 && row != 0) || (dst_offset == 0 && row != 0)) ++ { ++ TIFFError("extractContigSamplesToBuffer", ++ "Integer overflow detected while calculating row offset"); ++ return (1); ++ } + src = in + src_offset; + dst = out + dst_offset; + +@@ -4354,7 +4696,7 @@ static int combineSeparateSamplesBytes(unsigned char *srcbuffs[], + int level) + { + int i, bytes_per_sample; +- uint32_t row, col, col_offset, src_rowsize, dst_rowsize, row_offset; ++ uint32_t row, col, src_rowsize, dst_rowsize; + unsigned char *src; + unsigned char *dst; + tsample_t s; +@@ -4380,14 +4722,31 @@ static int combineSeparateSamplesBytes(unsigned char *srcbuffs[], + dump_info(dumpfile, format, "combineSeparateSamplesBytes", + "Input data, Sample %" PRIu16, s); + dump_buffer(dumpfile, format, 1, cols, row, +- srcbuffs[s] + (row * src_rowsize)); ++ srcbuffs[s] + row_offset); + } + } +- dst = out + (row * dst_rowsize); +- row_offset = row * src_rowsize; ++ dst = out + dst_offset; + for (col = 0; col < cols; col++) + { +- col_offset = row_offset + (col * (bps / 8)); ++ tmsize_t col_bytes = ++ _TIFFMultiplySSize(NULL, col, bps / 8, "column offset"); ++ tmsize_t col_offset; ++ if (col_bytes == 0 && col != 0) ++ { ++ TIFFError("combineSeparateSamplesBytes", ++ "Integer overflow detected while calculating column " ++ "offset"); ++ return (1); ++ } ++ col_offset = ++ _TIFFAddSSize(NULL, row_offset, col_bytes, "column offset"); ++ if (col_offset == 0 && (row_offset != 0 || col_bytes != 0)) ++ { ++ TIFFError("combineSeparateSamplesBytes", ++ "Integer overflow detected while calculating column " ++ "offset"); ++ return (1); ++ } + for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) + { + src = srcbuffs[s] + col_offset; +@@ -4403,7 +4762,7 @@ static int combineSeparateSamplesBytes(unsigned char *srcbuffs[], + dump_info(dumpfile, format, "combineSeparateSamplesBytes", + "Output data, combined samples"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset); + } + } + +@@ -4511,7 +4870,7 @@ static int combineSeparateSamples8bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateSamples8bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -4629,7 +4988,7 @@ static int combineSeparateSamples16bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateSamples16bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -4661,27 +5020,54 @@ static int combineSeparateSamples24bits(uint8_t *in[], uint8_t *out, + } + + /* bytes_per_sample = (bps + 7) / 8; */ +- src_rowsize = ((bps * cols) + 7) / 8; +- dst_rowsize = ((bps * cols * spp) + 7) / 8; ++ if (computeRowSize32(&src_rowsize, cols, 1, bps, __func__) || ++ computeRowSize32(&dst_rowsize, cols, spp, bps, __func__)) ++ return (1); + maskbits = (uint32_t)-1 >> (32 - bps); + + for (row = 0; row < rows; row++) + { ++ tmsize_t dst_offset_s; ++ tmsize_t src_offset_s; + ready_bits = 0; + buff1 = buff2 = 0; +- dst = out + (row * dst_rowsize); +- src_offset = row * src_rowsize; ++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); ++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); ++ src_offset = ++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); ++ if ((dst_offset_s == 0 && row != 0) || ++ (src_offset_s == 0 && row != 0) || ++ (src_offset == 0 && src_offset_s != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating row offset"); ++ return (1); ++ } ++ dst = out + dst_offset_s; + for (col = 0; col < cols; col++) + { + /* Compute src byte(s) and bits within byte(s) */ +- bit_offset = col * bps; ++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) ++ return (1); + src_byte = bit_offset / 8; + src_bit = bit_offset % 8; + + matchbits = maskbits << (32 - src_bit - bps); + for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) + { +- src = in[s] + src_offset + src_byte; ++ { ++ tmsize_t total_src_offset = ++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); ++ if (total_src_offset == 0 && ++ (src_offset != 0 || src_byte != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "source offset"); ++ return (1); ++ } ++ src = in[s] + total_src_offset; ++ } + if (little_endian) + buff1 = ((uint32_t)src[0] << 24) | + ((uint32_t)src[1] << 16) | ((uint32_t)src[2] << 8) | +@@ -4765,7 +5151,7 @@ static int combineSeparateSamples24bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateSamples24bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -5078,7 +5464,7 @@ static int combineSeparateTileSamples8bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateTileSamples8bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -5196,7 +5582,7 @@ static int combineSeparateTileSamples16bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateTileSamples16bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -5331,7 +5717,7 @@ static int combineSeparateTileSamples24bits(uint8_t *in[], uint8_t *out, + dump_info(dumpfile, format, "combineSeparateTileSamples24bits", + "Output data"); + dump_buffer(dumpfile, format, 1, dst_rowsize, row, +- out + (row * dst_rowsize)); ++ out + dst_offset_s); + } + } + +@@ -5577,7 +5963,20 @@ static int readSeparateStripsIntoBuffer(TIFF *in, uint8_t *obuf, + for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) + { + buff = srcbuffs[s]; +- strip = (s * strips_per_sample) + j; ++ { ++ uint64_t strip_offset = ++ _TIFFMultiply64(in, s, strips_per_sample, "strip index"); ++ uint64_t strip64 = ++ _TIFFAdd64(in, strip_offset, j, "strip index"); ++ strip = _TIFFCastUInt64ToUInt32(in, strip64, "strip index"); ++ if ((strip_offset == 0 && s != 0 && strips_per_sample != 0) || ++ (strip64 == 0 && (strip_offset != 0 || j != 0)) || ++ (strip == 0 && strip64 != 0)) ++ { ++ result = 0; ++ break; ++ } ++ } + bytes_read = TIFFReadEncodedStrip(in, strip, buff, stripsize); + if (bytes_read < 0) + { +@@ -5606,7 +6005,19 @@ static int readSeparateStripsIntoBuffer(TIFF *in, uint8_t *obuf, + + if (rps > rows_this_strip) + rps = rows_this_strip; +- dst = obuf + (dst_rowsize * rows_processed); ++ { ++ tmsize_t dst_offset = _TIFFComputeRowOffset( ++ in, dst_rowsize, rows_processed, "row offset"); ++ if (dst_offset == 0 && rows_processed != 0) ++ { ++ TIFFError("readSeparateStripsIntoBuffer", ++ "Integer overflow detected while calculating row " ++ "offset"); ++ result = 0; ++ break; ++ } ++ dst = obuf + dst_offset; ++ } + if ((bps % 8) == 0) + { + if (combineSeparateSamplesBytes(srcbuffs, dst, width, rps, spp, bps, +@@ -5730,6 +6141,7 @@ static void initPageSetup(struct pagedef *page, struct pageseg *pagelist, + page->vmargin = 0.0; + page->rows = 0; + page->cols = 0; ++ page->total_sections = 0; + page->orient = ORIENTATION_NONE; + + for (i = 0; i < MAX_SECTIONS; i++) +@@ -6693,20 +7105,34 @@ static int computeOutputPixelOffsets(struct crop_mask *crop, + y1 = TIFFhowmany(iwidth, olength); + y2 = TIFFhowmany(ilength, owidth); + +- if ((x1 * x2) < (y1 * y2)) +- { /* Portrait */ +- ocols = x1; +- orows = x2; +- /* orientation = ORIENTATION_PORTRAIT; */ +- } +- else +- { /* Landscape */ +- ocols = y1; +- orows = y2; +- x1 = olength; +- olength = owidth; +- owidth = x1; +- /* orientation = ORIENTATION_LANDSCAPE; */ ++ { ++ uint64_t portrait_pages = ++ _TIFFMultiply64(NULL, x1, x2, "page count"); ++ uint64_t landscape_pages = ++ _TIFFMultiply64(NULL, y1, y2, "page count"); ++ if ((portrait_pages == 0 && x1 != 0 && x2 != 0) || ++ (landscape_pages == 0 && y1 != 0 && y2 != 0)) ++ { ++ TIFFError("computeOutputPixelOffsets", ++ "Integer overflow detected while calculating " ++ "page count"); ++ return (1); ++ } ++ if (portrait_pages < landscape_pages) ++ { /* Portrait */ ++ ocols = x1; ++ orows = x2; ++ /* orientation = ORIENTATION_PORTRAIT; */ ++ } ++ else ++ { /* Landscape */ ++ ocols = y1; ++ orows = y2; ++ x1 = olength; ++ olength = owidth; ++ owidth = x1; ++ /* orientation = ORIENTATION_LANDSCAPE; */ ++ } + } + } + +@@ -6737,15 +7163,44 @@ static int computeOutputPixelOffsets(struct crop_mask *crop, + } + page->cols = ocols; + +- line_bytes = TIFFhowmany8(owidth * image->spp * image->bps); +- +- if ((orows * ocols) > MAX_SECTIONS) ++ if ((orows == 0) || (ocols == 0) || (ocols > (MAX_SECTIONS / orows))) + { + TIFFError("computeOutputPixelOffsets", + "Rows and Columns exceed maximum sections\nIncrease " + "resolution or reduce sections"); + return (-1); + } ++ { ++ uint64_t total_sections64 = ++ _TIFFMultiply64(NULL, orows, ocols, "subdivision count"); ++ page->total_sections = _TIFFCastUInt64ToUInt32(NULL, total_sections64, ++ "subdivision count"); ++ if (total_sections64 == 0 || page->total_sections == 0) ++ { ++ TIFFError("computeOutputPixelOffsets", ++ "Integer overflow computing subdivision count"); ++ return (-1); ++ } ++ } ++ ++ { ++ uint64_t line_bytes64 = _TIFFComputeRowSize64( ++ NULL, owidth, image->spp, image->bps, "section row size"); ++ if (line_bytes64 == 0) ++ { ++ TIFFError("computeOutputPixelOffsets", ++ "Integer overflow detected while calculating row size"); ++ return (-1); ++ } ++ line_bytes = ++ _TIFFCastUInt64ToUInt32(NULL, line_bytes64, "section row size"); ++ if (line_bytes == 0) ++ { ++ TIFFError("computeOutputPixelOffsets", ++ "Section row size exceeds UINT32_MAX"); ++ return (-1); ++ } ++ } + + /* build the list of offsets for each output section */ + for (k = 0, i = 0; i < orows; i++) +@@ -7043,13 +7498,13 @@ static int loadImage(TIFF *in, struct image_data *image, struct dump_opts *dump, + exit(EXIT_FAILURE); + } + +- if (nstrips != 0 && stsize > (tmsize_t)(TIFF_TMSIZE_T_MAX / nstrips)) ++ buffsize = _TIFFMultiplySSize(in, stsize, nstrips, "strip buffer size"); ++ if (buffsize == 0) + { + TIFFError("loadImage", + "Integer overflow when calculating buffer size"); + exit(EXIT_FAILURE); + } +- buffsize = stsize * nstrips; + /* The buffsize_check and the possible adaptation of buffsize + * has to account also for padding of each line to a byte boundary. + * This is assumed by mirrorImage() and rotateImage(). +@@ -7057,25 +7512,39 @@ static int loadImage(TIFF *in, struct image_data *image, struct dump_opts *dump, + * need a buffer, which is at least 3 bytes larger than the actual + * image. Otherwise buffer-overflow might occur there. + */ +- if ((spp != 0 && bps != 0 && +- width > (uint32_t)((UINT32_MAX - 7) / spp / bps)) || +- (width != 0 && spp != 0 && bps != 0 && +- length > (tmsize_t)(TIFF_TMSIZE_T_MAX / +- (uint32_t)(((width * spp * bps) + 7) / 8)))) + { +- TIFFError("loadImage", "Integer overflow detected."); +- exit(EXIT_FAILURE); ++ uint64_t rowbytes64 = _TIFFComputeRowSize64(in, width, spp, bps, ++ "loadImage row size"); ++ tmsize_t rowbytes; ++ if (rowbytes64 == 0) ++ { ++ TIFFError("loadImage", "Integer overflow detected."); ++ exit(EXIT_FAILURE); ++ } ++ rowbytes = ++ _TIFFCastUInt64ToSSize(in, rowbytes64, "loadImage row size"); ++ if (rowbytes == 0) ++ { ++ TIFFError("loadImage", "Integer overflow detected."); ++ exit(EXIT_FAILURE); ++ } ++ buffsize_check = _TIFFMultiplySSize(in, (tmsize_t)length, rowbytes, ++ "loadImage buffer size"); ++ if (buffsize_check == 0) ++ { ++ TIFFError("loadImage", "Integer overflow detected."); ++ exit(EXIT_FAILURE); ++ } + } +- buffsize_check = +- (tmsize_t)length * (uint32_t)(((width * spp * bps) + 7) / 8); + if (buffsize < buffsize_check) + { + buffsize = buffsize_check; + #ifdef DEBUG2 + TIFFError("loadImage", +- "Stripsize %" PRIu32 " is too small, using imagelength * " +- "width * spp * bps / 8 = %" PRIu32, +- stsize, (unsigned long)buffsize); ++ "Stripsize %" TIFF_SSIZE_FORMAT ++ " is too small, using imagelength * row size = " ++ "%" TIFF_SSIZE_FORMAT, ++ stsize, buffsize); + #endif + } + +@@ -7291,6 +7760,7 @@ static int extractCompositeRegions(struct image_data *image, + uint32_t src_rowsize, dst_rowsize, src_offset, dst_offset; + uint32_t crop_width, crop_length, img_width /*, img_length */; + uint32_t prev_length, prev_width, composite_width; ++ uint64_t crop_bits64 = 0; + uint16_t bps, spp; + uint8_t *src, *dst; + tsample_t count, sample = 0; /* Update to extract one or more samples */ +@@ -7377,8 +7847,9 @@ static int extractCompositeRegions(struct image_data *image, + crop->regionlist[i].width = crop_width; + crop->regionlist[i].length = crop_length; + +- src_rowsize = ((img_width * bps * spp) + 7) / 8; +- dst_rowsize = (((crop_width * bps * count) + 7) / 8); ++ if (computeRowSize32(&src_rowsize, img_width, spp, bps, __func__) || ++ computeRowSize32(&dst_rowsize, crop_width, count, bps, __func__)) ++ return (1); + + switch (crop->edge_ref) + { +@@ -7399,10 +7870,41 @@ static int extractCompositeRegions(struct image_data *image, + + for (row = first_row; row <= last_row; row++) + { +- src_offset = row * src_rowsize; +- dst_offset = (row - first_row) * dst_rowsize; ++ tmsize_t src_offset_s = ++ _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); ++ tmsize_t dst_offset_s = _TIFFComputeRowOffset( ++ NULL, dst_rowsize, row - first_row, __func__); ++ src_offset = _TIFFCastUInt64ToUInt32( ++ NULL, (uint64_t)src_offset_s, __func__); ++ dst_offset = _TIFFCastUInt64ToUInt32( ++ NULL, (uint64_t)dst_offset_s, __func__); ++ if ((src_offset_s == 0 && row != 0) || ++ (dst_offset_s == 0 && row != first_row) || ++ (src_offset == 0 && src_offset_s != 0) || ++ (dst_offset == 0 && dst_offset_s != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "row offset"); ++ return (1); ++ } + src = read_buff + src_offset; +- dst = crop_buff + dst_offset + (prev_length * dst_rowsize); ++ { ++ tmsize_t prev_offset_s = _TIFFComputeRowOffset( ++ NULL, dst_rowsize, prev_length, __func__); ++ tmsize_t total_dst_offset = _TIFFAddSSize( ++ NULL, dst_offset_s, prev_offset_s, __func__); ++ if ((prev_offset_s == 0 && prev_length != 0) || ++ (total_dst_offset == 0 && ++ (dst_offset_s != 0 || prev_offset_s != 0))) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while " ++ "calculating buffer offset"); ++ return (1); ++ } ++ dst = crop_buff + total_dst_offset; ++ } + switch (shift_width) + { + case 0: +@@ -7489,14 +7991,55 @@ static int extractCompositeRegions(struct image_data *image, + } + crop->combined_width += crop_width; + crop->combined_length = crop_length; +- dst_rowsize = (((composite_width * bps * count) + 7) / 8); +- trailing_bits = (crop_width * bps * count) % 8; ++ if (computeRowSize32(&dst_rowsize, composite_width, count, bps, ++ __func__)) ++ return (1); ++ { ++ crop_bits64 = _TIFFComputeBitOffset(NULL, crop_width, count, ++ bps, __func__); ++ if (crop_bits64 == 0 && crop_width != 0) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "trailing bits"); ++ return (1); ++ } ++ trailing_bits = (uint32_t)(crop_bits64 % 8); ++ } + for (row = first_row; row <= last_row; row++) + { +- src_offset = row * src_rowsize; +- dst_offset = (row - first_row) * dst_rowsize; ++ tmsize_t src_offset_s = ++ _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); ++ tmsize_t dst_offset_s = _TIFFComputeRowOffset( ++ NULL, dst_rowsize, row - first_row, __func__); ++ src_offset = _TIFFCastUInt64ToUInt32( ++ NULL, (uint64_t)src_offset_s, __func__); ++ dst_offset = _TIFFCastUInt64ToUInt32( ++ NULL, (uint64_t)dst_offset_s, __func__); ++ if ((src_offset_s == 0 && row != 0) || ++ (dst_offset_s == 0 && row != first_row) || ++ (src_offset == 0 && src_offset_s != 0) || ++ (dst_offset == 0 && dst_offset_s != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "row offset"); ++ return (1); ++ } + src = read_buff + src_offset; +- dst = crop_buff + dst_offset + prev_width; ++ { ++ tmsize_t total_dst_offset = _TIFFAddSSize( ++ NULL, dst_offset_s, prev_width, __func__); ++ if (total_dst_offset == 0 && ++ (dst_offset_s != 0 || prev_width != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while " ++ "calculating buffer offset"); ++ return (1); ++ } ++ dst = crop_buff + total_dst_offset; ++ } + + switch (shift_width) + { +@@ -7641,13 +8184,29 @@ static int extractSeparateRegion(struct image_data *image, + + src = read_buff; + dst = crop_buff; +- src_rowsize = ((img_width * bps * spp) + 7) / 8; +- dst_rowsize = (((crop_width * bps * spp) + 7) / 8); ++ if (computeRowSize32(&src_rowsize, img_width, spp, bps, __func__) || ++ computeRowSize32(&dst_rowsize, crop_width, spp, bps, __func__)) ++ return (1); + + for (row = first_row; row <= last_row; row++) + { +- src_offset = row * src_rowsize; +- dst_offset = (row - first_row) * dst_rowsize; ++ tmsize_t src_offset_s = ++ _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); ++ tmsize_t dst_offset_s = ++ _TIFFComputeRowOffset(NULL, dst_rowsize, row - first_row, __func__); ++ src_offset = ++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); ++ dst_offset = ++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)dst_offset_s, __func__); ++ if ((src_offset_s == 0 && row != 0) || ++ (dst_offset_s == 0 && row != first_row) || ++ (src_offset == 0 && src_offset_s != 0) || ++ (dst_offset == 0 && dst_offset_s != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating row offset"); ++ return (1); ++ } + src = read_buff + src_offset; + dst = crop_buff + dst_offset; + +@@ -7814,11 +8373,42 @@ static int extractImageSection(struct image_data *image, + + if ((bps % 8) == 0) + { +- col_offset = (first_col * spp * bps) / 8; ++ uint64_t first_col_bits = _TIFFComputeBitOffset( ++ NULL, first_col, spp, bps, "section column offset"); ++ col_offset = _TIFFCastUInt64ToUInt32(NULL, first_col_bits / 8, ++ "section column offset"); ++ if ((first_col_bits == 0 && first_col != 0) || ++ (col_offset == 0 && first_col_bits != 0)) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing section column offset"); ++ return (1); ++ } + for (row = first_row; row <= last_row; row++) + { +- row_offset = row * img_rowsize; +- src_offset = row_offset + col_offset; ++ tmsize_t row_offset_s = ++ _TIFFComputeRowOffset(NULL, img_rowsize, row, "row offset"); ++ uint64_t src_offset64; ++ row_offset = _TIFFCastUInt64ToUInt32(NULL, (uint64_t)row_offset_s, ++ "row offset"); ++ if ((row_offset_s == 0 && row != 0) || ++ (row_offset == 0 && row_offset_s != 0)) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing row offset"); ++ return (1); ++ } ++ src_offset64 = _TIFFAdd64(NULL, row_offset, col_offset, ++ "section source offset"); ++ src_offset = _TIFFCastUInt64ToUInt32(NULL, src_offset64, ++ "section source offset"); ++ if ((src_offset64 == 0 && (row_offset != 0 || col_offset != 0)) || ++ (src_offset == 0 && src_offset64 != 0)) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing source offset"); ++ return (1); ++ } + + #ifdef DEVELMODE + TIFFError("", "Src offset: %8" PRIu32 ", Dst offset: %8" PRIu32, +@@ -7831,16 +8421,45 @@ static int extractImageSection(struct image_data *image, + } + else + { /* bps != 8 */ +- shift1 = +- ((first_col * spp * bps) % +- 8); /* shift1 = bits to skip in the first byte of source buffer*/ ++ uint64_t first_col_bits = _TIFFComputeBitOffset( ++ NULL, first_col, spp, bps, "section column offset"); ++ if (first_col_bits == 0 && first_col != 0) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing section column offset"); ++ return (1); ++ } ++ shift1 = (uint32_t)(first_col_bits % 8); ++ /* shift1 = bits to skip in the first byte of source buffer */ + for (row = first_row; row <= last_row; row++) + { + /* pull out the first byte */ +- row_offset = row * img_rowsize; +- offset1 = row_offset + ((first_col * spp * bps) / +- 8); /* offset1 = offset into source of byte +- with first bits to be extracted */ ++ tmsize_t row_offset_s = ++ _TIFFComputeRowOffset(NULL, img_rowsize, row, "row offset"); ++ uint64_t offset1_64; ++ row_offset = _TIFFCastUInt64ToUInt32(NULL, (uint64_t)row_offset_s, ++ "row offset"); ++ if ((row_offset_s == 0 && row != 0) || ++ (row_offset == 0 && row_offset_s != 0)) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing row offset"); ++ return (1); ++ } ++ offset1_64 = _TIFFAdd64(NULL, row_offset, first_col_bits / 8, ++ "section source offset"); ++ offset1 = _TIFFCastUInt64ToUInt32(NULL, offset1_64, ++ "section source offset"); ++ if ((offset1_64 == 0 && ++ (row_offset != 0 || (first_col_bits / 8) != 0)) || ++ (offset1 == 0 && offset1_64 != 0)) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing source offset"); ++ return (1); ++ } ++ /* offset1 = offset into source of byte with first bits to be ++ * extracted */ + + #ifdef DEVELMODE + for (j = 0, k = 7; j < 8; j++, k--) +@@ -8509,7 +9128,7 @@ static int createImageSection(uint32_t sectsize, unsigned char **sect_buff_ptr) + "Unable to allocate/reallocate section buffer"); + return (-1); + } +- _TIFFmemset(sect_buff, 0, sectsize + NUM_BUFF_OVERSIZE_BYTES); ++ _TIFFmemset(sect_buff, 0, padded_sectsize); + } + } + +@@ -8529,6 +9148,7 @@ static int processCropSelections(struct image_data *image, + int i; + uint32_t width, length, total_width, total_length; + tsize_t cropsize; ++ tmsize_t padded_cropsize; + unsigned char *crop_buff = NULL; + unsigned char *read_buff = NULL; + unsigned char *next_buff = NULL; +@@ -8804,6 +9424,7 @@ static int createCroppedImage(struct image_data *image, struct crop_mask *crop, + unsigned char *read_buff = NULL; + unsigned char *crop_buff = NULL; + unsigned char *new_buff = NULL; ++ tmsize_t padded_cropsize; + static tsize_t prev_cropsize = 0; + + read_buff = *read_buff_ptr; +@@ -8854,7 +9475,7 @@ static int createCroppedImage(struct image_data *image, struct crop_mask *crop, + "Unable to allocate/reallocate crop buffer"); + return (-1); + } +- _TIFFmemset(crop_buff, 0, cropsize + NUM_BUFF_OVERSIZE_BYTES); ++ _TIFFmemset(crop_buff, 0, padded_cropsize); + } + } + +@@ -9638,10 +10259,11 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { + int shift_width; + uint32_t bytes_per_pixel, bytes_per_sample; +- uint32_t row, rowsize, src_offset, dst_offset; ++ uint32_t row, rowsize; + uint32_t i, col, width, length; +- uint32_t colsize, col_offset, pix_offset; +- tmsize_t buffsize; ++ uint32_t colsize, pix_offset; ++ tmsize_t src_offset, dst_offset, col_offset; ++ tmsize_t buffsize, allocsize; + unsigned char *ibuff; + unsigned char *src; + unsigned char *dst; +@@ -9750,8 +10372,20 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { /* non 8 bit per sample data */ + for (row = 0; row < length; row++) + { +- src_offset = row * rowsize; +- dst_offset = (length - row - 1) * rowsize; ++ uint32_t dst_row = length - row - 1; ++ src_offset = ++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); ++ dst_offset = ++ _TIFFComputeRowOffset(NULL, rowsize, dst_row, __func__); ++ if ((src_offset == 0 && row != 0) || ++ (dst_offset == 0 && dst_row != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "row offset"); ++ _TIFFfree(rbuff); ++ return (-1); ++ } + src = ibuff + src_offset; + dst = rbuff + dst_offset; + switch (shift_width) +@@ -9806,9 +10440,26 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { + for (col = 0; col < width; col++) + { +- src_offset = +- ((length - 1) * rowsize) + (col * bytes_per_pixel); +- dst_offset = col * colsize; ++ tmsize_t src_row_offset = _TIFFComputeRowOffset( ++ NULL, rowsize, length - 1, __func__); ++ tmsize_t src_col_offset = _TIFFMultiplySSize( ++ NULL, col, bytes_per_pixel, "column offset"); ++ src_offset = _TIFFAddSSize(NULL, src_row_offset, ++ src_col_offset, __func__); ++ dst_offset = ++ _TIFFComputeRowOffset(NULL, colsize, col, __func__); ++ if ((src_row_offset == 0 && length != 1) || ++ (src_col_offset == 0 && col != 0) || ++ (src_offset == 0 && ++ (src_row_offset != 0 || src_col_offset != 0)) || ++ (dst_offset == 0 && col != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "rotation offset"); ++ _TIFFfree(rbuff); ++ return (-1); ++ } + src = ibuff + src_offset; + dst = rbuff + dst_offset; + for (row = length; row > 0; row--) +@@ -9823,8 +10474,19 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { /* non 8 bit per sample data */ + for (col = 0; col < width; col++) + { +- src_offset = (length - 1) * rowsize; +- dst_offset = col * colsize; ++ src_offset = _TIFFComputeRowOffset(NULL, rowsize, ++ length - 1, __func__); ++ dst_offset = ++ _TIFFComputeRowOffset(NULL, colsize, col, __func__); ++ if ((src_offset == 0 && length != 1) || ++ (dst_offset == 0 && col != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "rotation offset"); ++ _TIFFfree(rbuff); ++ return (-1); ++ } + src = ibuff + src_offset; + dst = rbuff + dst_offset; + switch (shift_width) +@@ -9898,8 +10560,20 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { + for (col = 0; col < width; col++) + { +- src_offset = col * bytes_per_pixel; +- dst_offset = (width - col - 1) * colsize; ++ uint32_t dst_row = width - col - 1; ++ src_offset = _TIFFMultiplySSize(NULL, col, bytes_per_pixel, ++ "column offset"); ++ dst_offset = ++ _TIFFComputeRowOffset(NULL, colsize, dst_row, __func__); ++ if ((src_offset == 0 && col != 0) || ++ (dst_offset == 0 && dst_row != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "rotation offset"); ++ _TIFFfree(rbuff); ++ return (-1); ++ } + src = ibuff + src_offset; + dst = rbuff + dst_offset; + for (row = length; row > 0; row--) +@@ -9914,8 +10588,18 @@ static int rotateImage(uint16_t rotation, struct image_data *image, + { /* non 8 bit per sample data */ + for (col = 0; col < width; col++) + { ++ uint32_t dst_row = width - col - 1; + src_offset = 0; +- dst_offset = (width - col - 1) * colsize; ++ dst_offset = ++ _TIFFComputeRowOffset(NULL, colsize, dst_row, __func__); ++ if (dst_offset == 0 && dst_row != 0) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "rotation offset"); ++ _TIFFfree(rbuff); ++ return (-1); ++ } + src = ibuff + src_offset; + dst = rbuff + dst_offset; + switch (shift_width) +@@ -10316,7 +11000,8 @@ static int reverseSamplesBytes(uint16_t spp, uint16_t bps, uint32_t width, + uint8_t *src, uint8_t *dst) + { + int i; +- uint32_t col, bytes_per_pixel, col_offset; ++ uint32_t col, bytes_per_pixel; ++ tmsize_t col_offset; + uint8_t bytebuff1; + unsigned char swapbuff[32]; + +@@ -10340,7 +11025,15 @@ static int reverseSamplesBytes(uint16_t spp, uint16_t bps, uint32_t width, + case 2: + for (col = 0; col < (width / 2); col++) + { +- col_offset = col * bytes_per_pixel; ++ col_offset = _TIFFMultiplySSize(NULL, col, bytes_per_pixel, ++ "column offset"); ++ if (col_offset == 0 && col != 0) ++ { ++ TIFFError("reverseSamplesBytes", ++ "Integer overflow detected while calculating " ++ "column offset"); ++ return (1); ++ } + _TIFFmemcpy(swapbuff, src + col_offset, bytes_per_pixel); + _TIFFmemcpy(src + col_offset, + dst - col_offset - bytes_per_pixel, +@@ -10375,29 +11068,44 @@ static int mirrorImage(uint16_t spp, uint16_t bps, uint16_t mirror, + { + int shift_width; + uint32_t bytes_per_pixel, bytes_per_sample; +- uint32_t row, rowsize, row_offset; ++ uint32_t row, rowsize; ++ tmsize_t row_offset; ++ tmsize_t padded_rowsize; + unsigned char *line_buff = NULL; + unsigned char *src; + unsigned char *dst; + + src = ibuff; +- rowsize = ((width * bps * spp) + 7) / 8; ++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) ++ return (-1); ++ if (computePaddedSize(&padded_rowsize, rowsize, __func__)) ++ return (-1); + switch (mirror) + { + case MIRROR_BOTH: + case MIRROR_VERT: +- line_buff = +- (unsigned char *)limitMalloc(rowsize + NUM_BUFF_OVERSIZE_BYTES); ++ line_buff = (unsigned char *)limitMalloc(padded_rowsize); + if (line_buff == NULL) + { + TIFFError("mirrorImage", +- "Unable to allocate mirror line buffer of %1u bytes", +- rowsize + NUM_BUFF_OVERSIZE_BYTES); ++ "Unable to allocate mirror line buffer of " ++ "%" TIFF_SSIZE_FORMAT " bytes", ++ padded_rowsize); + return (-1); + } +- _TIFFmemset(line_buff, '\0', rowsize + NUM_BUFF_OVERSIZE_BYTES); ++ _TIFFmemset(line_buff, '\0', padded_rowsize); + +- dst = ibuff + (rowsize * (length - 1)); ++ row_offset = ++ _TIFFComputeRowOffset(NULL, rowsize, length - 1, __func__); ++ if (row_offset == 0 && length != 1) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating row " ++ "offset"); ++ _TIFFfree(line_buff); ++ return (-1); ++ } ++ dst = ibuff + row_offset; + for (row = 0; row < length / 2; row++) + { + _TIFFmemcpy(line_buff, src, rowsize); +@@ -10416,9 +11124,30 @@ static int mirrorImage(uint16_t spp, uint16_t bps, uint16_t mirror, + { + for (row = 0; row < length; row++) + { +- row_offset = row * rowsize; ++ tmsize_t row_offset_s = ++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); ++ if (row_offset_s == 0 && row != 0) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "row offset"); ++ return (-1); ++ } ++ row_offset = row_offset_s; + src = ibuff + row_offset; +- dst = ibuff + row_offset + rowsize; ++ { ++ tmsize_t end_offset = ++ _TIFFAddSSize(NULL, row_offset, rowsize, __func__); ++ if (end_offset == 0 && ++ (row_offset != 0 || rowsize != 0)) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while " ++ "calculating row offset"); ++ return (-1); ++ } ++ dst = ibuff + end_offset; ++ } + if (reverseSamplesBytes(spp, bps, width, src, dst)) + { + return (-1); +@@ -10444,10 +11173,19 @@ static int mirrorImage(uint16_t spp, uint16_t bps, uint16_t mirror, + + for (row = 0; row < length; row++) + { +- row_offset = row * rowsize; ++ tmsize_t row_offset_s = ++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); ++ if (row_offset_s == 0 && row != 0) ++ { ++ TIFFError(__func__, ++ "Integer overflow detected while calculating " ++ "row offset"); ++ _TIFFfree(line_buff); ++ return (-1); ++ } ++ row_offset = row_offset_s; + src = ibuff + row_offset; +- _TIFFmemset(line_buff, '\0', +- rowsize + NUM_BUFF_OVERSIZE_BYTES); ++ _TIFFmemset(line_buff, '\0', padded_rowsize); + switch (shift_width) + { + case 1: +diff --git a/archive/tools/tiffcrop.c.rej b/archive/tools/tiffcrop.c.rej +new file mode 100644 +index 0000000..aac7a0a +--- /dev/null ++++ b/archive/tools/tiffcrop.c.rej +@@ -0,0 +1,2413 @@ ++diff a/archive/tools/tiffcrop.c b/archive/tools/tiffcrop.c (rejected hunks) ++@@ -951,7 +962,8 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, ++ unsigned char *tilebuf = NULL; ++ ++ bytes_per_sample = (uint32_t)((bps + 7) / 8); ++- bytes_per_pixel = (uint32_t)(((bps * spp) + 7) / 8); +++ if (computeRowSize32(&bytes_per_pixel, 1, spp, bps, __func__)) +++ return 0; ++ ++ if ((bps % 8) == 0) ++ shift_width = 0; ++@@ -971,40 +983,55 @@ static int readContigTilesIntoBuffer(TIFF *in, uint8_t *buf, ++ exit(EXIT_FAILURE); ++ } ++ ++- if (tilesize < (tsize_t)(tl * tile_rowsize)) ++ { ++-#ifdef DEBUG2 ++- TIFFError("readContigTilesIntoBuffer", ++- "Tilesize %" PRId64 ++- " is too small, using alternate calculation %" PRIu64, ++- tilesize, tl * tile_rowsize); ++-#endif ++- if (tile_rowsize != 0 && ++- (tmsize_t)tl > (TIFF_TMSIZE_T_MAX / tile_rowsize)) +++ tmsize_t calculated_tile_size = +++ _TIFFMultiplySSize(in, tile_rowsize, tl, "tile buffer size"); +++ if (calculated_tile_size == 0) ++ { ++ TIFFError("readContigTilesIntoBuffer", ++ "Integer overflow when calculating buffer size."); ++ exit(EXIT_FAILURE); ++ } ++- tile_buffsize = tl * tile_rowsize; +++ if (tilesize < calculated_tile_size) +++ { +++#ifdef DEBUG2 +++ TIFFError("readContigTilesIntoBuffer", +++ "Tilesize %" TIFF_SSIZE_FORMAT +++ " is too small, using alternate calculation " +++ "%" TIFF_SSIZE_FORMAT, +++ tilesize, calculated_tile_size); +++#endif +++ tile_buffsize = calculated_tile_size; +++ } ++ } ++ ++ /* Add 3 padding bytes for extractContigSamplesShifted32bits */ ++- if ((size_t)tile_buffsize > TIFF_TMSIZE_T_MAX - NUM_BUFF_OVERSIZE_BYTES) ++ { ++- TIFFError("readContigTilesIntoBuffer", ++- "Integer overflow when calculating buffer size."); ++- exit(EXIT_FAILURE); +++ tmsize_t padded_tile_buffsize; +++ if (computePaddedSize(&padded_tile_buffsize, tile_buffsize, +++ "readContigTilesIntoBuffer")) +++ exit(EXIT_FAILURE); +++ tilebuf = (unsigned char *)limitMalloc(padded_tile_buffsize); ++ } ++- tilebuf = ++- (unsigned char *)limitMalloc(tile_buffsize + NUM_BUFF_OVERSIZE_BYTES); ++ if (tilebuf == 0) ++ return 0; ++ tilebuf[tile_buffsize] = 0; ++ tilebuf[tile_buffsize + 1] = 0; ++ tilebuf[tile_buffsize + 2] = 0; ++ ++- dst_rowsize = ((imagewidth * bps * spp) + 7) / 8; +++ { +++ uint64_t dst_rowsize64 = _TIFFComputeRowSize64(in, imagewidth, spp, bps, +++ "destination row size"); +++ dst_rowsize = +++ _TIFFCastUInt64ToUInt32(in, dst_rowsize64, "destination row size"); +++ if (dst_rowsize64 == 0 || dst_rowsize == 0) +++ { +++ TIFFError("readContigTilesIntoBuffer", +++ "Integer overflow detected while calculating row size"); +++ _TIFFfree(tilebuf); +++ return 0; +++ } +++ } ++ for (row = 0; row < imagelength; row += tl) ++ { ++ nrow = (row + tl > imagelength) ? imagelength - row : tl; ++@@ -1167,22 +1296,40 @@ static int readSeparateTilesIntoBuffer(TIFF *in, uint8_t *obuf, ++ unsigned char *tbuff = NULL; ++ ++ bytes_per_sample = (uint16_t)((bps + 7) / 8); ++- ++- for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++) ++ { ++- srcbuffs[sample] = NULL; ++- tbuff = ++- (unsigned char *)limitMalloc(tilesize + NUM_BUFF_OVERSIZE_BYTES); ++- if (!tbuff) +++ uint64_t dst_rowsize64 = _TIFFComputeRowSize64(in, imagewidth, spp, bps, +++ "destination row size"); +++ dst_rowsize = +++ _TIFFCastUInt64ToSSize(in, dst_rowsize64, "destination row size"); +++ if (dst_rowsize64 == 0 || dst_rowsize == 0) ++ { ++ TIFFError("readSeparateTilesIntoBuffer", ++- "Unable to allocate tile read buffer for sample %d", ++- sample); ++- for (i = 0; i < sample; i++) ++- _TIFFfree(srcbuffs[i]); +++ "Integer overflow detected while calculating row size"); +++ return 0; +++ } +++ } +++ +++ { +++ tmsize_t padded_tilesize; +++ if (computePaddedSize(&padded_tilesize, tilesize, +++ "readSeparateTilesIntoBuffer")) ++ return 0; +++ +++ for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++) +++ { +++ srcbuffs[sample] = NULL; +++ tbuff = (unsigned char *)limitMalloc(padded_tilesize); +++ if (!tbuff) +++ { +++ TIFFError("readSeparateTilesIntoBuffer", +++ "Unable to allocate tile read buffer for sample %d", +++ sample); +++ for (i = 0; i < sample; i++) +++ _TIFFfree(srcbuffs[i]); +++ return 0; +++ } +++ srcbuffs[sample] = tbuff; ++ } ++- srcbuffs[sample] = tbuff; ++ } ++ /* Each tile contains only the data for a single plane ++ * arranged in scanlines of tw * bytes_per_sample bytes. ++@@ -1350,21 +1539,14 @@ static int writeBufferToSeparateStrips(TIFF *out, uint8_t *buf, uint32_t length, ++ tstrip_t strip = 0; ++ tsize_t stripsize = TIFFStripSize(out); ++ tsize_t rowstripsize, scanlinesize = TIFFScanlineSize(out); +++ tmsize_t padded_rowstripsize; ++ tdata_t obuf; ++ ++ (void)TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &local_rowsperstrip); ++ (void)TIFFGetFieldDefaulted(out, TIFFTAG_BITSPERSAMPLE, &bps); ++ bytes_per_sample = (uint32_t)((bps + 7) / 8); ++- if (width == 0 || (uint32_t)bps * (uint32_t)spp > UINT32_MAX / width || ++- (uint32_t)bps * (uint32_t)spp * width > UINT32_MAX - 7U) ++- { ++- TIFFError( ++- TIFFFileName(out), ++- "Error, uint32_t overflow when computing (bps * spp * width) + 7"); ++- return 1; ++- } ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7U) / ++- 8; /* source has interleaved samples */ +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) +++ return 1; /* source has interleaved samples */ ++ if (bytes_per_sample == 0 || ++ local_rowsperstrip > UINT32_MAX / bytes_per_sample || ++ local_rowsperstrip * bytes_per_sample > UINT32_MAX / (width + 1)) ++@@ -1377,7 +1559,9 @@ static int writeBufferToSeparateStrips(TIFF *out, uint8_t *buf, uint32_t length, ++ rowstripsize = (tsize_t)local_rowsperstrip * bytes_per_sample * (width + 1); ++ ++ /* Add 3 padding bytes for extractContigSamples32bits */ ++- obuf = limitMalloc(rowstripsize + NUM_BUFF_OVERSIZE_BYTES); +++ if (computePaddedSize(&padded_rowstripsize, rowstripsize, __func__)) +++ return 1; +++ obuf = limitMalloc(padded_rowstripsize); ++ if (obuf == NULL) ++ return 1; ++ ++@@ -1389,9 +1573,20 @@ static int writeBufferToSeparateStrips(TIFF *out, uint8_t *buf, uint32_t length, ++ : local_rowsperstrip; ++ ++ stripsize = TIFFVStripSize(out, nrows); ++- src = buf + (row * rowsize); ++- memset(obuf, '\0', ++- (size_t)(rowstripsize + NUM_BUFF_OVERSIZE_BYTES)); +++ { +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(out, rowsize, row, __func__); +++ if (row_offset == 0 && row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row " +++ "offset"); +++ _TIFFfree(obuf); +++ return 1; +++ } +++ src = buf + row_offset; +++ } +++ memset(obuf, '\0', (size_t)padded_rowstripsize); ++ if (extractContigSamplesToBuffer((uint8_t *)obuf, src, nrows, width, ++ s, spp, bps, dump)) ++ { ++@@ -1462,41 +1659,49 @@ static int writeBufferToContigTiles(TIFF *out, uint8_t *buf, ++ exit(EXIT_FAILURE); ++ } ++ ++- tile_buffsize = tilesize; ++- if (tilesize < (tsize_t)(tl * tile_rowsize)) ++ { ++-#ifdef DEBUG2 ++- TIFFError("writeBufferToContigTiles", ++- "Tilesize %" PRId64 ++- " is too small, using alternate calculation %" PRIu32, ++- tilesize, tl * tile_rowsize); ++-#endif ++- if (tile_rowsize != 0 && ++- (tmsize_t)tl > (TIFF_TMSIZE_T_MAX / tile_rowsize)) +++ tmsize_t calculated_tile_size = +++ _TIFFMultiplySSize(out, tile_rowsize, tl, "tile buffer size"); +++ if (calculated_tile_size == 0) ++ { ++ TIFFError("writeBufferToContigTiles", ++ "Integer overflow when calculating buffer size"); ++ exit(EXIT_FAILURE); ++ } ++- tile_buffsize = tl * tile_rowsize; +++ tile_buffsize = tilesize; +++ if (tilesize < calculated_tile_size) +++ { +++#ifdef DEBUG2 +++ TIFFError("writeBufferToContigTiles", +++ "Tilesize %" TIFF_SSIZE_FORMAT +++ " is too small, using alternate calculation " +++ "%" TIFF_SSIZE_FORMAT, +++ tilesize, calculated_tile_size); +++#endif +++ tile_buffsize = calculated_tile_size; +++ } ++ } ++ ++- if (imagewidth == 0 || ++- (uint32_t)bps * (uint32_t)spp > UINT32_MAX / imagewidth || ++- (uint32_t)bps * (uint32_t)spp * imagewidth > UINT32_MAX - 7U) ++ { ++- TIFFError(TIFFFileName(out), "Error, uint32_t overflow when computing " ++- "(imagewidth * bps * spp) + 7"); ++- return 1; +++ uint64_t src_rowsize64 = +++ _TIFFComputeRowSize64(out, imagewidth, spp, bps, "source row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(out, src_rowsize64, "source row size"); +++ if (src_rowsize64 == 0 || src_rowsize == 0) +++ { +++ TIFFError(TIFFFileName(out), +++ "Error, integer overflow when computing source row size"); +++ return 1; +++ } ++ } ++- src_rowsize = ((uint32_t)bps * (uint32_t)spp * imagewidth + 7U) / 8; ++ ++ /* Add 3 padding bytes for extractContigSamples32bits */ ++- tilebuf = ++- (unsigned char *)limitMalloc(tile_buffsize + NUM_BUFF_OVERSIZE_BYTES); +++ if (computePaddedSize(&padded_tile_buffsize, tile_buffsize, __func__)) +++ return 1; +++ tilebuf = (unsigned char *)limitMalloc(padded_tile_buffsize); ++ if (tilebuf == 0) ++ return 1; ++- memset(tilebuf, 0, (size_t)(tile_buffsize + NUM_BUFF_OVERSIZE_BYTES)); +++ memset(tilebuf, 0, (size_t)padded_tile_buffsize); ++ for (row = 0; row < imagelength; row += tl) ++ { ++ nrow = (row + tl > imagelength) ? imagelength - row : tl; ++@@ -1545,17 +1781,23 @@ static int writeBufferToSeparateTiles(TIFF *out, uint8_t *buf, ++ tsample_t spp, struct dump_opts *dump) ++ { ++ /* Add 3 padding bytes for extractContigSamples32bits */ ++- tdata_t obuf = limitMalloc(TIFFTileSize(out) + NUM_BUFF_OVERSIZE_BYTES); +++ tmsize_t tilesize = TIFFTileSize(out); +++ tmsize_t padded_tilesize; +++ tdata_t obuf; ++ uint32_t tl, tw; ++ uint32_t row, col, nrow, ncol; ++- uint32_t src_rowsize, col_offset; +++ uint32_t src_rowsize; +++ tmsize_t col_offset; ++ uint16_t bps; ++ tsample_t s; ++ uint8_t *bufp = (uint8_t *)buf; ++ +++ if (computePaddedSize(&padded_tilesize, tilesize, __func__)) +++ return 1; +++ obuf = limitMalloc(padded_tilesize); ++ if (obuf == NULL) ++ return 1; ++- memset(obuf, 0, (size_t)(TIFFTileSize(out) + NUM_BUFF_OVERSIZE_BYTES)); +++ memset(obuf, 0, (size_t)padded_tilesize); ++ ++ if (!TIFFGetField(out, TIFFTAG_TILELENGTH, &tl) || ++ !TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw) || ++@@ -1565,16 +1807,19 @@ static int writeBufferToSeparateTiles(TIFF *out, uint8_t *buf, ++ return 1; ++ } ++ ++- if (imagewidth == 0 || ++- (uint32_t)bps * (uint32_t)spp > UINT32_MAX / imagewidth || ++- (uint32_t)bps * (uint32_t)spp * imagewidth > UINT32_MAX - 7) ++ { ++- TIFFError(TIFFFileName(out), "Error, uint32_t overflow when computing " ++- "(imagewidth * bps * spp) + 7"); ++- _TIFFfree(obuf); ++- return 1; +++ uint64_t src_rowsize64 = +++ _TIFFComputeRowSize64(out, imagewidth, spp, bps, "source row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(out, src_rowsize64, "source row size"); +++ if (src_rowsize64 == 0 || src_rowsize == 0) +++ { +++ TIFFError(TIFFFileName(out), +++ "Error, integer overflow when computing source row size"); +++ _TIFFfree(obuf); +++ return 1; +++ } ++ } ++- src_rowsize = ((uint32_t)bps * (uint32_t)spp * imagewidth + 7U) / 8; ++ ++ for (row = 0; row < imagelength; row += tl) ++ { ++@@ -1953,10 +2229,8 @@ void process_command_opts(int argc, char *argv[], char *mp, char *mode, ++ ignore = TRUE; /* ignore errors */ ++ break; ++ case 'k': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ break; ++ case 'l': ++ outtiled = TRUE; /* tile length */ ++@@ -3254,11 +3539,31 @@ static int dump_buffer(FILE *dumpfile, int format, uint32_t rows, ++ ++ for (i = 0; i < rows; i++) ++ { ++- dump_ptr = buff + (i * width); +++ tmsize_t dump_offset = +++ _TIFFComputeRowOffset(NULL, width, i, "dump buffer offset"); +++ if (dump_offset == 0 && i != 0 && width != 0) +++ { +++ TIFFError("dump_buffer", +++ "Integer overflow detected while calculating buffer " +++ "offset"); +++ return (1); +++ } +++ dump_ptr = buff + dump_offset; ++ if (format == DUMP_TEXT) +++ { +++ uint64_t dump_file_offset = +++ _TIFFMultiply64(NULL, row, width, "dump file offset"); +++ if (dump_file_offset == 0 && row != 0 && width != 0) +++ { +++ TIFFError("dump_buffer", +++ "Integer overflow detected while calculating file " +++ "offset"); +++ return (1); +++ } ++ dump_info(dumpfile, format, "", ++- "Row %4" PRIu32 ", %" PRIu32 " bytes at offset %" PRIu32, ++- row + i + 1u, width, row * width); +++ "Row %4" PRIu32 ", %" PRIu32 " bytes at offset %" PRIu64, +++ row + i + 1u, width, dump_file_offset); +++ } ++ ++ for (k = (int)width; k >= 10; k -= 10, dump_ptr += 10) ++ dump_data(dumpfile, format, "", dump_ptr, 10); ++@@ -3318,13 +3720,17 @@ static int extractContigSamplesBytes(uint8_t *in, uint8_t *out, uint32_t cols, ++ end = start + numcols; ++ } ++ ++- dst_rowsize = (uint32_t)((bps * (end - start) * count) / 8); +++ if (computeRowSize32(&dst_rowsize, end - start, count, bps, __func__)) +++ return (1); ++ ++ bytes_per_sample = (int)((bps + 7) / 8); ++ /* Optimize case for copying all samples */ ++ if (count == spp) ++ { ++- src = in + (uint32_t)(start * spp * (uint32_t)bytes_per_sample); +++ uint32_t src_bit_offset; +++ if (computeBitOffset32(&src_bit_offset, start, spp, bps, __func__)) +++ return (1); +++ src = in + src_bit_offset / 8; ++ _TIFFmemcpy(dst, src, dst_rowsize); ++ } ++ else ++@@ -3334,18 +3740,12 @@ static int extractContigSamplesBytes(uint8_t *in, uint8_t *out, uint32_t cols, ++ for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); ++ sindex++) ++ { ++- bit_offset = col * bps * spp; ++- if (sindex == 0) ++- { ++- src_byte = bit_offset / 8; ++- /* src_bit = bit_offset % 8; */ ++- } ++- else ++- { ++- src_byte = ++- (uint32_t)((bit_offset + ((uint32_t)sindex * bps)) / 8); ++- /* src_bit = (bit_offset + (sindex * bps)) % 8; */ ++- } +++ if (computeSampleBitOffset32(&bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ /* src_bit = bit_offset % 8; */ ++ src = in + src_byte; ++ for (i = 0; i < bytes_per_sample; i++) ++ *dst++ = *src++; ++@@ -3417,8 +3818,13 @@ static int extractContigSamples8bits(uint8_t *in, uint8_t *out, uint32_t cols, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -3510,8 +3917,13 @@ static int extractContigSamples16bits(uint8_t *in, uint8_t *out, uint32_t cols, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -3612,8 +4025,13 @@ static int extractContigSamples24bits(uint8_t *in, uint8_t *out, uint32_t cols, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -3737,8 +4156,13 @@ static int extractContigSamples32bits(uint8_t *in, uint8_t *out, uint32_t cols, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -3857,8 +4282,13 @@ static int extractContigSamplesShifted8bits(uint8_t *in, uint8_t *out, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -3941,7 +4371,8 @@ static int extractContigSamplesShifted16bits(uint8_t *in, uint8_t *out, ++ maskbits = (uint16_t)((uint16_t)-1 >> (16 - bps)); ++ for (col = start; col < end; col++) ++ { /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps * spp; +++ if (computeBitOffset32(&bit_offset, col, spp, bps, __func__)) +++ return (1); ++ for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); ++ sindex++) ++ { ++@@ -3952,8 +4383,13 @@ static int extractContigSamplesShifted16bits(uint8_t *in, uint8_t *out, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -4066,8 +4503,13 @@ static int extractContigSamplesShifted24bits(uint8_t *in, uint8_t *out, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -4182,8 +4625,13 @@ static int extractContigSamplesShifted32bits(uint8_t *in, uint8_t *out, ++ } ++ else ++ { ++- src_byte = (bit_offset + ((uint32_t)sindex * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sindex * bps)) % 8; +++ uint32_t sample_bit_offset; +++ if (computeSampleBitOffset32(&sample_bit_offset, col, +++ (tsample_t)sindex, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = sample_bit_offset / 8; +++ src_bit = sample_bit_offset % 8; ++ } ++ ++ src = in + src_byte; ++@@ -4246,13 +4694,18 @@ static int extractContigSamplesToBuffer(uint8_t *out, uint8_t *in, ++ uint16_t bps, struct dump_opts *dump) ++ { ++ int shift_width, bytes_per_sample, bytes_per_pixel; ++- uint32_t src_rowsize, src_offset, row, first_col = 0; ++- uint32_t dst_rowsize, dst_offset; +++ uint32_t src_rowsize, row, first_col = 0; +++ uint32_t dst_rowsize; ++ tsample_t count = 1; ++ uint8_t *src, *dst; ++ ++ bytes_per_sample = (int)((bps + 7) / 8); ++- bytes_per_pixel = (int)(((bps * spp) + 7) / 8); +++ { +++ uint32_t bytes_per_pixel32; +++ if (computeRowSize32(&bytes_per_pixel32, 1, spp, bps, __func__)) +++ return (1); +++ bytes_per_pixel = (int)bytes_per_pixel32; +++ } ++ if ((bps % 8) == 0) ++ shift_width = 0; ++ else ++@@ -4262,8 +4715,23 @@ static int extractContigSamplesToBuffer(uint8_t *out, uint8_t *in, ++ else ++ shift_width = bytes_per_sample + 1; ++ } ++- src_rowsize = ((uint32_t)bps * (uint32_t)spp * cols + 7) / 8; ++- dst_rowsize = ((bps * cols) + 7) / 8; +++ { +++ uint64_t src_rowsize64 = +++ _TIFFComputeRowSize64(NULL, cols, spp, bps, "source row size"); +++ uint64_t dst_rowsize64 = _TIFFComputeRowSize64(NULL, cols, count, bps, +++ "destination row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(NULL, src_rowsize64, "source row size"); +++ dst_rowsize = _TIFFCastUInt64ToUInt32(NULL, dst_rowsize64, +++ "destination row size"); +++ if (src_rowsize64 == 0 || dst_rowsize64 == 0 || src_rowsize == 0 || +++ dst_rowsize == 0) +++ { +++ TIFFError("extractContigSamplesToBuffer", +++ "Integer overflow detected while calculating row size"); +++ return (1); +++ } +++ } ++ ++ if ((dump->outfile != NULL) && (dump->level == 4)) ++ { ++@@ -4329,12 +4805,17 @@ static int extractContigSamplesToTileBuffer( ++ uint16_t count, uint16_t spp, uint16_t bps, struct dump_opts *dump) ++ { ++ int shift_width, bytes_per_sample, bytes_per_pixel; ++- uint32_t src_rowsize, src_offset, row; ++- uint32_t dst_rowsize, dst_offset; +++ uint32_t src_rowsize, row; +++ uint32_t dst_rowsize; ++ uint8_t *src, *dst; ++ ++ bytes_per_sample = (int)((bps + 7) / 8); ++- bytes_per_pixel = (int)(((bps * spp) + 7) / 8); +++ { +++ uint32_t bytes_per_pixel32; +++ if (computeRowSize32(&bytes_per_pixel32, 1, spp, bps, __func__)) +++ return (1); +++ bytes_per_pixel = (int)bytes_per_pixel32; +++ } ++ if ((bps % 8) == 0) ++ shift_width = 0; ++ else ++@@ -4352,13 +4833,36 @@ static int extractContigSamplesToTileBuffer( ++ "Sample %" PRIu32 ", %" PRIu32 " rows", sample + 1u, rows + 1u); ++ } ++ ++- src_rowsize = ((uint32_t)bps * (uint32_t)spp * imagewidth + 7) / 8; ++- dst_rowsize = ((bps * local_tilewidth * count) + 7) / 8; +++ { +++ uint64_t src_rowsize64 = _TIFFComputeRowSize64(NULL, imagewidth, spp, +++ bps, "source row size"); +++ uint64_t dst_rowsize64 = _TIFFComputeRowSize64( +++ NULL, local_tilewidth, count, bps, "destination row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(NULL, src_rowsize64, "source row size"); +++ dst_rowsize = _TIFFCastUInt64ToUInt32(NULL, dst_rowsize64, +++ "destination row size"); +++ if (src_rowsize64 == 0 || dst_rowsize64 == 0 || src_rowsize == 0 || +++ dst_rowsize == 0) +++ { +++ TIFFError("extractContigSamplesToTileBuffer", +++ "Integer overflow detected while calculating row size"); +++ return (1); +++ } +++ } ++ ++ for (row = 0; row < rows; row++) ++ { ++- src_offset = row * src_rowsize; ++- dst_offset = row * dst_rowsize; +++ tmsize_t src_offset = +++ _TIFFComputeRowOffset(NULL, src_rowsize, row, "source row offset"); +++ tmsize_t dst_offset = _TIFFComputeRowOffset(NULL, dst_rowsize, row, +++ "destination row offset"); +++ if ((src_offset == 0 && row != 0) || (dst_offset == 0 && row != 0)) +++ { +++ TIFFError("extractContigSamplesToTileBuffer", +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ src = in + src_offset; ++ dst = out + dst_offset; ++ ++@@ -4466,10 +4970,35 @@ static int combineSeparateSamplesBytes(unsigned char *srcbuffs[], ++ ++ bytes_per_sample = (bps + 7) / 8; ++ ++- src_rowsize = ((bps * cols) + 7) / 8; ++- dst_rowsize = ((uint32_t)bps * (uint32_t)spp * cols + 7) / 8; +++ { +++ uint64_t src_rowsize64 = +++ _TIFFComputeRowSize64(NULL, cols, 1, bps, "source row size"); +++ uint64_t dst_rowsize64 = +++ _TIFFComputeRowSize64(NULL, cols, spp, bps, "destination row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(NULL, src_rowsize64, "source row size"); +++ dst_rowsize = _TIFFCastUInt64ToUInt32(NULL, dst_rowsize64, +++ "destination row size"); +++ if (src_rowsize64 == 0 || dst_rowsize64 == 0 || src_rowsize == 0 || +++ dst_rowsize == 0) +++ { +++ TIFFError("combineSeparateSamplesBytes", +++ "Integer overflow detected while calculating row size"); +++ return (1); +++ } +++ } ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(NULL, src_rowsize, row, "source row offset"); +++ tmsize_t dst_offset = _TIFFComputeRowOffset(NULL, dst_rowsize, row, +++ "destination row offset"); +++ if ((row_offset == 0 && row != 0) || (dst_offset == 0 && row != 0)) +++ { +++ TIFFError("combineSeparateSamplesBytes", +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ if ((dumpfile != NULL) && (level == 2)) ++ { ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++@@ -4531,20 +5077,35 @@ static int combineSeparateSamples8bits(uint8_t *in[], uint8_t *out, ++ } ++ ++ /* bytes_per_sample = (bps + 7) / 8; */ ++- src_rowsize = ((bps * cols) + 7) / 8; ++- dst_rowsize = ((bps * cols * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, cols, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, cols, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint8_t)((uint8_t)-1 >> (8 - bps)); ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++@@ -4552,7 +5113,19 @@ static int combineSeparateSamples8bits(uint8_t *in[], uint8_t *out, ++ /* load up next sample from each plane */ ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ buff1 = (uint8_t)(((*src) & matchbits) << (src_bit)); ++ ++ /* If we have a full buffer's worth, write it out */ ++@@ -4639,27 +5212,54 @@ static int combineSeparateSamples16bits(uint8_t *in[], uint8_t *out, ++ } ++ ++ /* bytes_per_sample = (bps + 7) / 8; */ ++- src_rowsize = ((bps * cols) + 7) / 8; ++- dst_rowsize = ((bps * cols * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, cols, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, cols, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint16_t)((uint16_t)-1 >> (16 - bps)); ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++ matchbits = (uint16_t)(maskbits << (16 - src_bit - bps)); ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ if (little_endian) ++ buff1 = (uint16_t)((src[0] << 8) | src[1]); ++ else ++@@ -4894,28 +5521,55 @@ static int combineSeparateSamples32bits(uint8_t *in[], uint8_t *out, ++ } ++ ++ /* bytes_per_sample = (bps + 7) / 8; */ ++- src_rowsize = ((bps * cols) + 7) / 8; ++- dst_rowsize = ((bps * cols * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, cols, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, cols, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint64_t)-1 >> (64 - bps); ++ /* shift_width = ((bps + 7) / 8) + 1; */ ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++ matchbits = maskbits << (64 - src_bit - bps); ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ if (little_endian) ++ { ++ longbuff1 = ((uint32_t)src[0] << 24) | ++@@ -5017,7 +5671,7 @@ static int combineSeparateTileSamplesBytes(unsigned char *srcbuffs[], ++ uint16_t bps) ++ { ++ int i, bytes_per_sample; ++- uint32_t row, col, col_offset, src_rowsize, dst_rowsize, src_offset; +++ uint32_t row, col, src_rowsize, dst_rowsize; ++ unsigned char *src; ++ unsigned char *dst; ++ tsample_t s; ++@@ -5031,19 +5685,63 @@ static int combineSeparateTileSamplesBytes(unsigned char *srcbuffs[], ++ } ++ ++ bytes_per_sample = (bps + 7) / 8; ++- src_rowsize = ((bps * tw) + 7) / 8; ++- dst_rowsize = (uint32_t)imagewidth * (uint32_t)bytes_per_sample * spp; +++ { +++ uint64_t src_rowsize64 = +++ _TIFFComputeRowSize64(NULL, tw, 1, bps, "source row size"); +++ uint64_t dst_rowsize64 = _TIFFComputeRowSize64( +++ NULL, imagewidth, spp, bps, "destination row size"); +++ src_rowsize = +++ _TIFFCastUInt64ToUInt32(NULL, src_rowsize64, "source row size"); +++ dst_rowsize = _TIFFCastUInt64ToUInt32(NULL, dst_rowsize64, +++ "destination row size"); +++ if (src_rowsize64 == 0 || dst_rowsize64 == 0 || src_rowsize == 0 || +++ dst_rowsize == 0) +++ { +++ TIFFError("combineSeparateTileSamplesBytes", +++ "Integer overflow detected while calculating row size"); +++ return (1); +++ } +++ } ++ for (row = 0; row < rows; row++) ++ { ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ tmsize_t dst_offset = _TIFFComputeRowOffset(NULL, dst_rowsize, row, +++ "destination row offset"); +++ tmsize_t src_offset = +++ _TIFFComputeRowOffset(NULL, src_rowsize, row, "source row offset"); +++ if ((dst_offset == 0 && row != 0) || (src_offset == 0 && row != 0)) +++ { +++ TIFFError("combineSeparateTileSamplesBytes", +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset; ++ #ifdef DEVELMODE ++- TIFFError("", "Tile row %4d, Src offset %6d Dst offset %6zd", row, ++- src_offset, dst - out); +++ TIFFError("", +++ "Tile row %4d, Src offset %" TIFF_SSIZE_FORMAT +++ " Dst offset %6zd", +++ row, src_offset, dst - out); ++ #endif ++ for (col = 0; col < cols; col++) ++ { ++- col_offset = src_offset + (col * (bps / 8)); +++ tmsize_t col_bytes = +++ _TIFFMultiplySSize(NULL, col, bps / 8, "column offset"); +++ tmsize_t col_offset; +++ if (col_bytes == 0 && col != 0) +++ { +++ TIFFError("combineSeparateTileSamplesBytes", +++ "Integer overflow detected while calculating column " +++ "offset"); +++ return (1); +++ } +++ col_offset = +++ _TIFFAddSSize(NULL, src_offset, col_bytes, "column offset"); +++ if (col_offset == 0 && (src_offset != 0 || col_bytes != 0)) +++ { +++ TIFFError("combineSeparateTileSamplesBytes", +++ "Integer overflow detected while calculating column " +++ "offset"); +++ return (1); +++ } ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++ src = srcbuffs[s] + col_offset; ++@@ -5082,20 +5780,35 @@ static int combineSeparateTileSamples8bits(uint8_t *in[], uint8_t *out, ++ return (1); ++ } ++ ++- src_rowsize = ((bps * tw) + 7) / 8; ++- dst_rowsize = ((imagewidth * bps * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, tw, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, imagewidth, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint8_t)((uint8_t)-1 >> (8 - bps)); ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++@@ -5103,7 +5816,19 @@ static int combineSeparateTileSamples8bits(uint8_t *in[], uint8_t *out, ++ /* load up next sample from each plane */ ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ buff1 = (uint8_t)(((*src) & matchbits) << (src_bit)); ++ ++ /* If we have a full buffer's worth, write it out */ ++@@ -5190,27 +5915,54 @@ static int combineSeparateTileSamples16bits(uint8_t *in[], uint8_t *out, ++ return (1); ++ } ++ ++- src_rowsize = ((bps * tw) + 7) / 8; ++- dst_rowsize = ((imagewidth * bps * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, tw, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, imagewidth, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint16_t)((uint16_t)-1 >> (16 - bps)); ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++ matchbits = (uint16_t)(maskbits << (16 - src_bit - bps)); ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ if (little_endian) ++ buff1 = (uint16_t)((src[0] << 8) | src[1]); ++ else ++@@ -5308,27 +6060,54 @@ static int combineSeparateTileSamples24bits(uint8_t *in[], uint8_t *out, ++ return (1); ++ } ++ ++- src_rowsize = ((bps * tw) + 7) / 8; ++- dst_rowsize = ((imagewidth * bps * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, tw, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, imagewidth, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint32_t)-1 >> (32 - bps); ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++ matchbits = maskbits << (32 - src_bit - bps); ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ if (little_endian) ++ buff1 = (uint32_t)((src[0] << 24) | (src[1] << 16) | ++ (src[2] << 8) | src[3]); ++@@ -5444,28 +6223,55 @@ static int combineSeparateTileSamples32bits(uint8_t *in[], uint8_t *out, ++ return (1); ++ } ++ ++- src_rowsize = ((bps * tw) + 7) / 8; ++- dst_rowsize = ((imagewidth * bps * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, tw, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, imagewidth, spp, bps, __func__)) +++ return (1); ++ maskbits = (uint64_t)-1 >> (64 - bps); ++ /* shift_width = ((bps + 7) / 8) + 1; */ ++ ++ for (row = 0; row < rows; row++) ++ { +++ tmsize_t dst_offset_s; +++ tmsize_t src_offset_s; ++ ready_bits = 0; ++ buff1 = buff2 = 0; ++- dst = out + (row * dst_rowsize); ++- src_offset = row * src_rowsize; +++ dst_offset_s = _TIFFComputeRowOffset(NULL, dst_rowsize, row, __func__); +++ src_offset_s = _TIFFComputeRowOffset(NULL, src_rowsize, row, __func__); +++ src_offset = +++ _TIFFCastUInt64ToUInt32(NULL, (uint64_t)src_offset_s, __func__); +++ if ((dst_offset_s == 0 && row != 0) || +++ (src_offset_s == 0 && row != 0) || +++ (src_offset == 0 && src_offset_s != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } +++ dst = out + dst_offset_s; ++ for (col = 0; col < cols; col++) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = col * bps; +++ if (computeBitOffset32(&bit_offset, col, 1, bps, __func__)) +++ return (1); ++ src_byte = bit_offset / 8; ++ src_bit = bit_offset % 8; ++ ++ matchbits = maskbits << (64 - src_bit - bps); ++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- src = in[s] + src_offset + src_byte; +++ { +++ tmsize_t total_src_offset = +++ _TIFFAddSSize(NULL, src_offset, src_byte, __func__); +++ if (total_src_offset == 0 && +++ (src_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "source offset"); +++ return (1); +++ } +++ src = in[s] + total_src_offset; +++ } ++ if (little_endian) ++ { ++ longbuff1 = (uint32_t)((src[0] << 24) | (src[1] << 16) | ++@@ -5593,14 +6399,20 @@ static int readSeparateStripsIntoBuffer(TIFF *in, uint8_t *obuf, ++ rps = length; ++ ++ bytes_per_sample = (int)((bps + 7) / 8); ++- bytes_per_pixel = (int)(((bps * spp) + 7) / 8); +++ { +++ uint32_t bytes_per_pixel32; +++ if (computeRowSize32(&bytes_per_pixel32, 1, spp, bps, __func__)) +++ return (0); +++ bytes_per_pixel = (int)bytes_per_pixel32; +++ } ++ if (bytes_per_pixel < (bytes_per_sample + 1)) ++ shift_width = bytes_per_pixel; ++ else ++ shift_width = (int)(bytes_per_sample + 1); ++ ++- src_rowsize = ((bps * width) + 7) / 8; ++- dst_rowsize = ((bps * width * spp) + 7) / 8; +++ if (computeRowSize32(&src_rowsize, width, 1, bps, __func__) || +++ computeRowSize32(&dst_rowsize, width, spp, bps, __func__)) +++ return (0); ++ dst = obuf; ++ ++ if ((dump->infile != NULL) && (dump->level == 3)) ++@@ -5624,31 +6436,31 @@ static int readSeparateStripsIntoBuffer(TIFF *in, uint8_t *obuf, ++ strips_per_sample = nstrips / spp; ++ ++ /* Add 3 padding bytes for combineSeparateSamples32bits */ ++- if ((size_t)stripsize > TIFF_TMSIZE_T_MAX - NUM_BUFF_OVERSIZE_BYTES) ++ { ++- TIFFError("readSeparateStripsIntoBuffer", ++- "Integer overflow when calculating buffer size."); ++- exit(EXIT_FAILURE); ++- } +++ tmsize_t padded_stripsize; +++ if (computePaddedSize(&padded_stripsize, stripsize, +++ "readSeparateStripsIntoBuffer")) +++ exit(EXIT_FAILURE); ++ ++- for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++- { ++- srcbuffs[s] = NULL; ++- buff = ++- (unsigned char *)limitMalloc(stripsize + NUM_BUFF_OVERSIZE_BYTES); ++- if (!buff) +++ for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++) ++ { ++- TIFFError( ++- "readSeparateStripsIntoBuffer", ++- "Unable to allocate strip read buffer for sample %" PRIu16, s); ++- for (i = 0; i < s; i++) ++- _TIFFfree(srcbuffs[i]); ++- return 0; +++ srcbuffs[s] = NULL; +++ buff = (unsigned char *)limitMalloc(padded_stripsize); +++ if (!buff) +++ { +++ TIFFError( +++ "readSeparateStripsIntoBuffer", +++ "Unable to allocate strip read buffer for sample %" PRIu16, +++ s); +++ for (i = 0; i < s; i++) +++ _TIFFfree(srcbuffs[i]); +++ return 0; +++ } +++ buff[stripsize] = 0; +++ buff[stripsize + 1] = 0; +++ buff[stripsize + 2] = 0; +++ srcbuffs[s] = buff; ++ } ++- buff[stripsize] = 0; ++- buff[stripsize + 1] = 0; ++- buff[stripsize + 2] = 0; ++- srcbuffs[s] = buff; ++ } ++ ++ rows_processed = 0; ++@@ -6045,12 +6883,26 @@ static int computeInputPixelOffsets(struct crop_mask *crop, ++ if (zlength > max_length) ++ max_length = zlength; ++ ++- buffsize = ++- (uint32_t)(((uint64_t)zwidth * image->bps * image->spp + 7) / ++- 8 * (zlength + 1)); +++ if (computeCropBufferSize32(&buffsize, zwidth, zlength, image->spp, +++ image->bps, "computeInputPixelOffsets")) +++ return (-1); ++ ++ crop->regionlist[i].buffsize = buffsize; ++- crop->bufftotal += buffsize; +++ { +++ uint64_t bufftotal64 = +++ _TIFFAdd64(NULL, crop->bufftotal, buffsize, +++ "computeInputPixelOffsets"); +++ uint32_t bufftotal32 = _TIFFCastUInt64ToUInt32( +++ NULL, bufftotal64, "computeInputPixelOffsets"); +++ if (bufftotal64 == 0 || (bufftotal32 == 0 && bufftotal64 != 0)) +++ { +++ TIFFError("computeInputPixelOffsets", +++ "Integer overflow detected while accumulating " +++ "crop buffer size"); +++ return (-1); +++ } +++ crop->bufftotal = bufftotal32; +++ } ++ ++ /* For composite images with more than one region, the ++ * combined_length or combined_width always needs to be equal, ++@@ -6655,12 +7507,26 @@ static int getCropOffsets(struct image_data *image, struct crop_mask *crop, ++ break; ++ } /* end switch statement */ ++ ++- buffsize = (uint32_t)(((uint64_t)zwidth * image->bps * image->spp + 7) / ++- 8 * (zlength + 1)); +++ if (computeCropBufferSize32(&buffsize, zwidth, zlength, image->spp, +++ image->bps, "getCropOffsets")) +++ return (-1); ++ crop->regionlist[i].width = (uint32_t)zwidth; ++ crop->regionlist[i].length = (uint32_t)zlength; ++ crop->regionlist[i].buffsize = buffsize; ++- crop->bufftotal += buffsize; +++ { +++ uint64_t bufftotal64 = +++ _TIFFAdd64(NULL, crop->bufftotal, buffsize, "getCropOffsets"); +++ uint32_t bufftotal32 = +++ _TIFFCastUInt64ToUInt32(NULL, bufftotal64, "getCropOffsets"); +++ if (bufftotal64 == 0 || (bufftotal32 == 0 && bufftotal64 != 0)) +++ { +++ TIFFError("getCropOffsets", +++ "Integer overflow detected while accumulating crop " +++ "buffer size"); +++ return (-1); +++ } +++ crop->bufftotal = bufftotal32; +++ } ++ ++ if (dump->outfile != NULL) ++ dump_info(dump->outfile, dump->format, "", ++@@ -6940,9 +7849,21 @@ static int computeOutputPixelOffsets(struct crop_mask *crop, ++ sections[k].x2 = x2; ++ sections[k].y1 = y1; ++ sections[k].y2 = y2; ++- sections[k].buffsize = line_bytes * olength; +++ { +++ uint64_t buffsize64 = _TIFFMultiply64(NULL, line_bytes, olength, +++ "section buffer size"); +++ uint32_t buffsize = _TIFFCastUInt64ToUInt32( +++ NULL, buffsize64, "section buffer size"); +++ if (buffsize64 == 0 || buffsize == 0) +++ { +++ TIFFError("computeOutputPixelOffsets", +++ "Section buffer size exceeds UINT32_MAX"); +++ return (-1); +++ } +++ sections[k].buffsize = buffsize; +++ } ++ sections[k].position = (int)(k + 1); ++- sections[k].total = (int)(orows * ocols); +++ sections[k].total = (int)page->total_sections; ++ } ++ } ++ return (0); ++@@ -7164,38 +8085,43 @@ static int loadImage(TIFF *in, struct image_data *image, struct dump_opts *dump, ++ TIFFGetField(in, TIFFTAG_TILELENGTH, &tl); ++ ++ tile_rowsize = TIFFTileRowSize(in); ++- if (ntiles == 0 || tlsize == 0 || tile_rowsize == 0) +++ if (ntiles == 0 || tlsize == 0 || tile_rowsize == 0 || tl == 0) ++ { ++ TIFFError("loadImage", ++ "File appears to be tiled, but the number of tiles, tile " ++- "size, or tile rowsize is zero."); ++- exit(EXIT_FAILURE); ++- } ++- if (ntiles != 0 && tlsize > (tmsize_t)(TIFF_TMSIZE_T_MAX / ntiles)) ++- { ++- TIFFError("loadImage", ++- "Integer overflow when calculating buffer size"); +++ "size, tile length, or tile rowsize is zero."); ++ exit(EXIT_FAILURE); ++ } ++- buffsize = tlsize * ntiles; ++- ++- if (tl != 0 && ntiles != 0 && ++- tile_rowsize > (tmsize_t)(TIFF_TMSIZE_T_MAX / tl / ntiles)) +++ buffsize = _TIFFMultiplySSize(in, tlsize, ntiles, "tile buffer size"); +++ if (buffsize == 0) ++ { ++ TIFFError("loadImage", ++ "Integer overflow when calculating buffer size"); ++ exit(EXIT_FAILURE); ++ } ++- if (buffsize < (tmsize_t)ntiles * tl * tile_rowsize) ++ { ++- buffsize = ntiles * tl * tile_rowsize; +++ tmsize_t tile_rows = +++ _TIFFMultiplySSize(in, tile_rowsize, tl, "tile buffer size"); +++ tmsize_t calculated_buffsize = +++ _TIFFMultiplySSize(in, tile_rows, ntiles, "tile buffer size"); +++ if (tile_rows == 0 || calculated_buffsize == 0) +++ { +++ TIFFError("loadImage", +++ "Integer overflow when calculating buffer size"); +++ exit(EXIT_FAILURE); +++ } +++ if (buffsize < calculated_buffsize) +++ { +++ buffsize = calculated_buffsize; ++ ++ #ifdef DEBUG2 ++- TIFFError("loadImage", ++- "Tilesize %" PRIu32 " is too small, using ntiles * " ++- "tilelength * tilerowsize %" PRIu32, ++- tlsize, buffsize); +++ TIFFError("loadImage", +++ "Tilesize %" TIFF_SSIZE_FORMAT +++ " is too small, using ntiles * tilelength * " +++ "tilerowsize %" TIFF_SSIZE_FORMAT, +++ tlsize, buffsize); ++ #endif +++ } ++ } ++ ++ if (dump->infile != NULL) ++@@ -7298,19 +8238,18 @@ static int loadImage(TIFF *in, struct image_data *image, struct dump_opts *dump, ++ _TIFFfree(read_buff); ++ *read_ptr = NULL; ++ } ++- if (buffsize > 0xFFFFFFFFU - 3) ++ { ++- TIFFError("loadImage", "Required read buffer size too large"); ++- return (-1); +++ tmsize_t padded_buffsize; +++ if (computePaddedSize(&padded_buffsize, buffsize, "loadImage")) +++ return (-1); +++ read_buff = (unsigned char *)limitMalloc(padded_buffsize); +++ check_buffsize = padded_buffsize; ++ } ++- read_buff = ++- (unsigned char *)limitMalloc(buffsize + NUM_BUFF_OVERSIZE_BYTES); ++ if (!read_buff) ++ { ++ TIFFError("loadImage", "Unable to allocate read buffer"); ++ return (-1); ++ } ++- check_buffsize = buffsize + NUM_BUFF_OVERSIZE_BYTES; ++ ++ read_buff[buffsize] = 0; ++ read_buff[buffsize + 1] = 0; ++@@ -7393,12 +8332,14 @@ static int loadImage(TIFF *in, struct image_data *image, struct dump_opts *dump, ++ (uint64_t)scanlinesize); ++ } ++ for (i = 0; i < length; i++) ++- /* Apparently, the scanlinesize test above was accepted to fail. ++- * Thus silence Coverity Scan warning because this seems to be ++- * intentional. */ ++- /* coverity[overflow_sink:SUPPRESS] */ +++ { +++ tmsize_t scanline_offset = _TIFFComputeRowOffset( +++ in, scanlinesize, i, "scanline buffer offset"); +++ if (scanline_offset == 0 && i != 0 && scanlinesize != 0) +++ return (-1); ++ dump_buffer(dump->infile, dump->format, 1, (uint32_t)scanlinesize, ++- i, read_buff + (i * scanlinesize)); +++ i, read_buff + scanline_offset); +++ } ++ } ++ return (0); ++ } /* end loadImage */ ++@@ -7490,7 +8432,12 @@ static int extractCompositeRegions(struct image_data *image, ++ count = spp; ++ ++ bytes_per_sample = (int)((bps + 7) / 8); ++- bytes_per_pixel = (int)(((bps * spp) + 7) / 8); +++ { +++ uint32_t bytes_per_pixel32; +++ if (computeRowSize32(&bytes_per_pixel32, 1, spp, bps, __func__)) +++ return (1); +++ bytes_per_pixel = (int)bytes_per_pixel32; +++ } ++ if ((bps % 8) == 0) ++ shift_width = 0; ++ else ++@@ -7757,9 +8777,39 @@ static int extractCompositeRegions(struct image_data *image, ++ return (1); ++ } ++ } ++- prev_width += (crop_width * bps * count) / 8; +++ { +++ uint64_t prev_width64 = +++ _TIFFAdd64(NULL, prev_width, crop_bits64 / 8, __func__); +++ uint32_t prev_width32 = +++ _TIFFCastUInt64ToUInt32(NULL, prev_width64, __func__); +++ if ((prev_width64 == 0 && +++ (prev_width != 0 || crop_bits64 >= 8)) || +++ (prev_width32 == 0 && prev_width64 != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "composite width"); +++ return (1); +++ } +++ prev_width = prev_width32; +++ } ++ prev_trailing_bits += trailing_bits; ++- prev_width += prev_trailing_bits / 8; +++ { +++ uint64_t prev_width64 = _TIFFAdd64( +++ NULL, prev_width, prev_trailing_bits / 8, __func__); +++ uint32_t prev_width32 = +++ _TIFFCastUInt64ToUInt32(NULL, prev_width64, __func__); +++ if ((prev_width64 == 0 && +++ (prev_width != 0 || prev_trailing_bits >= 8)) || +++ (prev_width32 == 0 && prev_width64 != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "composite width"); +++ return (1); +++ } +++ prev_width = prev_width32; +++ } ++ prev_trailing_bits %= 8; ++ break; ++ } ++@@ -7800,7 +8850,8 @@ static int extractSeparateRegion(struct image_data *image, ++ count = spp; ++ ++ bytes_per_sample = (uint32_t)((bps + 7) / 8); ++- bytes_per_pixel = (uint32_t)(((bps * spp) + 7) / 8); +++ if (computeRowSize32(&bytes_per_pixel, 1, spp, bps, __func__)) +++ return (1); ++ if ((bps % 8) == 0) ++ shift_width = 0; /* Byte aligned data only */ ++ else ++@@ -7967,18 +9034,21 @@ static int extractImageSection(struct image_data *image, ++ */ ++ /* row size in full bytes of source image */ ++ { ++- uint64_t img_bits = (uint64_t)img_width * spp * bps; ++- if (img_bits > UINT32_MAX - 7) +++ uint64_t img_rowsize64 = +++ _TIFFComputeRowSize64(NULL, img_width, spp, bps, "image row size"); +++ img_rowsize = +++ _TIFFCastUInt64ToUInt32(NULL, img_rowsize64, "image row size"); +++ if (img_rowsize64 == 0 || img_rowsize == 0) ++ { ++ TIFFError("extractImageSection", ++ "Integer overflow computing image row size"); ++ return (1); ++ } ++- img_rowsize = (uint32_t)((img_bits + 7) / 8); ++ } ++ /* number of COMPLETE bytes per row in section */ ++ { ++- uint64_t sect_bits = (uint64_t)sect_width * spp * bps; +++ uint64_t sect_bits = +++ _TIFFComputeBitOffset(NULL, sect_width, spp, bps, "section size"); ++ if (sect_bits > UINT32_MAX) ++ { ++ TIFFError("extractImageSection", ++@@ -8254,7 +9384,20 @@ static int writeSelections(TIFF *in, TIFF **out, struct crop_mask *crop, ++ autoindex = 0; ++ if (update_output_file(out, mp, autoindex, filename, page)) ++ return (1); ++- page_count = (int)(crop->selections * total_pages); +++ { +++ uint64_t page_count64 = _TIFFMultiply64( +++ in, crop->selections, total_pages, "page count"); +++ if ((page_count64 == 0 && crop->selections != 0 && +++ total_pages != 0) || +++ page_count64 > (uint64_t)INT_MAX) +++ { +++ TIFFError("writeSelections", +++ "Integer overflow detected while calculating " +++ "page count"); +++ return (1); +++ } +++ page_count = (int)page_count64; +++ } ++ for (i = 0; i < crop->selections; i++) ++ { ++ crop_buff = seg_buffs[i].buffer; ++@@ -8351,11 +9494,20 @@ static int writeImageSections(TIFF *in, TIFF *out, struct image_data *image, ++ "Increase resolution or reduce sections"); ++ return (-1); ++ } +++ if (page->total_sections == 0) +++ { +++ uint64_t total_sections64 = +++ _TIFFMultiply64(in, page->cols, page->rows, "subdivision count"); +++ page->total_sections = +++ _TIFFCastUInt64ToUInt32(in, total_sections64, "subdivision count"); +++ if (total_sections64 == 0 || page->total_sections == 0) +++ return (-1); +++ } ++ ++ hres = page->hres; ++ vres = page->vres; ++ ++- k = page->cols * page->rows; +++ k = page->total_sections; ++ if ((k < 1) || (k > MAX_SECTIONS)) ++ { ++ TIFFError("writeImageSections", ++@@ -8369,14 +9521,26 @@ static int writeImageSections(TIFF *in, TIFF *out, struct image_data *image, ++ { ++ width = sections[i].x2 - sections[i].x1 + 1; ++ length = sections[i].y2 - sections[i].y1 + 1; ++- /* Use the same integer (n+7)/8 ceiling formula as loadImage:7209 to ++- * avoid an off-by-one overcount that previously came from ++- * ceil((n+7)/8.0). Then promote to uint64_t to detect overflow before ++- * the result is stored back into the uint32_t sectsize. */ ++- { ++- uint64_t bpr64 = ++- ((uint64_t)width * image->bps * image->spp + 7) / 8; ++- uint64_t sectsize64 = bpr64 * length; +++ { +++ uint64_t bpr64 = _TIFFComputeRowSize64( +++ in, width, image->spp, image->bps, "section row size"); +++ uint64_t sectsize64; +++ if (bpr64 == 0) +++ { +++ TIFFError( +++ "writeImageSections", +++ "Integer overflow detected while calculating row size"); +++ return (-1); +++ } +++ sectsize64 = +++ _TIFFMultiply64(in, bpr64, length, "section buffer size"); +++ if (sectsize64 == 0) +++ { +++ TIFFError("writeImageSections", +++ "Integer overflow detected while calculating section " +++ "size"); +++ return (-1); +++ } ++ if (sectsize64 > (uint64_t)UINT32_MAX - NUM_BUFF_OVERSIZE_BYTES) ++ { ++ TIFFError("writeImageSections", ++@@ -8729,33 +9893,34 @@ static int createImageSection(uint32_t sectsize, unsigned char **sect_buff_ptr) ++ { ++ unsigned char *sect_buff = NULL; ++ unsigned char *new_buff = NULL; +++ tmsize_t padded_sectsize; ++ static uint32_t prev_sectsize = 0; ++ ++ sect_buff = *sect_buff_ptr; +++ if (computePaddedSize(&padded_sectsize, sectsize, "createImageSection")) +++ return (-1); ++ ++ if (!sect_buff) ++ { ++- sect_buff = ++- (unsigned char *)limitMalloc(sectsize + NUM_BUFF_OVERSIZE_BYTES); +++ sect_buff = (unsigned char *)limitMalloc(padded_sectsize); ++ if (!sect_buff) ++ { ++ TIFFError("createImageSection", ++ "Unable to allocate/reallocate section buffer"); ++ return (-1); ++ } ++- _TIFFmemset(sect_buff, 0, sectsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(sect_buff, 0, padded_sectsize); ++ } ++ else ++ { ++ if (prev_sectsize < sectsize) ++ { ++- new_buff = (unsigned char *)_TIFFrealloc( ++- sect_buff, sectsize + NUM_BUFF_OVERSIZE_BYTES); +++ new_buff = +++ (unsigned char *)_TIFFrealloc(sect_buff, padded_sectsize); ++ if (!new_buff) ++ { ++ _TIFFfree(sect_buff); ++- sect_buff = (unsigned char *)limitMalloc( ++- sectsize + NUM_BUFF_OVERSIZE_BYTES); +++ sect_buff = (unsigned char *)limitMalloc(padded_sectsize); ++ } ++ else ++ sect_buff = new_buff; ++@@ -8874,12 +10040,12 @@ static int processCropSelections(struct image_data *image, ++ crop->combined_width = computed_width; ++ crop->combined_length = computed_length; ++ ++- uint64_t rowsize = ++- ((uint64_t)crop->combined_width * image->bps * image->spp + 7) / 8; +++ uint64_t rowsize = _TIFFComputeRowSize64( +++ NULL, crop->combined_width, image->spp, image->bps, "row size"); +++ uint64_t total_size = _TIFFMultiply64( +++ NULL, rowsize, crop->combined_length, "buffer size"); ++ ++- uint64_t total_size = rowsize * crop->combined_length; ++- ++- if (total_size > TIFF_TMSIZE_T_MAX) +++ if (rowsize == 0 || total_size == 0 || total_size > TIFF_TMSIZE_T_MAX) ++ { ++ TIFFError("processCropSelections", ++ "Composite buffer size overflow"); ++@@ -8887,23 +10053,24 @@ static int processCropSelections(struct image_data *image, ++ } ++ ++ cropsize = (tmsize_t)total_size; +++ if (computePaddedSize(&padded_cropsize, cropsize, +++ "processCropSelections")) +++ return (-1); ++ ++ crop_buff = seg_buffs[0].buffer; ++ if (!crop_buff) ++- crop_buff = (unsigned char *)limitMalloc(cropsize + ++- NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = (unsigned char *)limitMalloc(padded_cropsize); ++ else ++ { ++ prev_cropsize = (tsize_t)seg_buffs[0].size; ++ if (prev_cropsize < cropsize) ++ { ++- next_buff = (unsigned char *)_TIFFrealloc( ++- crop_buff, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ next_buff = +++ (unsigned char *)_TIFFrealloc(crop_buff, padded_cropsize); ++ if (!next_buff) ++ { ++ _TIFFfree(crop_buff); ++- crop_buff = (unsigned char *)limitMalloc( ++- cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = (unsigned char *)limitMalloc(padded_cropsize); ++ } ++ else ++ crop_buff = next_buff; ++@@ -8917,7 +10084,7 @@ static int processCropSelections(struct image_data *image, ++ return (-1); ++ } ++ ++- _TIFFmemset(crop_buff, 0, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(crop_buff, 0, padded_cropsize); ++ seg_buffs[0].buffer = crop_buff; ++ seg_buffs[0].size = (size_t)cropsize; ++ ++@@ -9019,10 +10186,12 @@ static int processCropSelections(struct image_data *image, ++ width = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1; ++ length = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1; ++ ++- rowsize = ((uint64_t)width * image->bps * image->spp + 7) / 8; +++ rowsize = _TIFFComputeRowSize64(NULL, width, image->spp, image->bps, +++ "row size"); ++ ++- total_size = rowsize * length; ++- if (total_size > TIFF_TMSIZE_T_MAX) +++ total_size = _TIFFMultiply64(NULL, rowsize, length, "buffer size"); +++ if (rowsize == 0 || total_size == 0 || +++ total_size > TIFF_TMSIZE_T_MAX) ++ { ++ TIFFError("processCropSelections", ++ "Region buffer size overflow"); ++@@ -9030,6 +10199,9 @@ static int processCropSelections(struct image_data *image, ++ } ++ ++ cropsize = (tmsize_t)total_size; +++ if (computePaddedSize(&padded_cropsize, cropsize, +++ "processCropSelections")) +++ return (-1); ++ ++ /* Keep the region dimensions in sync with the allocated buffer. */ ++ crop->regionlist[i].width = width; ++@@ -9037,20 +10209,19 @@ static int processCropSelections(struct image_data *image, ++ ++ crop_buff = seg_buffs[i].buffer; ++ if (!crop_buff) ++- crop_buff = (unsigned char *)limitMalloc( ++- cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = (unsigned char *)limitMalloc(padded_cropsize); ++ else ++ { ++ prev_cropsize = (tsize_t)seg_buffs[i].size; ++ if (prev_cropsize < cropsize) ++ { ++- next_buff = (unsigned char *)_TIFFrealloc( ++- crop_buff, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ next_buff = (unsigned char *)_TIFFrealloc(crop_buff, +++ padded_cropsize); ++ if (!next_buff) ++ { ++ _TIFFfree(crop_buff); ++- crop_buff = (unsigned char *)limitMalloc( ++- cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = +++ (unsigned char *)limitMalloc(padded_cropsize); ++ } ++ else ++ crop_buff = next_buff; ++@@ -9064,7 +10235,7 @@ static int processCropSelections(struct image_data *image, ++ return (-1); ++ } ++ ++- _TIFFmemset(crop_buff, 0, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(crop_buff, 0, padded_cropsize); ++ seg_buffs[i].buffer = crop_buff; ++ seg_buffs[i].size = (size_t)cropsize; ++ ++@@ -9195,31 +10367,31 @@ static int createCroppedImage(struct image_data *image, struct crop_mask *crop, ++ crop->combined_length = image->length; ++ ++ cropsize = crop->bufftotal; +++ if (computePaddedSize(&padded_cropsize, cropsize, "createCroppedImage")) +++ return (-1); ++ crop_buff = *crop_buff_ptr; ++ if (!crop_buff) ++ { ++- crop_buff = ++- (unsigned char *)limitMalloc(cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = (unsigned char *)limitMalloc(padded_cropsize); ++ if (!crop_buff) ++ { ++ TIFFError("createCroppedImage", ++ "Unable to allocate/reallocate crop buffer"); ++ return (-1); ++ } ++- _TIFFmemset(crop_buff, 0, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(crop_buff, 0, padded_cropsize); ++ prev_cropsize = cropsize; ++ } ++ else ++ { ++ if (prev_cropsize < cropsize) ++ { ++- new_buff = (unsigned char *)_TIFFrealloc( ++- crop_buff, cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ new_buff = +++ (unsigned char *)_TIFFrealloc(crop_buff, padded_cropsize); ++ if (!new_buff) ++ { ++ free(crop_buff); ++- crop_buff = (unsigned char *)limitMalloc( ++- cropsize + NUM_BUFF_OVERSIZE_BYTES); +++ crop_buff = (unsigned char *)limitMalloc(padded_cropsize); ++ } ++ else ++ crop_buff = new_buff; ++@@ -9651,35 +10823,49 @@ static int rotateContigSamples8bits(uint16_t rotation, uint16_t spp, ++ return (1); ++ } ++ ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7) / 8; +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) +++ return (1); ++ ready_bits = 0; ++ maskbits = (uint8_t)((uint8_t)-1 >> (8 - bps)); ++ buff1 = buff2 = 0; ++ ++ for (row = 0; row < length; row++) ++ { ++- bit_offset = col * bps * spp; +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); +++ if (row_offset == 0 && row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- src_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ src_bit = bit_offset % 8; ++ ++ switch (rotation) ++ { ++ case 90: ++- next = src + src_byte - (row * rowsize); +++ next = src + src_byte - row_offset; ++ break; ++ case 270: ++- next = src + src_byte + (row * rowsize); +++ { +++ tmsize_t next_offset = +++ _TIFFAddSSize(NULL, row_offset, src_byte, __func__); +++ if (next_offset == 0 && (row_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "sample offset"); +++ return (1); +++ } +++ next = src + next_offset; ++ break; +++ } ++ default: ++ TIFFError("rotateContigSamples8bits", ++ "Invalid rotation %" PRIu16, rotation); ++@@ -9733,34 +10919,48 @@ static int rotateContigSamples16bits(uint16_t rotation, uint16_t spp, ++ return (1); ++ } ++ ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7) / 8; +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) +++ return (1); ++ ready_bits = 0; ++ maskbits = (uint16_t)((uint16_t)-1 >> (16 - bps)); ++ buff1 = buff2 = 0; ++ for (row = 0; row < length; row++) ++ { ++- bit_offset = col * bps * spp; +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); +++ if (row_offset == 0 && row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- src_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ src_bit = bit_offset % 8; ++ ++ switch (rotation) ++ { ++ case 90: ++- next = src + src_byte - (row * rowsize); +++ next = src + src_byte - row_offset; ++ break; ++ case 270: ++- next = src + src_byte + (row * rowsize); +++ { +++ tmsize_t next_offset = +++ _TIFFAddSSize(NULL, row_offset, src_byte, __func__); +++ if (next_offset == 0 && (row_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "sample offset"); +++ return (1); +++ } +++ next = src + next_offset; ++ break; +++ } ++ default: ++ TIFFError("rotateContigSamples8bits", ++ "Invalid rotation %" PRIu16, rotation); ++@@ -9821,34 +11021,48 @@ static int rotateContigSamples24bits(uint16_t rotation, uint16_t spp, ++ return (1); ++ } ++ ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7) / 8; +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) +++ return (1); ++ ready_bits = 0; ++ maskbits = (uint32_t)-1 >> (32 - bps); ++ buff1 = buff2 = 0; ++ for (row = 0; row < length; row++) ++ { ++- bit_offset = col * bps * spp; +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); +++ if (row_offset == 0 && row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- src_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ src_bit = bit_offset % 8; ++ ++ switch (rotation) ++ { ++ case 90: ++- next = src + src_byte - (row * rowsize); +++ next = src + src_byte - row_offset; ++ break; ++ case 270: ++- next = src + src_byte + (row * rowsize); +++ { +++ tmsize_t next_offset = +++ _TIFFAddSSize(NULL, row_offset, src_byte, __func__); +++ if (next_offset == 0 && (row_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "sample offset"); +++ return (1); +++ } +++ next = src + next_offset; ++ break; +++ } ++ default: ++ TIFFError("rotateContigSamples8bits", ++ "Invalid rotation %" PRIu16, rotation); ++@@ -9920,41 +11134,48 @@ static int rotateContigSamples32bits(uint16_t rotation, uint16_t spp, ++ return (1); ++ } ++ ++- /* bytes_per_sample = (bps + 7) / 8; */ ++- /* bytes_per_pixel = ((bps * spp) + 7) / 8; */ ++- /* if (bytes_per_pixel < (bytes_per_sample + 1)) */ ++- /* shift_width = bytes_per_pixel; */ ++- /* else */ ++- /* shift_width = bytes_per_sample + 1; */ ++- ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7) / 8; +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__)) +++ return (1); ++ ready_bits = 0; ++ maskbits = (uint64_t)-1 >> (64 - bps); ++ buff1 = buff2 = 0; ++ for (row = 0; row < length; row++) ++ { ++- bit_offset = col * bps * spp; +++ tmsize_t row_offset = +++ _TIFFComputeRowOffset(NULL, rowsize, row, __func__); +++ if (row_offset == 0 && row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating row offset"); +++ return (1); +++ } ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- src_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ src_bit = bit_offset % 8; ++ ++ switch (rotation) ++ { ++ case 90: ++- next = src + src_byte - (row * rowsize); +++ next = src + src_byte - row_offset; ++ break; ++ case 270: ++- next = src + src_byte + (row * rowsize); +++ { +++ tmsize_t next_offset = +++ _TIFFAddSSize(NULL, row_offset, src_byte, __func__); +++ if (next_offset == 0 && (row_offset != 0 || src_byte != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "sample offset"); +++ return (1); +++ } +++ next = src + next_offset; ++ break; +++ } ++ default: ++ TIFFError("rotateContigSamples8bits", ++ "Invalid rotation %" PRIu16, rotation); ++@@ -10034,43 +11256,60 @@ static int rotateImage(uint16_t rotation, struct image_data *image, ++ spp = image->spp; ++ bps = image->bps; ++ ++- if ((spp != 0 && bps != 0 && ++- width > (uint32_t)((UINT32_MAX - 7) / spp / bps)) || ++- (spp != 0 && bps != 0 && ++- length > (uint32_t)((UINT32_MAX - 7) / spp / bps))) ++- { ++- TIFFError("rotateImage", "Integer overflow detected."); +++ if (computeRowSize32(&rowsize, width, spp, bps, __func__) || +++ computeRowSize32(&colsize, length, spp, bps, __func__)) ++ return (-1); ++- } ++- rowsize = ((uint32_t)bps * (uint32_t)spp * width + 7) / 8; ++- colsize = ((uint32_t)bps * (uint32_t)spp * length + 7) / 8; ++- if ((colsize * width) > (rowsize * length)) ++ { ++- if (((tmsize_t)colsize + 1) != 0 && ++- (tmsize_t)width > ((TIFF_TMSIZE_T_MAX - NUM_BUFF_OVERSIZE_BYTES) / ++- ((tmsize_t)colsize + 1))) +++ uint64_t col_total = +++ _TIFFMultiply64(NULL, colsize, width, "rotation buffer size"); +++ uint64_t row_total = +++ _TIFFMultiply64(NULL, rowsize, length, "rotation buffer size"); +++ if (col_total == 0 || row_total == 0) ++ { ++ TIFFError("rotateImage", ++ "Integer overflow when calculating buffer size."); ++ return (-1); ++ } ++- buffsize = ((tmsize_t)colsize + 1) * width; ++- } ++- else ++- { ++- if (((tmsize_t)rowsize + 1) != 0 && ++- (tmsize_t)length > ((TIFF_TMSIZE_T_MAX - NUM_BUFF_OVERSIZE_BYTES) / ++- ((tmsize_t)rowsize + 1))) +++ if (col_total > row_total) ++ { ++- TIFFError("rotateImage", ++- "Integer overflow when calculating buffer size."); ++- return (-1); +++ tmsize_t col_pitch = +++ _TIFFAddSSize(NULL, colsize, 1, "rotation buffer size"); +++ buffsize = _TIFFMultiplySSize(NULL, col_pitch, width, +++ "rotation buffer size"); +++ if (col_pitch == 0 || buffsize == 0) +++ { +++ TIFFError("rotateImage", +++ "Integer overflow when calculating buffer size."); +++ return (-1); +++ } ++ } ++- buffsize = ((tmsize_t)rowsize + 1) * length; +++ else +++ { +++ tmsize_t row_pitch = +++ _TIFFAddSSize(NULL, rowsize, 1, "rotation buffer size"); +++ buffsize = _TIFFMultiplySSize(NULL, row_pitch, length, +++ "rotation buffer size"); +++ if (row_pitch == 0 || buffsize == 0) +++ { +++ TIFFError("rotateImage", +++ "Integer overflow when calculating buffer size."); +++ return (-1); +++ } +++ } +++ } +++ +++ allocsize = _TIFFAddSSize(NULL, buffsize, NUM_BUFF_OVERSIZE_BYTES, +++ "rotation buffer"); +++ if (allocsize == 0) +++ { +++ TIFFError("rotateImage", +++ "Integer overflow when calculating buffer size."); +++ return (-1); ++ } ++ ++ bytes_per_sample = (uint32_t)((bps + 7) / 8); ++- bytes_per_pixel = (uint32_t)(((bps * spp) + 7) / 8); +++ if (computeRowSize32(&bytes_per_pixel, 1, spp, bps, __func__)) +++ return (-1); ++ if (bytes_per_pixel < (bytes_per_sample + 1)) ++ shift_width = (int)bytes_per_pixel; ++ else ++@@ -10092,16 +11331,15 @@ static int rotateImage(uint16_t rotation, struct image_data *image, ++ } ++ ++ /* Add 3 padding bytes for extractContigSamplesShifted32bits */ ++- if (!(rbuff = ++- (unsigned char *)limitMalloc(buffsize + NUM_BUFF_OVERSIZE_BYTES))) +++ if (!(rbuff = (unsigned char *)limitMalloc(allocsize))) ++ { ++ TIFFError("rotateImage", ++ "Unable to allocate rotation buffer of %" TIFF_SSIZE_FORMAT ++ " bytes ", ++- buffsize + NUM_BUFF_OVERSIZE_BYTES); +++ allocsize); ++ return (-1); ++ } ++- _TIFFmemset(rbuff, '\0', buffsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(rbuff, '\0', allocsize); ++ if (rot_buf_size != NULL) ++ *rot_buf_size = (size_t)buffsize; ++ ++@@ -10112,14 +11350,47 @@ static int rotateImage(uint16_t rotation, struct image_data *image, ++ if ((bps % 8) == 0) /* byte aligned data */ ++ { ++ src = ibuff; ++- pix_offset = (uint32_t)(spp * bps) / 8; +++ pix_offset = bytes_per_pixel; ++ for (row = 0; row < length; row++) ++ { ++- dst_offset = (length - row - 1) * rowsize; +++ uint32_t dst_row = length - row - 1; +++ dst_offset = +++ _TIFFComputeRowOffset(NULL, rowsize, dst_row, __func__); +++ if (dst_offset == 0 && dst_row != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while calculating " +++ "row offset"); +++ _TIFFfree(rbuff); +++ return (-1); +++ } ++ for (col = 0; col < width; col++) ++ { ++- col_offset = (width - col - 1) * pix_offset; ++- dst = rbuff + dst_offset + col_offset; +++ uint32_t dst_col = width - col - 1; +++ col_offset = _TIFFMultiplySSize( +++ NULL, dst_col, pix_offset, "column offset"); +++ if (col_offset == 0 && dst_col != 0) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while " +++ "calculating column offset"); +++ _TIFFfree(rbuff); +++ return (-1); +++ } +++ { +++ tmsize_t total_dst_offset = _TIFFAddSSize( +++ NULL, dst_offset, col_offset, __func__); +++ if (total_dst_offset == 0 && +++ (dst_offset != 0 || col_offset != 0)) +++ { +++ TIFFError(__func__, +++ "Integer overflow detected while " +++ "calculating rotation offset"); +++ _TIFFfree(rbuff); +++ return (-1); +++ } +++ dst = rbuff + total_dst_offset; +++ } ++ ++ for (i = 0; i < bytes_per_pixel; i++) ++ *dst++ = *src++; ++@@ -10395,19 +11728,13 @@ static int reverseSamples8bits(uint16_t spp, uint16_t bps, uint32_t width, ++ for (col = width; col > 0; col--) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = (col - 1) * bps * spp; ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- src_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- src_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col - 1, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ src_bit = bit_offset % 8; ++ ++ src = ibuff + src_byte; ++ match_bits = (uint8_t)(mask_bits << (8 - src_bit - bps)); ++@@ -10459,19 +11786,13 @@ static int reverseSamples16bits(uint16_t spp, uint16_t bps, uint32_t width, ++ for (col = width; col > 0; col--) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = (col - 1) * bps * spp; ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- high_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- high_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col - 1, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ high_bit = bit_offset % 8; ++ ++ src = ibuff + src_byte; ++ match_bits = (uint16_t)(mask_bits << (16 - high_bit - bps)); ++@@ -10532,19 +11853,13 @@ static int reverseSamples24bits(uint16_t spp, uint16_t bps, uint32_t width, ++ for (col = width; col > 0; col--) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = (col - 1) * bps * spp; ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- high_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- high_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col - 1, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ high_bit = bit_offset % 8; ++ ++ src = ibuff + src_byte; ++ match_bits = mask_bits << (32 - high_bit - bps); ++@@ -10615,29 +11930,16 @@ static int reverseSamples32bits(uint16_t spp, uint16_t bps, uint32_t width, ++ mask_bits = (uint64_t)-1 >> (64 - bps); ++ dst = obuff; ++ ++- /* bytes_per_sample = (bps + 7) / 8; */ ++- /* bytes_per_pixel = ((bps * spp) + 7) / 8; */ ++- /* if (bytes_per_pixel < (bytes_per_sample + 1)) */ ++- /* shift_width = bytes_per_pixel; */ ++- /* else */ ++- /* shift_width = bytes_per_sample + 1; */ ++- ++ for (col = width; col > 0; col--) ++ { ++ /* Compute src byte(s) and bits within byte(s) */ ++- bit_offset = (col - 1) * bps * spp; ++ for (sample = 0; sample < spp; sample++) ++ { ++- if (sample == 0) ++- { ++- src_byte = bit_offset / 8; ++- high_bit = bit_offset % 8; ++- } ++- else ++- { ++- src_byte = (bit_offset + ((uint32_t)sample * bps)) / 8; ++- high_bit = (bit_offset + ((uint32_t)sample * bps)) % 8; ++- } +++ if (computeSampleBitOffset32(&bit_offset, col - 1, sample, spp, bps, +++ __func__)) +++ return (1); +++ src_byte = bit_offset / 8; +++ high_bit = bit_offset % 8; ++ ++ src = ibuff + src_byte; ++ match_bits = mask_bits << (64 - high_bit - bps); ++@@ -10705,7 +12008,8 @@ static int reverseSamplesBytes(uint16_t spp, uint16_t bps, uint32_t width, ++ return (1); ++ } ++ ++- bytes_per_pixel = (uint32_t)(((bps * spp) + 7) / 8); +++ if (computeRowSize32(&bytes_per_pixel, 1, spp, bps, __func__)) +++ return (1); ++ if (bytes_per_pixel > sizeof(swapbuff)) ++ { ++ TIFFError("reverseSamplesBytes", "bytes_per_pixel too large"); ++@@ -10806,16 +12154,19 @@ static int mirrorImage(uint16_t spp, uint16_t bps, uint16_t mirror, ++ } ++ else ++ { /* non 8 bit per sample data */ ++- if (!(line_buff = (unsigned char *)limitMalloc( ++- rowsize + NUM_BUFF_OVERSIZE_BYTES))) +++ if (!(line_buff = (unsigned char *)limitMalloc(padded_rowsize))) ++ { ++ TIFFError("mirrorImage", ++ "Unable to allocate mirror line buffer"); ++ return (-1); ++ } ++- _TIFFmemset(line_buff, '\0', rowsize + NUM_BUFF_OVERSIZE_BYTES); +++ _TIFFmemset(line_buff, '\0', padded_rowsize); ++ bytes_per_sample = (uint32_t)((bps + 7) / 8); ++- bytes_per_pixel = (uint32_t)(((bps * spp) + 7) / 8); +++ if (computeRowSize32(&bytes_per_pixel, 1, spp, bps, __func__)) +++ { +++ _TIFFfree(line_buff); +++ return (-1); +++ } ++ if (bytes_per_pixel < (bytes_per_sample + 1)) ++ shift_width = (int)bytes_per_pixel; ++ else +diff --git a/archive/tools/tiffgt.c b/archive/tools/tiffgt.c +index bd7f45a..027ee10 100644 +--- a/archive/tools/tiffgt.c ++++ b/archive/tools/tiffgt.c +@@ -271,7 +271,13 @@ static int initImage(void) + } + TIFFRGBAImageGet(&img, raster, img.width, img.height); + #if HOST_BIGENDIAN +- TIFFSwabArrayOfLong(raster, img.width * img.height); ++ { ++ uint32_t pixel_count = ++ _TIFFMultiply32(tif, img.width, img.height, "raster pixel count"); ++ if (pixel_count == 0) ++ return -1; ++ TIFFSwabArrayOfLong(raster, pixel_count); ++ } + #endif + return 0; + } +diff --git a/archive/tools/tiffgt.c.rej b/archive/tools/tiffgt.c.rej +new file mode 100644 +index 0000000..8874507 +--- /dev/null ++++ b/archive/tools/tiffgt.c.rej +@@ -0,0 +1,31 @@ ++diff a/archive/tools/tiffgt.c b/archive/tools/tiffgt.c (rejected hunks) ++@@ -170,15 +170,22 @@ int main(int argc, char *argv[]) ++ xmax = (uint32_t)(xmax - xmax / 10.0); ++ ymax = (uint32_t)(ymax - ymax / 10.0); ++ ++- filelist = ++- (char **)_TIFFmalloc((tmsize_t)((size_t)filenum * sizeof(char *))); ++- if (!filelist) ++ { ++- TIFFError(argv[0], "Can not allocate space for the file list."); ++- return EXIT_FAILURE; +++ tmsize_t filelist_size = +++ _TIFFMultiplySSize(NULL, filenum, sizeof(char *), "file list"); +++ if (filelist_size == 0 && filenum != 0) +++ { +++ TIFFError(argv[0], "Can not allocate space for the file list."); +++ return EXIT_FAILURE; +++ } +++ filelist = (char **)_TIFFmalloc(filelist_size); +++ if (!filelist) +++ { +++ TIFFError(argv[0], "Can not allocate space for the file list."); +++ return EXIT_FAILURE; +++ } +++ _TIFFmemcpy(filelist, argv + optind, filelist_size); ++ } ++- _TIFFmemcpy(filelist, argv + optind, ++- (tmsize_t)((size_t)filenum * sizeof(char *))); ++ fileindex = -1; ++ if (nextImage() < 0) ++ { +diff --git a/archive/tools/tiffmedian.c b/archive/tools/tiffmedian.c +index 3d5c9ca..ea9d44d 100644 +--- a/archive/tools/tiffmedian.c ++++ b/archive/tools/tiffmedian.c +@@ -50,6 +50,7 @@ + #endif + + #include "tiffio.h" ++#include "tiffiop.h" + + #ifndef EXIT_SUCCESS + #define EXIT_SUCCESS 0 +diff --git a/archive/tools/tiffmedian.c.rej b/archive/tools/tiffmedian.c.rej +new file mode 100644 +index 0000000..c49fcdb +--- /dev/null ++++ b/archive/tools/tiffmedian.c.rej +@@ -0,0 +1,23 @@ ++diff a/archive/tools/tiffmedian.c b/archive/tools/tiffmedian.c (rejected hunks) ++@@ -425,7 +426,20 @@ static void get_histogram(TIFF *local_in, Colorbox *box) ++ } ++ box->rmin = box->gmin = box->bmin = 999; ++ box->rmax = box->gmax = box->bmax = -1; ++- box->total = imagewidth * imagelength; +++ { +++ uint64_t total64 = _TIFFMultiply64(local_in, imagewidth, imagelength, +++ "image pixel count"); +++ uint32_t total32 = +++ _TIFFCastUInt64ToUInt32(local_in, total64, "image pixel count"); +++ if ((total64 == 0 && imagewidth != 0 && imagelength != 0) || +++ (total32 == 0 && total64 != 0)) +++ { +++ fprintf(stderr, "Image is too large to quantize\n"); +++ _TIFFfree(inputline); +++ exit(EXIT_FAILURE); +++ } +++ box->total = total32; +++ } ++ ++ { ++ uint32_t *ptr = &histogram[0][0][0]; +diff --git a/contrib/addtiffo/tif_overview.c b/contrib/addtiffo/tif_overview.c +index 9a4c344..843db51 100644 +--- a/contrib/addtiffo/tif_overview.c ++++ b/contrib/addtiffo/tif_overview.c +@@ -48,6 +48,7 @@ + /* TODO: update notes in header above */ + + #include ++#include + #include + #include + #include +@@ -161,6 +162,12 @@ uint32_t TIFF_WriteOverview(TIFF *hTIFF, uint32_t nXSize, uint32_t nYSize, + TIFFSetDirectory(hTIFF, (tdir_t)(iNumDir - 1)); + + nOffset = TIFFCurrentDirOffset(hTIFF); ++ if (nOffset > UINT32_MAX) ++ { ++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFF_WriteOverview", ++ "Overview directory offset exceeds classic TIFF range."); ++ return 0; ++ } + + TIFFSetSubDirectory(hTIFF, nBaseDirOffset); + +@@ -649,8 +656,6 @@ void TIFF_ProcessFullResBlock(TIFF *hTIFF, int nPlanarConfig, int bSubsampled, + * Establish the offset into this tile at which we should + * start placing data. + */ +- nTXOff = (nSXOff - nOXOff * nOMult * nOBlockXSize) / nOMult; +- nTYOff = (nSYOff - nOYOff * nOMult * nOBlockYSize) / nOMult; + + #ifdef DBMALLOC + malloc_chain_check(1); +@@ -672,8 +677,6 @@ void TIFF_ProcessFullResBlock(TIFF *hTIFF, int nPlanarConfig, int bSubsampled, + * Establish the offset into this tile at which we should + * start placing data. + */ +- nTXOff = (nSXOff - nOXOff * nOMult * nOBlockXSize) / nOMult; +- nTYOff = (nSYOff - nOYOff * nOMult * nOBlockYSize) / nOMult; + + /* + * Figure out the skew (extra space between ``our samples'') and +@@ -687,8 +690,20 @@ void TIFF_ProcessFullResBlock(TIFF *hTIFF, int nPlanarConfig, int bSubsampled, + } + else + { +- nSkewBits = nBitsPerPixel * (nSamples - 1); +- nSampleByteOffset = (nBitsPerPixel / 8) * iSample; ++ uint64_t nSkewBits64; ++ uint64_t nSampleByteOffset64; ++ ++ if (!TIFFOverviewMul64((uint64_t)nBitsPerPixel, ++ (uint64_t)(nSamples - 1), ++ &nSkewBits64) || ++ nSkewBits64 > INT_MAX || ++ !TIFFOverviewMul64((uint64_t)(nBitsPerPixel / 8), ++ (uint64_t)iSample, ++ &nSampleByteOffset64) || ++ nSampleByteOffset64 > INT_MAX) ++ return; ++ nSkewBits = (int)nSkewBits64; ++ nSampleByteOffset = (int)nSampleByteOffset64; + } + + /* +@@ -725,16 +740,22 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + int (*pfnProgress)(double, void *), void *pProgressData) + + { +- TIFFOvrCache **papoRawBIs; ++ TIFFOvrCache **papoRawBIs = NULL; + uint32_t nXSize, nYSize, nBlockXSize, nBlockYSize; + uint16_t nBitsPerPixel, nPhotometric, nCompressFlag, nSamples, + nPlanarConfig, nSampleFormat; + int bSubsampled; + uint16_t nHorSubsampling, nVerSubsampling; +- int bTiled, nSXOff, nSYOff, i; +- unsigned char *pabySrcTile; +- uint16_t *panRedMap, *panGreenMap, *panBlueMap; +- TIFFErrorHandler pfnWarning; ++ int bTiled, i; ++ uint32_t nSXOff, nSYOff; ++ unsigned char *pabySrcTile = NULL; ++ uint16_t *panRedMap = NULL, *panGreenMap = NULL, *panBlueMap = NULL; ++ uint16_t *panRedMapOwned = NULL; ++ uint16_t *panGreenMapOwned = NULL; ++ uint16_t *panBlueMapOwned = NULL; ++ tmsize_t nOverviewListSize = 0; ++ TIFFErrorHandler pfnWarning = NULL; ++ int bWarningHandlerChanged = FALSE; + + (void)pfnProgress; + (void)pProgressData; +@@ -771,7 +792,7 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + * either Frank Warmerdam warmerdam@pobox.com Joris Van Damme + * info@awaresystems.be + */ +- return; ++ goto cleanup; + } + bSubsampled = 1; + TIFFGetField(hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, +@@ -790,7 +811,7 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + "File `%s' has samples of %d bits per sample. Sample\n" + "sizes of less than 8 bits per sample are not supported.\n", + TIFFFileName(hTIFF), nBitsPerPixel); +- return; ++ goto cleanup; + } + bSubsampled = 0; + nHorSubsampling = 1; +@@ -802,6 +823,7 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + /* rereading directories. */ + /* -------------------------------------------------------------------- */ + pfnWarning = TIFFSetWarningHandler(NULL); ++ bWarningHandlerChanged = TRUE; + + /* -------------------------------------------------------------------- */ + /* Get the base raster block size. */ +@@ -817,6 +839,13 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + TIFFGetField(hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize); + bTiled = TRUE; + } ++ if (nBlockXSize == 0 || nBlockYSize == 0) ++ { ++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFBuildOverviews", ++ "File `%s' has an invalid block size.\n", ++ TIFFFileName(hTIFF)); ++ goto cleanup; ++ } + + /* -------------------------------------------------------------------- */ + /* Capture the palette if there is one. */ +@@ -863,11 +892,23 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, + if (bTiled) + { + if ((nOBlockXSize % 16) != 0) ++ { ++ uint32_t nAdjust = 16 - (nOBlockXSize % 16); ++ if (nOBlockXSize > UINT32_MAX - nAdjust) ++ goto cleanup; + nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16); ++ } + + if ((nOBlockYSize % 16) != 0) ++ { ++ uint32_t nAdjust = 16 - (nOBlockYSize % 16); ++ if (nOBlockYSize > UINT32_MAX - nAdjust) ++ goto cleanup; + nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16); ++ } + } ++ if (nOBlockXSize > INT_MAX || nOBlockYSize > INT_MAX) ++ goto cleanup; + + nDirOffset = TIFF_WriteOverview( + hTIFF, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nSamples, +diff --git a/contrib/addtiffo/tif_overview.c.rej b/contrib/addtiffo/tif_overview.c.rej +new file mode 100644 +index 0000000..c7068d6 +--- /dev/null ++++ b/contrib/addtiffo/tif_overview.c.rej +@@ -0,0 +1,991 @@ ++diff a/contrib/addtiffo/tif_overview.c b/contrib/addtiffo/tif_overview.c (rejected hunks) ++@@ -67,6 +68,132 @@ ++ ++ #define TIFF_DIR_MAX 65534 ++ +++static int TIFFOverviewToSSize(uint64_t value, tmsize_t *out) +++{ +++ if (value > (uint64_t)TIFF_TMSIZE_T_MAX) +++ return 0; +++ *out = (tmsize_t)value; +++ return 1; +++} +++ +++static int TIFFOverviewMulSSize(tmsize_t a, tmsize_t b, tmsize_t *out) +++{ +++ if (a < 0 || b < 0) +++ return 0; +++ if (b != 0 && a > TIFF_TMSIZE_T_MAX / b) +++ return 0; +++ *out = a * b; +++ return 1; +++} +++ +++static int TIFFOverviewMul64(uint64_t a, uint64_t b, uint64_t *out) +++{ +++ if (b != 0 && a > UINT64_MAX / b) +++ return 0; +++ *out = a * b; +++ return 1; +++} +++ +++static int TIFFOverviewAdd64(uint64_t a, uint64_t b, uint64_t *out) +++{ +++ if (a > UINT64_MAX - b) +++ return 0; +++ *out = a + b; +++ return 1; +++} +++ +++static int TIFFOverviewToSize(uint64_t value, size_t *out) +++{ +++ if (value > (uint64_t)((size_t)-1)) +++ return 0; +++ *out = (size_t)value; +++ return 1; +++} +++ +++static int TIFFOverviewPackedOffset(uint32_t y, uint32_t x, uint32_t hSub, +++ uint32_t vSub, uint32_t sampleRowSize, +++ uint32_t sampleBlockSize, size_t *out) +++{ +++ uint64_t offset; +++ uint64_t term; +++ +++ if (!TIFFOverviewMul64((uint64_t)(y / vSub), sampleRowSize, &offset)) +++ return 0; +++ if (!TIFFOverviewMul64((uint64_t)(y % vSub), hSub, &term) || +++ !TIFFOverviewAdd64(offset, term, &offset)) +++ return 0; +++ if (!TIFFOverviewMul64((uint64_t)(x / hSub), sampleBlockSize, &term) || +++ !TIFFOverviewAdd64(offset, term, &offset)) +++ return 0; +++ if (!TIFFOverviewAdd64(offset, x % hSub, &offset)) +++ return 0; +++ return TIFFOverviewToSize(offset, out); +++} +++ +++static int TIFFOverviewSampleOffset(uint32_t y, uint32_t x, +++ uint32_t sampleRowSize, +++ uint32_t sampleBlockSize, +++ uint32_t sampleOffset, size_t *out) +++{ +++ uint64_t offset; +++ uint64_t term; +++ +++ if (!TIFFOverviewMul64(y, sampleRowSize, &offset)) +++ return 0; +++ if (!TIFFOverviewMul64(x, sampleBlockSize, &term) || +++ !TIFFOverviewAdd64(offset, term, &offset)) +++ return 0; +++ if (!TIFFOverviewAdd64(offset, sampleOffset, &offset)) +++ return 0; +++ return TIFFOverviewToSize(offset, out); +++} +++ +++static int TIFFOverviewTileOffset(uint32_t srcOff, uint32_t ovrBlockOff, +++ uint32_t ovrMult, uint32_t ovrBlockSize, +++ uint32_t *tileOff) +++{ +++ uint64_t blockSpan; +++ uint64_t baseOff; +++ +++ if (ovrMult == 0) +++ return 0; +++ +++ if (!TIFFOverviewMul64(ovrMult, ovrBlockSize, &blockSpan) || +++ !TIFFOverviewMul64(ovrBlockOff, blockSpan, &baseOff)) +++ return 0; +++ +++ if (baseOff > srcOff) +++ return 0; +++ +++ *tileOff = (uint32_t)(((uint64_t)srcOff - baseOff) / ovrMult); +++ return 1; +++} +++ +++static int TIFFOverviewAdvanceUInt32(uint32_t *value, uint32_t step) +++{ +++ if (step == 0 || *value > UINT32_MAX - step) +++ return 0; +++ *value += step; +++ return 1; +++} +++ +++static int TIFFOverviewHowMany64(uint64_t value, uint64_t divisor, +++ uint64_t *out) +++{ +++ if (divisor == 0) +++ return 0; +++ +++ *out = value / divisor; +++ if ((value % divisor) != 0) +++ { +++ if (*out == UINT64_MAX) +++ return 0; +++ (*out)++; +++ } +++ +++ return 1; +++} +++ ++ /************************************************************************/ ++ /* TIFF_WriteOverview() */ ++ /* */ ++@@ -276,46 +409,80 @@ static void TIFF_DownSample(unsigned char *pabySrcTile, uint32_t nBlockXSize, ++ uint32_t i, j; ++ int k, nPixelBytes = (nBitsPerPixel) / 8; ++ int nPixelGroupBytes = (nBitsPerPixel + nPixelSkewBits) / 8; +++ int nLineOffset; ++ unsigned char *pabySrc, *pabyDst; ++ double *padfSamples; ++- size_t tpadfSamples_size, padfSamples_size; +++ size_t nDstPixelStep; +++ size_t padfSamples_count, padfSamples_size; +++ uint32_t nXIterations, nYIterations; +++ uint64_t nLineOffset64; ++ ++ assert(nBitsPerPixel >= 8); +++ if (nOMult <= 0 || nPixelBytes <= 0 || nPixelGroupBytes <= 0) +++ return; ++ ++- /* sizeof(double) * nOMult * nOMult */ ++- tpadfSamples_size = (size_t)nOMult * (size_t)nOMult; ++- if ((nOMult != 0) && (tpadfSamples_size / (size_t)nOMult == (size_t)nOMult)) ++- { ++- padfSamples_size = tpadfSamples_size; ++- tpadfSamples_size = padfSamples_size * sizeof(double); ++- if ((tpadfSamples_size / padfSamples_size) == sizeof(double)) ++- padfSamples_size = tpadfSamples_size; ++- else ++- padfSamples_size = 0; ++- } ++- else ++ { ++- padfSamples_size = 0; +++ uint64_t nXIterations64; +++ uint64_t nYIterations64; +++ +++ if (!TIFFOverviewHowMany64(nBlockXSize, (uint32_t)nOMult, +++ &nXIterations64) || +++ !TIFFOverviewHowMany64(nBlockYSize, (uint32_t)nOMult, +++ &nYIterations64) || +++ nXIterations64 > UINT32_MAX || nYIterations64 > UINT32_MAX) +++ return; +++ +++ nXIterations = (uint32_t)nXIterations64; +++ nYIterations = (uint32_t)nYIterations64; ++ } ++- if (padfSamples_size == 0) +++ +++ nLineOffset64 = (uint64_t)(uint32_t)nPixelGroupBytes * nBlockXSize; +++ if (nLineOffset64 > INT_MAX) +++ return; +++ nLineOffset = (int)nLineOffset64; +++ if ((size_t)nPixelBytes > ((size_t)-1) / (size_t)nPixelGroupBytes) +++ return; +++ nDstPixelStep = (size_t)nPixelBytes * (size_t)nPixelGroupBytes; +++ +++ /* sizeof(double) * nOMult * nOMult */ +++ if ((size_t)nOMult > ((size_t)-1) / (size_t)nOMult) +++ return; +++ padfSamples_count = (size_t)nOMult * (size_t)nOMult; +++ if (padfSamples_count > ((size_t)-1) / sizeof(double)) ++ { ++ /* TODO: This is an error condition */ ++ return; ++ } +++ padfSamples_size = padfSamples_count * sizeof(double); ++ padfSamples = (double *)malloc(padfSamples_size); ++ ++ /* ==================================================================== */ ++ /* Loop over scanline chunks to process, establishing where the */ ++ /* data is going. */ ++ /* ==================================================================== */ ++- for (j = 0; j * (uint32_t)nOMult < nBlockYSize; j++) +++ for (j = 0; j < nYIterations; j++) ++ { ++- if (j + nTYOff >= nOBlockYSize) +++ uint64_t dstOffset64; +++ uint64_t dstY64; +++ uint64_t srcY64 = (uint64_t)j * (uint32_t)nOMult; +++ size_t dstOffset; +++ uint32_t srcY; +++ +++ if (srcY64 >= nBlockYSize) ++ break; +++ srcY = (uint32_t)srcY64; ++ ++- pabyDst = pabyOTile + ((j + nTYOff) * nOBlockXSize + nTXOff) * ++- (uint32_t)nPixelBytes * ++- (uint32_t)nPixelGroupBytes; +++ dstY64 = (uint64_t)j + nTYOff; +++ if (dstY64 >= nOBlockYSize || nTXOff >= nOBlockXSize) +++ break; +++ +++ if (!TIFFOverviewMul64(dstY64, nOBlockXSize, &dstOffset64) || +++ !TIFFOverviewAdd64(dstOffset64, nTXOff, &dstOffset64) || +++ !TIFFOverviewMul64(dstOffset64, (uint64_t)nDstPixelStep, +++ &dstOffset64) || +++ !TIFFOverviewToSize(dstOffset64, &dstOffset)) +++ break; +++ pabyDst = pabyOTile + dstOffset; ++ ++ /* -------------------------------------------------------------------- ++ */ ++@@ -326,13 +493,26 @@ static void TIFF_DownSample(unsigned char *pabySrcTile, uint32_t nBlockXSize, ++ if (strncmp(pszResampling, "nearest", 4) == 0 || ++ strncmp(pszResampling, "NEAR", 4) == 0) ++ { ++- pabySrc = pabySrcTile + j * (uint32_t)nOMult * nBlockXSize * ++- (uint32_t)nPixelGroupBytes; ++- ++- for (i = 0; i * (uint32_t)nOMult < nBlockXSize; i++) +++ for (i = 0; i < nXIterations; i++) ++ { ++- if (i + nTXOff >= nOBlockXSize) +++ uint64_t srcX64 = (uint64_t)i * (uint32_t)nOMult; +++ uint32_t srcX; +++ uint64_t pixelOffset; +++ uint64_t srcOffset; +++ +++ if ((uint64_t)i + nTXOff >= nOBlockXSize) +++ break; +++ if (srcX64 >= nBlockXSize) +++ break; +++ srcX = (uint32_t)srcX64; +++ pixelOffset = (uint64_t)srcY * nBlockXSize + srcX; +++ if ((uint32_t)nPixelGroupBytes != 0 && +++ pixelOffset > UINT64_MAX / (uint32_t)nPixelGroupBytes) ++ break; +++ srcOffset = pixelOffset * (uint32_t)nPixelGroupBytes; +++ if (srcOffset > (uint64_t)((size_t)-1)) +++ break; +++ pabySrc = pabySrcTile + (size_t)srcOffset; ++ ++ /* ++ * For now use simple subsampling, from the top left corner ++@@ -342,8 +522,7 @@ static void TIFF_DownSample(unsigned char *pabySrcTile, uint32_t nBlockXSize, ++ for (k = 0; k < nPixelBytes; k++) ++ pabyDst[k] = pabySrc[k]; ++ ++- pabyDst += (uint32_t)nPixelBytes * (uint32_t)nPixelGroupBytes; ++- pabySrc += (uint32_t)nOMult * (uint32_t)nPixelGroupBytes; +++ pabyDst += nDstPixelStep; ++ } ++ } ++ ++@@ -356,35 +535,46 @@ static void TIFF_DownSample(unsigned char *pabySrcTile, uint32_t nBlockXSize, ++ else if (strncmp(pszResampling, "averag", 6) == 0 || ++ strncmp(pszResampling, "AVERAG", 6) == 0) ++ { ++- pabySrc = pabySrcTile + j * (uint32_t)nOMult * nBlockXSize * ++- (uint32_t)nPixelGroupBytes; ++- ++- for (i = 0; i * (uint32_t)nOMult < nBlockXSize; i++) +++ for (i = 0; i < nXIterations; i++) ++ { ++ double dfTotal; ++- uint32_t nXSize, nYSize, iSample; +++ uint32_t srcX, nXSize, nYSize; +++ uint64_t srcX64 = (uint64_t)i * (uint32_t)nOMult; +++ uint64_t pixelOffset; +++ uint64_t srcOffset; +++ uint64_t iSample, nSampleCount; ++ ++- if (i + nTXOff >= nOBlockXSize) +++ if ((uint64_t)i + nTXOff >= nOBlockXSize) ++ break; +++ if (srcX64 >= nBlockXSize) +++ break; +++ srcX = (uint32_t)srcX64; +++ +++ nXSize = MIN((uint32_t)nOMult, nBlockXSize - srcX); +++ nYSize = MIN((uint32_t)nOMult, nBlockYSize - srcY); +++ nSampleCount = (uint64_t)nXSize * nYSize; +++ pixelOffset = (uint64_t)srcY * nBlockXSize + srcX; +++ if ((uint32_t)nPixelGroupBytes != 0 && +++ pixelOffset > UINT64_MAX / (uint32_t)nPixelGroupBytes) +++ break; +++ srcOffset = pixelOffset * (uint32_t)nPixelGroupBytes; +++ if (srcOffset > (uint64_t)((size_t)-1)) +++ break; +++ pabySrc = pabySrcTile + (size_t)srcOffset; ++ ++- nXSize = MIN((uint32_t)nOMult, nBlockXSize - i); ++- nYSize = MIN((uint32_t)nOMult, nBlockYSize - j); ++- ++- TIFF_GetSourceSamples( ++- padfSamples, pabySrc, nPixelBytes, nSampleFormat, nXSize, ++- nYSize, nPixelGroupBytes, ++- (int)((uint32_t)nPixelGroupBytes * nBlockXSize)); +++ TIFF_GetSourceSamples(padfSamples, pabySrc, nPixelBytes, +++ nSampleFormat, nXSize, nYSize, +++ nPixelGroupBytes, nLineOffset); ++ ++ dfTotal = 0; ++- for (iSample = 0; iSample < nXSize * nYSize; iSample++) +++ for (iSample = 0; iSample < nSampleCount; iSample++) ++ { ++ dfTotal += padfSamples[iSample]; ++ } ++ ++ TIFF_SetSample(pabyDst, nPixelBytes, nSampleFormat, ++- dfTotal / (nXSize * nYSize)); +++ dfTotal / (double)nSampleCount); ++ ++- pabySrc += (uint32_t)nOMult * (uint32_t)nPixelGroupBytes; ++ pabyDst += (uint32_t)nPixelBytes; ++ } ++ } ++@@ -407,22 +597,57 @@ static void TIFF_DownSample_Subsampled( ++ int nSampleBlockSize; ++ int nSourceSampleRowSize; ++ int nDestSampleRowSize; +++ uint32_t nSampleBlockSizeU; +++ uint32_t nSourceSampleRowSizeU; +++ uint32_t nDestSampleRowSizeU; +++ uint32_t nOMultU; +++ uint32_t nHorSubsamplingU; +++ uint32_t nVerSubsamplingU; ++ uint32_t nSourceX, nSourceY; ++ uint32_t nSourceXSec, nSourceYSec; ++ uint32_t nSourceXSecEnd, nSourceYSecEnd; ++ uint32_t nDestX, nDestY; ++ int nSampleOffsetInSampleBlock; ++- unsigned int nCummulator; ++- unsigned int nCummulatorCount; ++- ++- nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2; ++- nSourceSampleRowSize = ++- (int)(((nBlockXSize + (uint32_t)nHorSubsampling - 1) / ++- (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize); ++- nDestSampleRowSize = (int)(((nOBlockXSize + (uint32_t)nHorSubsampling - 1) / ++- (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize); +++ uint64_t nCummulator; +++ uint64_t nCummulatorCount; +++ uint64_t nTmp; +++ +++ if (nOMult <= 0 || nHorSubsampling <= 0 || nVerSubsampling <= 0) +++ return; +++ nOMultU = (uint32_t)nOMult; +++ nHorSubsamplingU = (uint32_t)nHorSubsampling; +++ nVerSubsamplingU = (uint32_t)nVerSubsampling; +++ +++ if (!TIFFOverviewMul64(nHorSubsamplingU, nVerSubsamplingU, &nTmp) || +++ !TIFFOverviewAdd64(nTmp, 2, &nTmp) || nTmp > INT_MAX) +++ return; +++ nSampleBlockSize = (int)nTmp; +++ nSampleBlockSizeU = (uint32_t)nSampleBlockSize; +++ +++ { +++ uint64_t nSourceSamplesPerRow; +++ +++ if (!TIFFOverviewHowMany64(nBlockXSize, nHorSubsamplingU, +++ &nSourceSamplesPerRow) || +++ !TIFFOverviewMul64(nSourceSamplesPerRow, nSampleBlockSizeU, +++ &nTmp) || +++ nTmp > INT_MAX) +++ return; +++ } +++ nSourceSampleRowSize = (int)nTmp; +++ nSourceSampleRowSizeU = (uint32_t)nSourceSampleRowSize; +++ +++ { +++ uint64_t nDestSamplesPerRow; +++ +++ if (!TIFFOverviewHowMany64(nOBlockXSize, nHorSubsamplingU, +++ &nDestSamplesPerRow) || +++ !TIFFOverviewMul64(nDestSamplesPerRow, nSampleBlockSizeU, &nTmp) || +++ nTmp > INT_MAX) +++ return; +++ } +++ nDestSampleRowSize = (int)nTmp; +++ nDestSampleRowSizeU = (uint32_t)nDestSampleRowSize; ++ ++ if (strncmp(pszResampling, "nearest", 4) == 0 || ++ strncmp(pszResampling, "NEAR", 4) == 0) ++@@ -430,63 +655,94 @@ static void TIFF_DownSample_Subsampled( ++ if (nSample == 0) ++ { ++ for (nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; ++- nSourceY += (uint32_t)nOMult, nDestY++) +++ nDestY++) ++ { ++ if (nDestY >= nOBlockYSize) ++ break; ++ ++ for (nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; ++- nSourceX += (uint32_t)nOMult, nDestX++) +++ nDestX++) ++ { +++ size_t nDstOffset; +++ size_t nSrcOffset; +++ ++ if (nDestX >= nOBlockXSize) ++ break; ++ ++- *(pabyOTile + ++- (nDestY / (uint32_t)nVerSubsampling) * ++- (uint32_t)nDestSampleRowSize + ++- (nDestY % (uint32_t)nVerSubsampling) * ++- (uint32_t)nHorSubsampling + ++- (nDestX / (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize + ++- (nDestX % (uint32_t)nHorSubsampling)) = ++- *(pabySrcTile + ++- (nSourceY / (uint32_t)nVerSubsampling) * ++- (uint32_t)nSourceSampleRowSize + ++- (nSourceY % (uint32_t)nVerSubsampling) * ++- (uint32_t)nHorSubsampling + ++- (nSourceX / (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize + ++- (nSourceX % (uint32_t)nHorSubsampling)); +++ if (!TIFFOverviewPackedOffset( +++ nDestY, nDestX, nHorSubsamplingU, nVerSubsamplingU, +++ nDestSampleRowSizeU, nSampleBlockSizeU, +++ &nDstOffset) || +++ !TIFFOverviewPackedOffset( +++ nSourceY, nSourceX, nHorSubsamplingU, +++ nVerSubsamplingU, nSourceSampleRowSizeU, +++ nSampleBlockSizeU, &nSrcOffset)) +++ return; +++ +++ pabyOTile[nDstOffset] = pabySrcTile[nSrcOffset]; +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceX, nOMultU)) +++ break; ++ } +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceY, nOMultU)) +++ break; ++ } ++ } ++ else ++ { ++- nSampleOffsetInSampleBlock = ++- nHorSubsampling * nVerSubsampling + nSample - 1; ++- for (nSourceY = 0, nDestY = (nTYOff / (uint32_t)nVerSubsampling); ++- nSourceY < (nBlockYSize / (uint32_t)nVerSubsampling); ++- nSourceY += (uint32_t)nOMult, nDestY++) +++ uint64_t nSampleOffset64; +++ if (nSample <= 0 || +++ !TIFFOverviewMul64(nHorSubsamplingU, nVerSubsamplingU, +++ &nSampleOffset64) || +++ !TIFFOverviewAdd64(nSampleOffset64, (uint32_t)(nSample - 1), +++ &nSampleOffset64) || +++ nSampleOffset64 >= nSampleBlockSizeU || +++ nSampleOffset64 > INT_MAX) +++ return; +++ nSampleOffsetInSampleBlock = (int)nSampleOffset64; +++ for (nSourceY = 0, nDestY = (nTYOff / nVerSubsamplingU); +++ nSourceY < (nBlockYSize / nVerSubsamplingU); nDestY++) ++ { ++- if (nDestY * (uint32_t)nVerSubsampling >= nOBlockYSize) +++ uint64_t nDestYPixel; +++ +++ if (!TIFFOverviewMul64(nDestY, nVerSubsamplingU, &nDestYPixel)) +++ return; +++ if (nDestYPixel >= nOBlockYSize) ++ break; ++ ++- for (nSourceX = 0, ++- nDestX = (nTXOff / (uint32_t)nHorSubsampling); ++- nSourceX < (nBlockXSize / (uint32_t)nHorSubsampling); ++- nSourceX += (uint32_t)nOMult, nDestX++) +++ for (nSourceX = 0, nDestX = (nTXOff / nHorSubsamplingU); +++ nSourceX < (nBlockXSize / nHorSubsamplingU); nDestX++) ++ { ++- if (nDestX * (uint32_t)nHorSubsampling >= nOBlockXSize) +++ uint64_t nDestXPixel; +++ size_t nDstOffset; +++ size_t nSrcOffset; +++ +++ if (!TIFFOverviewMul64(nDestX, nHorSubsamplingU, +++ &nDestXPixel)) +++ return; +++ if (nDestXPixel >= nOBlockXSize) ++ break; ++ ++- *(pabyOTile + nDestY * (uint32_t)nDestSampleRowSize + ++- nDestX * (uint32_t)nSampleBlockSize + ++- (uint32_t)nSampleOffsetInSampleBlock) = ++- *(pabySrcTile + ++- nSourceY * (uint32_t)nSourceSampleRowSize + ++- nSourceX * (uint32_t)nSampleBlockSize + ++- (uint32_t)nSampleOffsetInSampleBlock); +++ if (!TIFFOverviewSampleOffset( +++ nDestY, nDestX, nDestSampleRowSizeU, +++ nSampleBlockSizeU, +++ (uint32_t)nSampleOffsetInSampleBlock, +++ &nDstOffset) || +++ !TIFFOverviewSampleOffset( +++ nSourceY, nSourceX, nSourceSampleRowSizeU, +++ nSampleBlockSizeU, +++ (uint32_t)nSampleOffsetInSampleBlock, &nSrcOffset)) +++ return; +++ +++ pabyOTile[nDstOffset] = pabySrcTile[nSrcOffset]; +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceX, nOMultU)) +++ break; ++ } +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceY, nOMultU)) +++ break; ++ } ++ } ++ } ++@@ -496,23 +752,30 @@ static void TIFF_DownSample_Subsampled( ++ if (nSample == 0) ++ { ++ for (nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; ++- nSourceY += (uint32_t)nOMult, nDestY++) +++ nDestY++) ++ { ++ if (nDestY >= nOBlockYSize) ++ break; ++ ++ for (nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; ++- nSourceX += (uint32_t)nOMult, nDestX++) +++ nDestX++) ++ { +++ uint64_t nSectionEnd64; +++ size_t nDstOffset; +++ ++ if (nDestX >= nOBlockXSize) ++ break; ++ ++- nSourceXSecEnd = nSourceX + (uint32_t)nOMult; ++- if (nSourceXSecEnd > nBlockXSize) +++ nSectionEnd64 = (uint64_t)nSourceX + nOMultU; +++ if (nSectionEnd64 > nBlockXSize) ++ nSourceXSecEnd = nBlockXSize; ++- nSourceYSecEnd = nSourceY + (uint32_t)nOMult; ++- if (nSourceYSecEnd > nBlockYSize) +++ else +++ nSourceXSecEnd = (uint32_t)nSectionEnd64; +++ nSectionEnd64 = (uint64_t)nSourceY + nOMultU; +++ if (nSectionEnd64 > nBlockYSize) ++ nSourceYSecEnd = nBlockYSize; +++ else +++ nSourceYSecEnd = (uint32_t)nSectionEnd64; ++ nCummulator = 0; ++ for (nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; ++ nSourceYSec++) ++@@ -520,62 +783,85 @@ static void TIFF_DownSample_Subsampled( ++ for (nSourceXSec = nSourceX; ++ nSourceXSec < nSourceXSecEnd; nSourceXSec++) ++ { ++- nCummulator += ++- *(pabySrcTile + ++- (nSourceYSec / (uint32_t)nVerSubsampling) * ++- (uint32_t)nSourceSampleRowSize + ++- (nSourceYSec % (uint32_t)nVerSubsampling) * ++- (uint32_t)nHorSubsampling + ++- (nSourceXSec / (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize + ++- (nSourceXSec % (uint32_t)nHorSubsampling)); +++ size_t nSrcOffset; +++ if (!TIFFOverviewPackedOffset( +++ nSourceYSec, nSourceXSec, nHorSubsamplingU, +++ nVerSubsamplingU, nSourceSampleRowSizeU, +++ nSampleBlockSizeU, &nSrcOffset) || +++ nCummulator > +++ UINT64_MAX - pabySrcTile[nSrcOffset]) +++ return; +++ nCummulator += pabySrcTile[nSrcOffset]; ++ } ++ } ++- nCummulatorCount = (nSourceXSecEnd - nSourceX) * ++- (nSourceYSecEnd - nSourceY); ++- *(pabyOTile + ++- (nDestY / (uint32_t)nVerSubsampling) * ++- (uint32_t)nDestSampleRowSize + ++- (nDestY % (uint32_t)nVerSubsampling) * ++- (uint32_t)nHorSubsampling + ++- (nDestX / (uint32_t)nHorSubsampling) * ++- (uint32_t)nSampleBlockSize + ++- (nDestX % (uint32_t)nHorSubsampling)) = +++ if (!TIFFOverviewMul64(nSourceXSecEnd - nSourceX, +++ nSourceYSecEnd - nSourceY, +++ &nCummulatorCount) || +++ nCummulatorCount == 0 || +++ !TIFFOverviewPackedOffset( +++ nDestY, nDestX, nHorSubsamplingU, nVerSubsamplingU, +++ nDestSampleRowSizeU, nSampleBlockSizeU, +++ &nDstOffset)) +++ return; +++ pabyOTile[nDstOffset] = ++ (unsigned char)((nCummulator + ++ (nCummulatorCount >> 1)) / ++ nCummulatorCount); +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceX, nOMultU)) +++ break; ++ } +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceY, nOMultU)) +++ break; ++ } ++ } ++ else ++ { ++- nSampleOffsetInSampleBlock = ++- nHorSubsampling * nVerSubsampling + nSample - 1; ++- for (nSourceY = 0, nDestY = (nTYOff / (uint32_t)nVerSubsampling); ++- nSourceY < (nBlockYSize / (uint32_t)nVerSubsampling); ++- nSourceY += (uint32_t)nOMult, nDestY++) +++ uint64_t nSampleOffset64; +++ if (nSample <= 0 || +++ !TIFFOverviewMul64(nHorSubsamplingU, nVerSubsamplingU, +++ &nSampleOffset64) || +++ !TIFFOverviewAdd64(nSampleOffset64, (uint32_t)(nSample - 1), +++ &nSampleOffset64) || +++ nSampleOffset64 >= nSampleBlockSizeU || +++ nSampleOffset64 > INT_MAX) +++ return; +++ nSampleOffsetInSampleBlock = (int)nSampleOffset64; +++ for (nSourceY = 0, nDestY = (nTYOff / nVerSubsamplingU); +++ nSourceY < (nBlockYSize / nVerSubsamplingU); nDestY++) ++ { ++- if (nDestY * (uint32_t)nVerSubsampling >= nOBlockYSize) +++ uint64_t nDestYPixel; +++ if (!TIFFOverviewMul64(nDestY, nVerSubsamplingU, &nDestYPixel)) +++ return; +++ if (nDestYPixel >= nOBlockYSize) ++ break; ++ ++- for (nSourceX = 0, ++- nDestX = (nTXOff / (uint32_t)nHorSubsampling); ++- nSourceX < (nBlockXSize / (uint32_t)nHorSubsampling); ++- nSourceX += (uint32_t)nOMult, nDestX++) +++ for (nSourceX = 0, nDestX = (nTXOff / nHorSubsamplingU); +++ nSourceX < (nBlockXSize / nHorSubsamplingU); nDestX++) ++ { ++- if (nDestX * (uint32_t)nHorSubsampling >= nOBlockXSize) +++ uint32_t nSourceXLimit = nBlockXSize / nHorSubsamplingU; +++ uint32_t nSourceYLimit = nBlockYSize / nVerSubsamplingU; +++ uint64_t nDestXPixel; +++ uint64_t nSectionEnd64; +++ size_t nDstOffset; +++ +++ if (!TIFFOverviewMul64(nDestX, nHorSubsamplingU, +++ &nDestXPixel)) +++ return; +++ if (nDestXPixel >= nOBlockXSize) ++ break; ++ ++- nSourceXSecEnd = nSourceX + (uint32_t)nOMult; ++- if (nSourceXSecEnd > ++- (nBlockXSize / (uint32_t)nHorSubsampling)) ++- nSourceXSecEnd = ++- (nBlockXSize / (uint32_t)nHorSubsampling); ++- nSourceYSecEnd = nSourceY + (uint32_t)nOMult; ++- if (nSourceYSecEnd > ++- (nBlockYSize / (uint32_t)nVerSubsampling)) ++- nSourceYSecEnd = ++- (nBlockYSize / (uint32_t)nVerSubsampling); +++ nSectionEnd64 = (uint64_t)nSourceX + nOMultU; +++ if (nSectionEnd64 > nSourceXLimit) +++ nSourceXSecEnd = nSourceXLimit; +++ else +++ nSourceXSecEnd = (uint32_t)nSectionEnd64; +++ nSectionEnd64 = (uint64_t)nSourceY + nOMultU; +++ if (nSectionEnd64 > nSourceYLimit) +++ nSourceYSecEnd = nSourceYLimit; +++ else +++ nSourceYSecEnd = (uint32_t)nSectionEnd64; ++ nCummulator = 0; ++ for (nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; ++ nSourceYSec++) ++@@ -583,22 +869,38 @@ static void TIFF_DownSample_Subsampled( ++ for (nSourceXSec = nSourceX; ++ nSourceXSec < nSourceXSecEnd; nSourceXSec++) ++ { ++- nCummulator += ++- *(pabySrcTile + ++- nSourceYSec * (uint32_t)nSourceSampleRowSize + ++- nSourceXSec * (uint32_t)nSampleBlockSize + ++- (uint32_t)nSampleOffsetInSampleBlock); +++ size_t nSrcOffset; +++ if (!TIFFOverviewSampleOffset( +++ nSourceYSec, nSourceXSec, +++ nSourceSampleRowSizeU, nSampleBlockSizeU, +++ (uint32_t)nSampleOffsetInSampleBlock, +++ &nSrcOffset) || +++ nCummulator > +++ UINT64_MAX - pabySrcTile[nSrcOffset]) +++ return; +++ nCummulator += pabySrcTile[nSrcOffset]; ++ } ++ } ++- nCummulatorCount = (nSourceXSecEnd - nSourceX) * ++- (nSourceYSecEnd - nSourceY); ++- *(pabyOTile + nDestY * (uint32_t)nDestSampleRowSize + ++- nDestX * (uint32_t)nSampleBlockSize + ++- (uint32_t)nSampleOffsetInSampleBlock) = +++ if (!TIFFOverviewMul64(nSourceXSecEnd - nSourceX, +++ nSourceYSecEnd - nSourceY, +++ &nCummulatorCount) || +++ nCummulatorCount == 0 || +++ !TIFFOverviewSampleOffset( +++ nDestY, nDestX, nDestSampleRowSizeU, +++ nSampleBlockSizeU, +++ (uint32_t)nSampleOffsetInSampleBlock, &nDstOffset)) +++ return; +++ pabyOTile[nDstOffset] = ++ (unsigned char)((nCummulator + ++ (nCummulatorCount >> 1)) / ++ nCummulatorCount); +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceX, nOMultU)) +++ break; ++ } +++ +++ if (!TIFFOverviewAdvanceUInt32(&nSourceY, nOMultU)) +++ break; ++ } ++ } ++ } ++@@ -634,18 +936,23 @@ void TIFF_ProcessFullResBlock(TIFF *hTIFF, int nPlanarConfig, int bSubsampled, ++ { ++ if (TIFFIsTiled(hTIFF)) ++ { +++ tmsize_t nTileSize = TIFFTileSize(hTIFF); +++ if (nTileSize <= 0) +++ return; ++ TIFFReadEncodedTile(hTIFF, ++ TIFFComputeTile(hTIFF, nSXOff, nSYOff, 0, ++ (tsample_t)iSample), ++- pabySrcTile, TIFFTileSize(hTIFF)); +++ pabySrcTile, nTileSize); ++ } ++ else ++ { ++- /* Silence Coverity Scan warning about checking return. */ ++- /* coverity[check_return:SUPPRESS] */ +++ tmsize_t nStripSize = TIFFStripSize(hTIFF); +++ if (nStripSize <= 0) +++ return; +++ ++ TIFFReadEncodedStrip( ++ hTIFF, TIFFComputeStrip(hTIFF, nSYOff, (tsample_t)iSample), ++- pabySrcTile, TIFFStripSize(hTIFF)); +++ pabySrcTile, nStripSize); ++ } ++ } ++ ++@@ -665,8 +972,15 @@ void TIFF_ProcessFullResBlock(TIFF *hTIFF, int nPlanarConfig, int bSubsampled, ++ * Fetch the destination overview tile ++ */ ++ nOMult = (uint32_t)panOvList[iOverview]; +++ if (nOMult == 0 || nOBlockXSize == 0 || nOBlockYSize == 0) +++ return; ++ nOXOff = (nSXOff / nOMult) / nOBlockXSize; ++ nOYOff = (nSYOff / nOMult) / nOBlockYSize; +++ if (!TIFFOverviewTileOffset(nSXOff, nOXOff, nOMult, nOBlockXSize, +++ &nTXOff) || +++ !TIFFOverviewTileOffset(nSYOff, nOYOff, nOMult, nOBlockYSize, +++ &nTYOff)) +++ return; ++ ++ if (bSubsampled) ++ { ++@@ -855,19 +1191,49 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, ++ &panBlueMap)) ++ { ++ uint16_t *panRed2, *panGreen2, *panBlue2; ++- int nColorCount = 1 << nBitsPerPixel; +++ uint64_t nColorCount; +++ uint64_t nColorBytes64; +++ tmsize_t nColorBytes; ++ ++- panRed2 = (uint16_t *)_TIFFmalloc(2 * nColorCount); ++- panGreen2 = (uint16_t *)_TIFFmalloc(2 * nColorCount); ++- panBlue2 = (uint16_t *)_TIFFmalloc(2 * nColorCount); +++ if (nBitsPerPixel >= 64) +++ { +++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFBuildOverviews", +++ "BitsPerSample is too large for a palette.\n"); +++ goto cleanup; +++ } +++ nColorCount = 1ULL << nBitsPerPixel; +++ if (!TIFFOverviewMul64(nColorCount, sizeof(uint16_t), &nColorBytes64) || +++ !TIFFOverviewToSSize(nColorBytes64, &nColorBytes)) +++ { +++ goto cleanup; +++ } +++ +++ panRed2 = (uint16_t *)_TIFFmalloc(nColorBytes); +++ panGreen2 = (uint16_t *)_TIFFmalloc(nColorBytes); +++ panBlue2 = (uint16_t *)_TIFFmalloc(nColorBytes); +++ if (panRed2 == NULL || panGreen2 == NULL || panBlue2 == NULL) +++ { +++ _TIFFfree(panRed2); +++ _TIFFfree(panGreen2); +++ _TIFFfree(panBlue2); +++ goto cleanup; +++ } +++ +++ memcpy(panRed2, panRedMap, (size_t)nColorBytes); +++ memcpy(panGreen2, panGreenMap, (size_t)nColorBytes); +++ memcpy(panBlue2, panBlueMap, (size_t)nColorBytes); ++ ++- memcpy(panRed2, panRedMap, 2 * (size_t)nColorCount); ++- memcpy(panGreen2, panGreenMap, 2 * (size_t)nColorCount); ++- memcpy(panBlue2, panBlueMap, 2 * (size_t)nColorCount); +++ panRedMapOwned = panRed2; +++ panGreenMapOwned = panGreen2; +++ panBlueMapOwned = panBlue2; ++ ++- panRedMap = panRed2; ++- panGreenMap = panGreen2; ++- panBlueMap = panBlue2; +++ panRed2 = NULL; +++ panGreen2 = NULL; +++ panBlue2 = NULL; +++ +++ panRedMap = panRedMapOwned; +++ panGreenMap = panGreenMapOwned; +++ panBlueMap = panBlueMapOwned; ++ } ++ else ++ { ++@@ -877,18 +1243,41 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, ++ /* -------------------------------------------------------------------- */ ++ /* Initialize overviews. */ ++ /* -------------------------------------------------------------------- */ ++- papoRawBIs = (TIFFOvrCache **)_TIFFmalloc( ++- (tmsize_t)((size_t)nOverviews * sizeof(void *))); +++ if (nOverviews <= 0) +++ { +++ goto cleanup; +++ } +++ if (!TIFFOverviewMulSSize((tmsize_t)nOverviews, (tmsize_t)sizeof(void *), +++ &nOverviewListSize)) +++ goto cleanup; +++ papoRawBIs = (TIFFOvrCache **)_TIFFmalloc(nOverviewListSize); +++ if (papoRawBIs == NULL) +++ { +++ goto cleanup; +++ } +++ _TIFFmemset(papoRawBIs, 0, nOverviewListSize); ++ ++ for (i = 0; i < nOverviews; i++) ++ { ++ uint32_t nOXSize, nOYSize, nOBlockXSize, nOBlockYSize; ++ toff_t nDirOffset; ++ ++- nOXSize = ++- (nXSize + (uint32_t)panOvList[i] - 1) / (uint32_t)panOvList[i]; ++- nOYSize = ++- (nYSize + (uint32_t)panOvList[i] - 1) / (uint32_t)panOvList[i]; +++ if (panOvList[i] <= 0) +++ goto cleanup; +++ +++ { +++ uint64_t nOXSize64; +++ uint64_t nOYSize64; +++ uint32_t nOverviewFactor = (uint32_t)panOvList[i]; +++ +++ if (!TIFFOverviewHowMany64(nXSize, nOverviewFactor, &nOXSize64) || +++ !TIFFOverviewHowMany64(nYSize, nOverviewFactor, &nOYSize64) || +++ nOXSize64 > UINT32_MAX || nOYSize64 > UINT32_MAX) +++ goto cleanup; +++ +++ nOXSize = (uint32_t)nOXSize64; +++ nOYSize = (uint32_t)nOYSize64; +++ } ++ ++ nOBlockXSize = MIN(nBlockXSize, nOXSize); ++ nOBlockYSize = MIN(nBlockYSize, nOYSize); ++@@ -909,30 +1310,37 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, ++ bUseSubIFDs, nHorSubsampling, nVerSubsampling); ++ ++ papoRawBIs[i] = TIFFCreateOvrCache(hTIFF, nDirOffset); ++- } ++- ++- if (panRedMap != NULL) ++- { ++- _TIFFfree(panRedMap); ++- _TIFFfree(panGreenMap); ++- _TIFFfree(panBlueMap); +++ if (papoRawBIs[i] == NULL) +++ goto cleanup; ++ } ++ ++ /* -------------------------------------------------------------------- */ ++ /* Allocate a buffer to hold a source block. */ ++ /* -------------------------------------------------------------------- */ ++ if (bTiled) ++- pabySrcTile = (unsigned char *)_TIFFmalloc(TIFFTileSize(hTIFF)); +++ { +++ tmsize_t nTileSize = TIFFTileSize(hTIFF); +++ if (nTileSize <= 0) +++ goto cleanup; +++ pabySrcTile = (unsigned char *)_TIFFmalloc(nTileSize); +++ } ++ else ++- pabySrcTile = (unsigned char *)_TIFFmalloc(TIFFStripSize(hTIFF)); +++ { +++ tmsize_t nStripSize = TIFFStripSize(hTIFF); +++ if (nStripSize <= 0) +++ goto cleanup; +++ pabySrcTile = (unsigned char *)_TIFFmalloc(nStripSize); +++ } +++ if (pabySrcTile == NULL) +++ goto cleanup; ++ ++ /* -------------------------------------------------------------------- */ ++ /* Loop over the source raster, applying data to the */ ++ /* destination raster. */ ++ /* -------------------------------------------------------------------- */ ++- for (nSYOff = 0; nSYOff < (int)nYSize; nSYOff += (int)nBlockYSize) +++ for (nSYOff = 0; nSYOff < nYSize; nSYOff += nBlockYSize) ++ { ++- for (nSXOff = 0; nSXOff < (int)nXSize; nSXOff += (int)nBlockXSize) +++ for (nSXOff = 0; nSXOff < nXSize; nSXOff += nBlockXSize) ++ { ++ /* ++ * Read and resample into the various overview images. ++@@ -941,23 +1349,33 @@ void TIFFBuildOverviews(TIFF *hTIFF, int nOverviews, int *panOvList, ++ TIFF_ProcessFullResBlock( ++ hTIFF, nPlanarConfig, bSubsampled, nHorSubsampling, ++ nVerSubsampling, nOverviews, panOvList, nBitsPerPixel, nSamples, ++- papoRawBIs, (uint32_t)nSXOff, (uint32_t)nSYOff, pabySrcTile, ++- nBlockXSize, nBlockYSize, nSampleFormat, pszResampleMethod); +++ papoRawBIs, nSXOff, nSYOff, pabySrcTile, nBlockXSize, +++ nBlockYSize, nSampleFormat, pszResampleMethod); +++ if (nXSize - nSXOff <= nBlockXSize) +++ break; ++ } +++ if (nYSize - nSYOff <= nBlockYSize) +++ break; ++ } ++ +++cleanup: ++ _TIFFfree(pabySrcTile); +++ _TIFFfree(panRedMapOwned); +++ _TIFFfree(panGreenMapOwned); +++ _TIFFfree(panBlueMapOwned); ++ ++ /* -------------------------------------------------------------------- */ ++ /* Cleanup the rawblockedimage files. */ ++ /* -------------------------------------------------------------------- */ ++ for (i = 0; i < nOverviews; i++) ++ { ++- TIFFDestroyOvrCache(papoRawBIs[i]); +++ if (papoRawBIs != NULL && papoRawBIs[i] != NULL) +++ TIFFDestroyOvrCache(papoRawBIs[i]); ++ } ++ ++ if (papoRawBIs != NULL) ++ _TIFFfree(papoRawBIs); ++ ++- TIFFSetWarningHandler(pfnWarning); +++ if (bWarningHandlerChanged) +++ TIFFSetWarningHandler(pfnWarning); ++ } +diff --git a/contrib/addtiffo/tif_ovrcache.c b/contrib/addtiffo/tif_ovrcache.c +index 9cbf09d..6db6399 100644 +--- a/contrib/addtiffo/tif_ovrcache.c ++++ b/contrib/addtiffo/tif_ovrcache.c +@@ -42,6 +42,7 @@ TIFFOvrCache *TIFFCreateOvrCache(TIFF *hTIFF, toff_t nDirOffset) + + { + TIFFOvrCache *psCache; ++ tmsize_t nBytesPerRowSize = 0; + toff_t nBaseDirOffset; + int nRet; + +diff --git a/contrib/addtiffo/tif_ovrcache.c.rej b/contrib/addtiffo/tif_ovrcache.c.rej +new file mode 100644 +index 0000000..0b31916 +--- /dev/null ++++ b/contrib/addtiffo/tif_ovrcache.c.rej +@@ -0,0 +1,376 @@ ++diff a/contrib/addtiffo/tif_ovrcache.c b/contrib/addtiffo/tif_ovrcache.c (rejected hunks) ++@@ -66,16 +67,34 @@ TIFFOvrCache *TIFFCreateOvrCache(TIFF *hTIFF, toff_t nDirOffset) ++ ++ if (!TIFFIsTiled(hTIFF)) ++ { +++ tmsize_t nBlockSize; ++ TIFFGetField(hTIFF, TIFFTAG_ROWSPERSTRIP, &(psCache->nBlockYSize)); ++ psCache->nBlockXSize = psCache->nXSize; ++- psCache->nBytesPerBlock = (toff_t)TIFFStripSize(hTIFF); +++ nBlockSize = TIFFStripSize(hTIFF); +++ if (nBlockSize <= 0) +++ { +++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFCreateOvrCache", +++ "Invalid overview strip size."); +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ psCache->nBytesPerBlock = (toff_t)nBlockSize; ++ psCache->bTiled = FALSE; ++ } ++ else ++ { +++ tmsize_t nBlockSize; ++ TIFFGetField(hTIFF, TIFFTAG_TILEWIDTH, &(psCache->nBlockXSize)); ++ TIFFGetField(hTIFF, TIFFTAG_TILELENGTH, &(psCache->nBlockYSize)); ++- psCache->nBytesPerBlock = (toff_t)TIFFTileSize(hTIFF); +++ nBlockSize = TIFFTileSize(hTIFF); +++ if (nBlockSize <= 0) +++ { +++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFCreateOvrCache", +++ "Invalid overview tile size."); +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ psCache->nBytesPerBlock = (toff_t)nBlockSize; ++ psCache->bTiled = TRUE; ++ } ++ ++@@ -83,29 +102,68 @@ TIFFOvrCache *TIFFCreateOvrCache(TIFF *hTIFF, toff_t nDirOffset) ++ /* Compute some values from this. */ ++ /* -------------------------------------------------------------------- */ ++ ++- psCache->nBlocksPerRow = ++- (int)((psCache->nXSize + psCache->nBlockXSize - 1) / ++- psCache->nBlockXSize); ++- psCache->nBlocksPerColumn = ++- (int)((psCache->nYSize + psCache->nBlockYSize - 1) / ++- psCache->nBlockYSize); +++ if (psCache->nBlockXSize == 0 || psCache->nBlockYSize == 0) +++ { +++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFCreateOvrCache", +++ "Invalid overview block size."); +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ { +++ uint64_t nBlocksPerRow = +++ TIFFhowmany_64(psCache->nXSize, psCache->nBlockXSize); +++ uint64_t nBlocksPerColumn = +++ TIFFhowmany_64(psCache->nYSize, psCache->nBlockYSize); +++ if (nBlocksPerRow > INT_MAX || nBlocksPerColumn > INT_MAX) +++ { +++ TIFFErrorExt(TIFFClientdata(hTIFF), "TIFFCreateOvrCache", +++ "Too many overview blocks."); +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ psCache->nBlocksPerRow = (int)nBlocksPerRow; +++ psCache->nBlocksPerColumn = (int)nBlocksPerColumn; +++ } ++ ++- if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) ++- psCache->nBytesPerRow = psCache->nBytesPerBlock * ++- (toff_t)psCache->nBlocksPerRow * ++- psCache->nSamples; ++- else ++- psCache->nBytesPerRow = ++- psCache->nBytesPerBlock * (toff_t)psCache->nBlocksPerRow; +++ { +++ uint64_t nBytesPerRow = _TIFFMultiply64( +++ hTIFF, psCache->nBytesPerBlock, (uint64_t)psCache->nBlocksPerRow, +++ "overview cache row"); +++ if (nBytesPerRow == 0 && psCache->nBytesPerBlock != 0 && +++ psCache->nBlocksPerRow != 0) +++ { +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ +++ if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) +++ { +++ nBytesPerRow = _TIFFMultiply64( +++ hTIFF, nBytesPerRow, psCache->nSamples, "overview cache row"); +++ if (nBytesPerRow == 0 && psCache->nSamples != 0) +++ { +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ } +++ +++ nBytesPerRowSize = +++ _TIFFCastUInt64ToSSize(hTIFF, nBytesPerRow, "overview cache row"); +++ if (nBytesPerRowSize == 0 && nBytesPerRow != 0) +++ { +++ _TIFFfree(psCache); +++ return NULL; +++ } +++ +++ psCache->nBytesPerRow = (toff_t)nBytesPerRow; +++ } ++ ++ /* -------------------------------------------------------------------- */ ++ /* Allocate and initialize the data buffers. */ ++ /* -------------------------------------------------------------------- */ ++ ++- psCache->pabyRow1Blocks = ++- (unsigned char *)_TIFFmalloc((tmsize_t)psCache->nBytesPerRow); ++- psCache->pabyRow2Blocks = ++- (unsigned char *)_TIFFmalloc((tmsize_t)psCache->nBytesPerRow); +++ psCache->pabyRow1Blocks = (unsigned char *)_TIFFmalloc(nBytesPerRowSize); +++ psCache->pabyRow2Blocks = (unsigned char *)_TIFFmalloc(nBytesPerRowSize); ++ ++ if (psCache->pabyRow1Blocks == NULL || psCache->pabyRow2Blocks == NULL) ++ { ++@@ -121,8 +179,8 @@ TIFFOvrCache *TIFFCreateOvrCache(TIFF *hTIFF, toff_t nDirOffset) ++ return NULL; ++ } ++ ++- _TIFFmemset(psCache->pabyRow1Blocks, 0, (tmsize_t)psCache->nBytesPerRow); ++- _TIFFmemset(psCache->pabyRow2Blocks, 0, (tmsize_t)psCache->nBytesPerRow); +++ _TIFFmemset(psCache->pabyRow1Blocks, 0, nBytesPerRowSize); +++ _TIFFmemset(psCache->pabyRow2Blocks, 0, nBytesPerRowSize); ++ ++ psCache->nBlockOffset = 0; ++ ++@@ -159,7 +217,12 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ uint64_t n; ++ if (psCache->nBitsPerPixel == 16) ++ { ++- n = (psCache->nBytesPerBlock * psCache->nSamples) / 2; +++ n = _TIFFMultiply64(psCache->hTIFF, psCache->nBytesPerBlock, +++ psCache->nSamples, "overview swab"); +++ if (n == 0 && psCache->nBytesPerBlock != 0 && +++ psCache->nSamples != 0) +++ return; +++ n /= 2; ++ #ifdef SIZEOF_SIZE_T ++ #if SIZEOF_SIZE_T <= 4 ++ if (n > INT32_MAX) ++@@ -183,7 +246,12 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ ++ else if (psCache->nBitsPerPixel == 32) ++ { ++- n = (psCache->nBytesPerBlock * psCache->nSamples) / 4; +++ n = _TIFFMultiply64(psCache->hTIFF, psCache->nBytesPerBlock, +++ psCache->nSamples, "overview swab"); +++ if (n == 0 && psCache->nBytesPerBlock != 0 && +++ psCache->nSamples != 0) +++ return; +++ n /= 4; ++ #ifdef SIZEOF_SIZE_T ++ #if SIZEOF_SIZE_T <= 4 ++ if (n > INT32_MAX) ++@@ -207,7 +275,12 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ ++ else if (psCache->nBitsPerPixel == 64) ++ { ++- n = (psCache->nBytesPerBlock * psCache->nSamples) / 8; +++ n = _TIFFMultiply64(psCache->hTIFF, psCache->nBytesPerBlock, +++ psCache->nSamples, "overview swab"); +++ if (n == 0 && psCache->nBytesPerBlock != 0 && +++ psCache->nSamples != 0) +++ return; +++ n /= 8; ++ #ifdef SIZEOF_SIZE_T ++ #if SIZEOF_SIZE_T <= 4 ++ if (n > INT32_MAX) ++@@ -268,14 +341,20 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ } ++ else ++ { ++- nTileID = TIFFComputeStrip( ++- psCache->hTIFF, (uint32_t)iTileY * psCache->nBlockYSize, ++- (tsample_t)iSample); +++ uint64_t nTileY = _TIFFMultiply64( +++ psCache->hTIFF, (uint32_t)iTileY, psCache->nBlockYSize, +++ "overview strip offset"); +++ uint64_t nNextTileY = +++ _TIFFAdd64(psCache->hTIFF, nTileY, psCache->nBlockYSize, +++ "overview strip offset"); +++ if ((nTileY == 0 && iTileY != 0) || nNextTileY == 0 || +++ nTileY > UINT32_MAX || nTileY >= psCache->nYSize) +++ return; +++ nTileID = TIFFComputeStrip(psCache->hTIFF, (uint32_t)nTileY, +++ (tsample_t)iSample); ++ RowsInStrip = psCache->nBlockYSize; ++- if (((uint32_t)iTileY + 1) * psCache->nBlockYSize > ++- psCache->nYSize) ++- RowsInStrip = psCache->nYSize - ++- (uint32_t)iTileY * psCache->nBlockYSize; +++ if (nNextTileY > psCache->nYSize) +++ RowsInStrip = (uint32_t)(psCache->nYSize - nTileY); ++ if (TIFFWriteEncodedStrip( ++ psCache->hTIFF, nTileID, pabyData, ++ TIFFVStripSize(psCache->hTIFF, RowsInStrip)) < 0) ++@@ -302,13 +381,19 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ } ++ else ++ { ++- nTileID = TIFFComputeStrip( ++- psCache->hTIFF, (uint32_t)iTileY * psCache->nBlockYSize, 0); +++ uint64_t nTileY = _TIFFMultiply64( +++ psCache->hTIFF, (uint32_t)iTileY, psCache->nBlockYSize, +++ "overview strip offset"); +++ uint64_t nNextTileY = +++ _TIFFAdd64(psCache->hTIFF, nTileY, psCache->nBlockYSize, +++ "overview strip offset"); +++ if ((nTileY == 0 && iTileY != 0) || nNextTileY == 0 || +++ nTileY > UINT32_MAX || nTileY >= psCache->nYSize) +++ return; +++ nTileID = TIFFComputeStrip(psCache->hTIFF, (uint32_t)nTileY, 0); ++ RowsInStrip = psCache->nBlockYSize; ++- if (((uint32_t)iTileY + 1) * psCache->nBlockYSize > ++- psCache->nYSize) ++- RowsInStrip = psCache->nYSize - ++- (uint32_t)iTileY * psCache->nBlockYSize; +++ if (nNextTileY > psCache->nYSize) +++ RowsInStrip = (uint32_t)(psCache->nYSize - nTileY); ++ if (TIFFWriteEncodedStrip( ++ psCache->hTIFF, nTileID, pabyData, ++ TIFFVStripSize(psCache->hTIFF, RowsInStrip)) < 0) ++@@ -326,7 +411,13 @@ static void TIFFWriteOvrRow(TIFFOvrCache *psCache) ++ psCache->pabyRow1Blocks = psCache->pabyRow2Blocks; ++ psCache->pabyRow2Blocks = pabyData; ++ ++- _TIFFmemset(pabyData, 0, (tmsize_t)psCache->nBytesPerRow); +++ { +++ tmsize_t nBytesPerRow = _TIFFCastUInt64ToSSize( +++ psCache->hTIFF, psCache->nBytesPerRow, "overview cache row"); +++ if (nBytesPerRow == 0 && psCache->nBytesPerRow != 0) +++ return; +++ _TIFFmemset(pabyData, 0, nBytesPerRow); +++ } ++ ++ psCache->nBlockOffset++; ++ ++@@ -350,7 +441,9 @@ unsigned char *TIFFGetOvrBlock(TIFFOvrCache *psCache, int iTileX, int iTileY, ++ int iSample) ++ ++ { ++- toff_t nRowOffset; +++ uint64_t nBlockOffset; +++ uint64_t nRowOffset; +++ tmsize_t nRowOffsetSize; ++ ++ if (iTileY > psCache->nBlockOffset + 1) ++ TIFFWriteOvrRow(psCache); ++@@ -362,17 +455,66 @@ unsigned char *TIFFGetOvrBlock(TIFFOvrCache *psCache, int iTileX, int iTileY, ++ assert(iSample >= 0 && iSample < psCache->nSamples); ++ ++ if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) ++- nRowOffset = ((((toff_t)iTileX * psCache->nSamples) + (toff_t)iSample) * ++- psCache->nBytesPerBlock); +++ { +++ uint64_t nOffset = +++ _TIFFMultiply64(psCache->hTIFF, (uint32_t)iTileX, psCache->nSamples, +++ "overview block offset"); +++ if (nOffset == 0 && iTileX != 0 && psCache->nSamples != 0) +++ return NULL; +++ nOffset = _TIFFAdd64(psCache->hTIFF, nOffset, (uint32_t)iSample, +++ "overview block offset"); +++ if (nOffset == 0 && (iTileX != 0 || iSample != 0)) +++ return NULL; +++ nOffset = +++ _TIFFMultiply64(psCache->hTIFF, nOffset, psCache->nBytesPerBlock, +++ "overview block offset"); +++ if (nOffset == 0 && psCache->nBytesPerBlock != 0 && +++ (iTileX != 0 || iSample != 0)) +++ return NULL; +++ nBlockOffset = nOffset; +++ nRowOffset = nOffset; +++ } ++ else ++- nRowOffset = ++- (toff_t)iTileX * psCache->nBytesPerBlock + ++- (toff_t)((psCache->nBitsPerPixel + 7) / 8 * (uint16_t)iSample); +++ { +++ uint64_t nSampleOffset; +++ uint64_t nOffset = +++ _TIFFMultiply64(psCache->hTIFF, (uint32_t)iTileX, +++ psCache->nBytesPerBlock, "overview block offset"); +++ if (nOffset == 0 && iTileX != 0 && psCache->nBytesPerBlock != 0) +++ return NULL; +++ nBlockOffset = nOffset; +++ nSampleOffset = _TIFFMultiply64( +++ psCache->hTIFF, (uint32_t)((psCache->nBitsPerPixel + 7) / 8), +++ (uint16_t)iSample, "overview block offset"); +++ if (nSampleOffset == 0 && iSample != 0) +++ return NULL; +++ nOffset = _TIFFAdd64(psCache->hTIFF, nOffset, nSampleOffset, +++ "overview block offset"); +++ if (nOffset == 0 && (iTileX != 0 || iSample != 0)) +++ return NULL; +++ nRowOffset = nOffset; +++ } +++ +++ { +++ uint64_t nBlockEnd = +++ _TIFFAdd64(psCache->hTIFF, nBlockOffset, psCache->nBytesPerBlock, +++ "overview block offset"); +++ if ((nBlockEnd == 0 && +++ (nBlockOffset != 0 || psCache->nBytesPerBlock != 0)) || +++ nBlockEnd > psCache->nBytesPerRow || nRowOffset < nBlockOffset || +++ nRowOffset >= nBlockEnd) +++ return NULL; +++ } +++ +++ nRowOffsetSize = _TIFFCastUInt64ToSSize(psCache->hTIFF, nRowOffset, +++ "overview block offset"); +++ if (nRowOffsetSize == 0 && nRowOffset != 0) +++ return NULL; ++ ++ if (iTileY == psCache->nBlockOffset) ++- return psCache->pabyRow1Blocks + nRowOffset; +++ return psCache->pabyRow1Blocks + nRowOffsetSize; ++ else ++- return psCache->pabyRow2Blocks + nRowOffset; +++ return psCache->pabyRow2Blocks + nRowOffsetSize; ++ } ++ ++ /************************************************************************/ ++@@ -383,7 +525,8 @@ unsigned char *TIFFGetOvrBlock_Subsampled(TIFFOvrCache *psCache, int iTileX, ++ int iTileY) ++ ++ { ++- toff_t nRowOffset; +++ uint64_t nRowOffset; +++ tmsize_t nRowOffsetSize; ++ ++ if (iTileY > psCache->nBlockOffset + 1) ++ TIFFWriteOvrRow(psCache); ++@@ -394,12 +537,31 @@ unsigned char *TIFFGetOvrBlock_Subsampled(TIFFOvrCache *psCache, int iTileX, ++ iTileY < psCache->nBlockOffset + 2); ++ assert(psCache->nPlanarConfig != PLANARCONFIG_SEPARATE); ++ ++- nRowOffset = (toff_t)iTileX * psCache->nBytesPerBlock; +++ nRowOffset = +++ _TIFFMultiply64(psCache->hTIFF, (uint32_t)iTileX, +++ psCache->nBytesPerBlock, "overview block offset"); +++ if (nRowOffset == 0 && iTileX != 0) +++ return NULL; +++ +++ { +++ uint64_t nBlockEnd = +++ _TIFFAdd64(psCache->hTIFF, nRowOffset, psCache->nBytesPerBlock, +++ "overview block offset"); +++ if ((nBlockEnd == 0 && +++ (nRowOffset != 0 || psCache->nBytesPerBlock != 0)) || +++ nBlockEnd > psCache->nBytesPerRow) +++ return NULL; +++ } +++ +++ nRowOffsetSize = _TIFFCastUInt64ToSSize(psCache->hTIFF, nRowOffset, +++ "overview block offset"); +++ if (nRowOffsetSize == 0 && nRowOffset != 0) +++ return NULL; ++ ++ if (iTileY == psCache->nBlockOffset) ++- return psCache->pabyRow1Blocks + nRowOffset; +++ return psCache->pabyRow1Blocks + nRowOffsetSize; ++ else ++- return psCache->pabyRow2Blocks + nRowOffset; +++ return psCache->pabyRow2Blocks + nRowOffsetSize; ++ } ++ ++ /************************************************************************/ +diff --git a/contrib/iptcutil/iptcutil.c b/contrib/iptcutil/iptcutil.c +index 49d4fcd..a87a58e 100644 +--- a/contrib/iptcutil/iptcutil.c ++++ b/contrib/iptcutil/iptcutil.c +@@ -1,6 +1,7 @@ + #include "tif_config.h" + + #include ++#include + #include + #include + #include +@@ -242,6 +243,7 @@ int formatIPTC(FILE *ifile, FILE *ofile) + if (c & (unsigned char)0x80) + { + unsigned char buffer[4]; ++ unsigned long taglen_ul; + + for (i = 0; i < 4; i++) + { +diff --git a/contrib/iptcutil/iptcutil.c.rej b/contrib/iptcutil/iptcutil.c.rej +new file mode 100644 +index 0000000..2667596 +--- /dev/null ++++ b/contrib/iptcutil/iptcutil.c.rej +@@ -0,0 +1,33 @@ ++diff a/contrib/iptcutil/iptcutil.c b/contrib/iptcutil/iptcutil.c (rejected hunks) ++@@ -253,8 +255,16 @@ static int formatIPTC(FILE *ifile, FILE *ofile) ++ return -1; ++ buffer[i] = (unsigned char)c; ++ } ++- taglen = (((long)buffer[0]) << 24) | (((long)buffer[1]) << 16) | ++- (((long)buffer[2]) << 8) | (((long)buffer[3])); +++ taglen_ul = (((unsigned long)buffer[0]) << 24) | +++ (((unsigned long)buffer[1]) << 16) | +++ (((unsigned long)buffer[2]) << 8) | +++ ((unsigned long)buffer[3]); +++ if (taglen_ul > LONG_MAX) +++ { +++ printf("Inappropriate IPTC tag length %lu\n", taglen_ul); +++ return -1; +++ } +++ taglen = (long)taglen_ul; ++ } ++ else ++ { ++@@ -331,8 +341,10 @@ static char *super_fgets(char *b, int *blen, FILE *file) ++ if ((int)(q - b + 1) >= len) ++ { ++ ptrdiff_t tlen = q - b; ++- len <<= 1; ++- b = (char *)realloc(b, (size_t)(len + 2)); +++ if (len > (INT_MAX - 2) / 2) +++ return NULL; +++ len *= 2; +++ b = (char *)realloc(b, (size_t)len + 2); ++ if (b == NULL) ++ break; ++ q = b + tlen; +diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c +index 49855bb..bcee234 100644 +--- a/libtiff/tif_aux.c ++++ b/libtiff/tif_aux.c +@@ -56,6 +56,21 @@ uint64_t _TIFFMultiply64(TIFF *tif, uint64_t first, uint64_t 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, + const char *where) + { +@@ -81,6 +96,30 @@ tmsize_t _TIFFMultiplySSize(TIFF *tif, tmsize_t first, tmsize_t 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) + { + 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; + } + ++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, + tmsize_t elem_size, const char *what) + { +diff --git a/libtiff/tif_aux.c.rej b/libtiff/tif_aux.c.rej +new file mode 100644 +index 0000000..5a5a714 +--- /dev/null ++++ b/libtiff/tif_aux.c.rej +@@ -0,0 +1,47 @@ ++diff a/libtiff/tif_aux.c b/libtiff/tif_aux.c (rejected hunks) ++@@ -137,7 +225,7 @@ static int TIFFDefaultTransferFunction(TIFF *tif, TIFFDirectory *td) ++ if (td->td_bitspersample > 24) ++ return 0; ++ ++- n = ((tmsize_t)1) << td->td_bitspersample; +++ n = (tmsize_t)(1ULL << td->td_bitspersample); ++ nbytes = (tmsize_t)((uint64_t)n * sizeof(uint16_t)); ++ tf[0] = (uint16_t *)_TIFFmallocExt(tif, nbytes); ++ if (tf[0] == NULL) ++@@ -199,8 +287,11 @@ static int TIFFDefaultRefBlackWhite(TIFF *tif, TIFFDirectory *td) ++ for (i = 0; i < 3; i++) ++ { ++ td->td_refblackwhite[2 * i + 0] = 0; ++- td->td_refblackwhite[2 * i + 1] = ++- (float)((1UL << td->td_bitspersample) - 1); +++ if (td->td_bitspersample < 64) +++ td->td_refblackwhite[2 * i + 1] = +++ (float)((1ULL << td->td_bitspersample) - 1ULL); +++ else +++ td->td_refblackwhite[2 * i + 1] = (float)UINT64_MAX; ++ } ++ } ++ return 1; ++@@ -258,7 +349,7 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap) ++ * 65535 even if td_bitspersamle is > 16 */ ++ if (td->td_bitspersample <= 16) ++ { ++- maxsamplevalue = (uint16_t)((1 << td->td_bitspersample) - +++ maxsamplevalue = (uint16_t)((1U << td->td_bitspersample) - ++ 1); /* 2**(BitsPerSample) - 1 */ ++ } ++ else ++@@ -295,8 +386,11 @@ int TIFFVGetFieldDefaulted(TIFF *tif, uint32_t tag, va_list ap) ++ } ++ case TIFFTAG_DOTRANGE: ++ *va_arg(ap, uint16_t *) = 0; ++- *va_arg(ap, uint16_t *) = ++- (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); ++ case TIFFTAG_INKSET: ++ *va_arg(ap, uint16_t *) = INKSET_CMYK; +diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c +index 8500621..b69b788 100644 +--- a/libtiff/tif_dir.c ++++ b/libtiff/tif_dir.c +@@ -557,11 +557,17 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap) + case TIFFTAG_TRANSFERFUNCTION: + { + 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; + for (i = 0; i < v; i++) + _TIFFsetShortArrayExt(tif, &td->td_transferfunction[i], +- va_arg(ap, uint16_t *), +- 1U << td->td_bitspersample); ++ va_arg(ap, uint16_t *), count); + break; + } + case TIFFTAG_REFERENCEBLACKWHITE: +diff --git a/libtiff/tif_dir.c.rej b/libtiff/tif_dir.c.rej +new file mode 100644 +index 0000000..8f2fc5a +--- /dev/null ++++ b/libtiff/tif_dir.c.rej +@@ -0,0 +1,15 @@ ++diff a/libtiff/tif_dir.c b/libtiff/tif_dir.c (rejected hunks) ++@@ -421,7 +421,12 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap) ++ td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap); ++ break; ++ case TIFFTAG_COLORMAP: ++- v32 = (uint32_t)(1UL << 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], ++ va_arg(ap, uint16_t *), v32); ++ _TIFFsetShortArrayExt(tif, &td->td_colormap[1], +diff --git a/libtiff/tif_dirwrite.c.rej b/libtiff/tif_dirwrite.c.rej +new file mode 100644 +index 0000000..238b1de +--- /dev/null ++++ b/libtiff/tif_dirwrite.c.rej +@@ -0,0 +1,139 @@ ++diff a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c (rejected hunks) ++@@ -2161,30 +2161,45 @@ static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir, ++ { ++ static const char module[] = "TIFFWriteDirectoryTagColormap"; ++ uint32_t m; +++ uint32_t count; +++ uint64_t count64; +++ tmsize_t total_values; +++ tmsize_t plane_bytes; ++ uint16_t *n; ++ int o; +++ 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. */ ++ { ++- EvaluateIFDdatasizeWrite(tif, 3 * m, sizeof(uint16_t), ndir); +++ EvaluateIFDdatasizeWrite(tif, count, sizeof(uint16_t), ndir); ++ return 1; ++ } ++ ++- n = (uint16_t *)_TIFFmallocExt( ++- tif, (tmsize_t)(3U * (size_t)m * sizeof(uint16_t))); +++ n = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t), +++ module); ++ if (n == NULL) ++ { ++ TIFFErrorExtR(tif, module, "Out of memory"); ++ return (0); ++ } ++- _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); ++- _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); ++- _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); +++ _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], plane_bytes); +++ _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], plane_bytes); +++ _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], plane_bytes); ++ o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP, ++- 3 * m, n); +++ count, n); ++ _TIFFfreeExt(tif, n); ++ return (o); ++ } ++@@ -2194,13 +2209,27 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, ++ { ++ static const char module[] = "TIFFWriteDirectoryTagTransferfunction"; ++ uint32_t m; +++ uint32_t count; +++ uint64_t count64; +++ tmsize_t total_values; +++ tmsize_t plane_bytes; ++ uint16_t n; ++ uint16_t *o; ++ int p; ++ /* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with ++- * (1 << BitsPerSample) * uint16_t values. +++ * 2**BitsPerSample uint16_t values. ++ */ +++ 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 */ ++ n = (tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples) > 1 ? 3 : 1; ++ /* clang-format on */ ++@@ -2225,36 +2254,39 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, ++ if (n == 3) ++ { ++ if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], ++- tif->tif_dir.td_transferfunction[2], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))) && +++ tif->tif_dir.td_transferfunction[2], plane_bytes) && ++ !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], ++- tif->tif_dir.td_transferfunction[1], ++- (tmsize_t)((size_t)m * sizeof(uint16_t)))) +++ tif->tif_dir.td_transferfunction[1], plane_bytes)) ++ 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. */ ++ { ++- EvaluateIFDdatasizeWrite(tif, n * m, 2, ndir); +++ EvaluateIFDdatasizeWrite(tif, count, 2, ndir); ++ return 1; ++ } ++ ++- o = (uint16_t *)_TIFFmallocExt( ++- tif, (tmsize_t)((size_t)n * m * sizeof(uint16_t))); +++ o = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t), +++ module); ++ if (o == NULL) ++ { ++ TIFFErrorExtR(tif, module, "Out of memory"); ++ return (0); ++ } ++- _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); +++ _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0], plane_bytes); ++ if (n > 1) ++- _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); +++ _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1], plane_bytes); ++ if (n > 2) ++ _TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2], ++- (tmsize_t)((size_t)m * sizeof(uint16_t))); +++ plane_bytes); ++ p = TIFFWriteDirectoryTagCheckedShortArray( ++- tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, n * m, o); +++ tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, count, o); ++ _TIFFfreeExt(tif, o); ++ return (p); ++ } +diff --git a/libtiff/tif_print.c.rej b/libtiff/tif_print.c.rej +new file mode 100644 +index 0000000..efbe07f +--- /dev/null ++++ b/libtiff/tif_print.c.rej +@@ -0,0 +1,62 @@ ++diff a/libtiff/tif_print.c b/libtiff/tif_print.c (rejected hunks) ++@@ -561,13 +561,18 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags) ++ if (flags & TIFFPRINT_COLORMAP) ++ { ++ fprintf(fd, "\n"); ++- 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]); +++ if (td->td_bitspersample >= 64) +++ fprintf(fd, " (BitsPerSample too large to print safely)\n"); +++ else +++ { +++ 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 ++ fprintf(fd, "(present)\n"); ++@@ -591,17 +596,24 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags) ++ if (flags & TIFFPRINT_CURVES) ++ { ++ fprintf(fd, "\n"); ++- uint64_t n = 1ULL << td->td_bitspersample; ++- for (uint64_t l = 0; l < n; l++) +++ if (td->td_bitspersample >= 64) +++ fprintf(fd, " (BitsPerSample too large to print safely)\n"); +++ else ++ { ++- uint16_t i; ++- fprintf(fd, " %2" PRIu64 ": %5" PRIu16, l, ++- td->td_transferfunction[0][l]); ++- for (i = 1; ++- i < td->td_samplesperpixel - td->td_extrasamples && i < 3; ++- i++) ++- fprintf(fd, " %5" PRIu16, td->td_transferfunction[i][l]); ++- fputc('\n', fd); +++ uint64_t n = 1ULL << td->td_bitspersample; +++ for (uint64_t l = 0; l < n; l++) +++ { +++ uint16_t i; +++ fprintf(fd, " %2" PRIu64 ": %5" PRIu16, l, +++ td->td_transferfunction[0][l]); +++ for (i = 1; +++ i < td->td_samplesperpixel - td->td_extrasamples && +++ i < 3; +++ i++) +++ fprintf(fd, " %5" PRIu16, +++ td->td_transferfunction[i][l]); +++ fputc('\n', fd); +++ } ++ } ++ } ++ else +diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c +index 4fec839..59945f0 100644 +--- a/libtiff/tif_read.c ++++ b/libtiff/tif_read.c +@@ -323,8 +323,16 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample) + td->td_imagelength); + 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) + { ++ uint64_t sample_offset; ++ uint64_t strip64; + if (sample >= td->td_samplesperpixel) + { + TIFFErrorExtR(tif, tif->tif_name, +@@ -332,8 +340,18 @@ static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample) + sample, td->td_samplesperpixel); + return (0); + } +- strip = (uint32_t)sample * td->td_stripsperimage + +- row / td->td_rowsperstrip; ++ sample_offset = ++ _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 + strip = row / td->td_rowsperstrip; +diff --git a/libtiff/tif_strip.c b/libtiff/tif_strip.c +index 820a254..6544c68 100644 +--- a/libtiff/tif_strip.c ++++ b/libtiff/tif_strip.c +@@ -41,6 +41,8 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample) + strip = row / td->td_rowsperstrip; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + { ++ uint64_t sample_offset; ++ uint64_t strip64; + if (sample >= td->td_samplesperpixel) + { + TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu", +diff --git a/libtiff/tif_strip.c.rej b/libtiff/tif_strip.c.rej +new file mode 100644 +index 0000000..ba5b1c7 +--- /dev/null ++++ b/libtiff/tif_strip.c.rej +@@ -0,0 +1,21 @@ ++diff a/libtiff/tif_strip.c b/libtiff/tif_strip.c (rejected hunks) ++@@ -54,11 +56,16 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample) ++ (unsigned long)td->td_samplesperpixel); ++ return (0); ++ } ++- uint32_t sample_offset = _TIFFMultiply32( ++- tif, (uint32_t)sample, td->td_stripsperimage, "TIFFComputeStrip"); +++ sample_offset = _TIFFMultiply64(tif, sample, td->td_stripsperimage, +++ "TIFFComputeStrip"); ++ if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0) ++ return (0); ++- strip += sample_offset; +++ 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); ++ } +diff --git a/libtiff/tif_tile.c.rej b/libtiff/tif_tile.c.rej +new file mode 100644 +index 0000000..0e052dd +--- /dev/null ++++ b/libtiff/tif_tile.c.rej +@@ -0,0 +1,53 @@ ++diff a/libtiff/tif_tile.c b/libtiff/tif_tile.c (rejected hunks) ++@@ -57,16 +57,47 @@ uint32_t TIFFComputeTile(TIFF *tif, uint32_t x, uint32_t y, uint32_t z, ++ 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) ++- tile = ++- xpt_ypt_zpt * s + xpt_ypt * (z / dz) + xpt * (y / dy) + x / dx; ++- else ++- tile = xpt_ypt * (z / dz) + xpt * (y / dy) + x / dx; +++ { +++ uint64_t sample_offset; +++ if (s >= td->td_samplesperpixel) +++ { +++ 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); ++ } +diff --git a/libtiff/tif_write.c b/libtiff/tif_write.c +index 6631a78..9a82ac7 100644 +--- a/libtiff/tif_write.c ++++ b/libtiff/tif_write.c +@@ -82,8 +82,16 @@ int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample) + /* + * 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) + { ++ uint64_t sample_offset; ++ uint64_t strip64; + if (sample >= td->td_samplesperpixel) + { + 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); + 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 + strip = row / td->td_rowsperstrip; +diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h +index fbf7b07..dbb1e84 100644 +--- a/libtiff/tiffiop.h ++++ b/libtiff/tiffiop.h +@@ -430,9 +430,18 @@ extern "C" + + 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 _TIFFAdd64(TIFF *, uint64_t, uint64_t, const char *); + extern tmsize_t _TIFFMultiplySSize(TIFF *, tmsize_t, tmsize_t, + const char *); ++ extern tmsize_t _TIFFAddSSize(TIFF *, tmsize_t, tmsize_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 *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t, + const char *); +diff --git a/tools/CMakeLists.txt.rej b/tools/CMakeLists.txt.rej +new file mode 100644 +index 0000000..4cf0efb +--- /dev/null ++++ b/tools/CMakeLists.txt.rej +@@ -0,0 +1,31 @@ ++diff a/tools/CMakeLists.txt b/tools/CMakeLists.txt (rejected hunks) ++@@ -29,6 +29,11 @@ if (WIN32) ++ source_group("Resource Files" FILES tif_tools_versioninfo.rc) ++ endif () ++ +++set(TIFF_TOOLS_COMMON_SOURCES +++ tiff_tools.c +++ tiff_tools.h +++) +++ ++ ++ add_executable(fax2ps ../placeholder.h) ++ target_sources(fax2ps PRIVATE fax2ps.c ${MSVC_RESOURCE_FILE}) ++@@ -130,6 +135,17 @@ target_sources(tiffsplit PRIVATE tiffsplit.c ${MSVC_RESOURCE_FILE}) ++ set_target_properties(tiffsplit PROPERTIES LINKER_LANGUAGE CXX) ++ target_link_libraries(tiffsplit PRIVATE tiff tiff_port) ++ +++foreach(target tiff2pdf +++ tiff2ps +++ tiff2rgba +++ tiffcp +++ tiffcrop +++ tiffinfo +++ tiffset +++ tiffsplit) +++ target_sources(${target} PRIVATE ${TIFF_TOOLS_COMMON_SOURCES}) +++endforeach() +++ ++ if(NOT CMAKE_CROSSCOMPILING) ++ add_executable(tiff_mkg3states ../placeholder.h) ++ target_sources(tiff_mkg3states PRIVATE mkg3states.c ../libtiff/tif_fax3.h) +diff --git a/tools/Makefile.am.rej b/tools/Makefile.am.rej +new file mode 100644 +index 0000000..d10ff44 +--- /dev/null ++++ b/tools/Makefile.am.rej +@@ -0,0 +1,58 @@ ++diff a/tools/Makefile.am b/tools/Makefile.am (rejected hunks) ++@@ -68,6 +68,8 @@ if HAVE_RPATH ++ AM_LDFLAGS = $(LIBDIR) ++ endif ++ +++TIFF_TOOLS_COMMON = tiff_tools.c tiff_tools.h +++ ++ fax2ps_SOURCES = fax2ps.c ++ fax2ps_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++@@ -92,22 +94,22 @@ thumbnail_LDADD = $(LIBTIFF) $(LIBPORT) ++ tiff2bw_SOURCES = tiff2bw.c ++ tiff2bw_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiff2pdf_SOURCES = tiff2pdf.c +++tiff2pdf_SOURCES = tiff2pdf.c $(TIFF_TOOLS_COMMON) ++ tiff2pdf_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiff2ps_SOURCES = tiff2ps.c +++tiff2ps_SOURCES = tiff2ps.c $(TIFF_TOOLS_COMMON) ++ tiff2ps_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiff2rgba_SOURCES = tiff2rgba.c +++tiff2rgba_SOURCES = tiff2rgba.c $(TIFF_TOOLS_COMMON) ++ tiff2rgba_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++ tiffcmp_SOURCES = tiffcmp.c ++ tiffcmp_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiffcp_SOURCES = tiffcp.c +++tiffcp_SOURCES = tiffcp.c $(TIFF_TOOLS_COMMON) ++ tiffcp_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiffcrop_SOURCES = tiffcrop.c +++tiffcrop_SOURCES = tiffcrop.c $(TIFF_TOOLS_COMMON) ++ tiffcrop_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++ tiffdither_SOURCES = tiffdither.c ++@@ -116,16 +118,16 @@ tiffdither_LDADD = $(LIBTIFF) $(LIBPORT) ++ tiffdump_SOURCES = tiffdump.c ++ tiffdump_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiffinfo_SOURCES = tiffinfo.c +++tiffinfo_SOURCES = tiffinfo.c $(TIFF_TOOLS_COMMON) ++ tiffinfo_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++ tiffmedian_SOURCES = tiffmedian.c ++ tiffmedian_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiffset_SOURCES = tiffset.c +++tiffset_SOURCES = tiffset.c $(TIFF_TOOLS_COMMON) ++ tiffset_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++-tiffsplit_SOURCES = tiffsplit.c +++tiffsplit_SOURCES = tiffsplit.c $(TIFF_TOOLS_COMMON) ++ tiffsplit_LDADD = $(LIBTIFF) $(LIBPORT) ++ ++ tiffgt_SOURCES = tiffgt.c +diff --git a/tools/tiffcp.c b/tools/tiffcp.c +index 2628bdb..b5bf5a8 100644 +--- a/tools/tiffcp.c ++++ b/tools/tiffcp.c +@@ -50,7 +50,9 @@ + #include + #endif + ++#include "tiff_tools.h" + #include "tiffio.h" ++#include "tiffiop.h" + + #ifndef EXIT_SUCCESS + #define EXIT_SUCCESS 0 +@@ -107,7 +109,7 @@ static int pageInSeq = 0; + */ + static void *limitMalloc(tmsize_t s) + { +- if (maxMalloc && (s > maxMalloc)) ++ if (s < 0 || (maxMalloc && (s > maxMalloc))) + { + fprintf(stderr, + "MemoryLimitError: allocation of %" TIFF_SSIZE_FORMAT +@@ -1636,9 +1638,14 @@ DECLAREreadFunc(readSeparateStripsIntoBuffer) + { + int status = 1; + tsize_t scanlinesize = TIFFScanlineSize(in); ++ tsize_t rowstride; + tdata_t scanline; + if (!scanlinesize) + return 0; ++ rowstride = ++ _TIFFMultiplySSize(in, scanlinesize, spp, "separate row stride"); ++ if (rowstride == 0) ++ return 0; + + scanline = limitMalloc(scanlinesize); + if (!scanline) +@@ -1669,7 +1676,7 @@ DECLAREreadFunc(readSeparateStripsIntoBuffer) + while (n-- > 0) + *bp = *sbuf++, bp += spp; + } +- bufp += scanlinesize * spp; ++ bufp += rowstride; + } + } + +@@ -1697,6 +1704,11 @@ DECLAREreadFunc(readContigTilesIntoBuffer) + _TIFFmemset(tilebuf, 0, tilesize); + (void)TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw); + (void)TIFFGetField(in, TIFFTAG_TILELENGTH, &tl); ++ if (tw == 0 || tl == 0) ++ { ++ status = 0; ++ goto done; ++ } + + for (row = 0; row < imagelength; row += tl) + { +@@ -1768,6 +1780,11 @@ DECLAREreadFunc(readSeparateTilesIntoBuffer) + (void)TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw); + (void)TIFFGetField(in, TIFFTAG_TILELENGTH, &tl); + (void)TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps); ++ if (tw == 0 || tl == 0) ++ { ++ status = 0; ++ goto done; ++ } + if (bps == 0) + { + TIFFError(TIFFFileName(in), "Error, cannot read BitsPerSample"); +@@ -1783,6 +1800,24 @@ DECLAREreadFunc(readSeparateTilesIntoBuffer) + goto done; + } + bytes_per_sample = bps / 8; ++ if (spp == 0 || bytes_per_sample == 0) ++ { ++ TIFFError(TIFFFileName(in), "Error, invalid sample size"); ++ status = 0; ++ goto done; ++ } ++ { ++ uint64_t sample_stride64 = ++ _TIFFMultiply64(in, spp, bytes_per_sample, "sample stride"); ++ sample_stride = ++ _TIFFCastUInt64ToUInt32(in, sample_stride64, "sample stride"); ++ if ((sample_stride64 == 0 && spp != 0) || tilew_spp == 0 || ++ sample_stride == 0) ++ { ++ status = 0; ++ goto done; ++ } ++ } + + for (row = 0; row < imagelength; row += tl) + { +@@ -1794,6 +1829,8 @@ DECLAREreadFunc(readSeparateTilesIntoBuffer) + { + tsample_t s; + ++ if (colb >= imagew) ++ break; + for (s = 0; s < spp; s++) + { + if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0 && !ignore) +@@ -1888,6 +1925,18 @@ DECLAREwriteFunc(writeBufferToSeparateStrips) + return 0; + } + bytes_per_sample = bps / 8; ++ rowsize64 = _TIFFMultiply64(out, imagewidth, spp, "separate row stride"); ++ if (rowsize64 == 0 && imagewidth != 0 && spp != 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } ++ rowsize = _TIFFCastUInt64ToSSize(out, rowsize64, "separate row stride"); ++ if (rowsize == 0 && rowsize64 != 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } + for (s = 0; s < spp; s++) + { + uint32_t row; +@@ -1933,6 +1982,11 @@ DECLAREwriteFunc(writeBufferToContigTiles) + _TIFFmemset(obuf, 0, tilesize); + (void)TIFFGetField(out, TIFFTAG_TILELENGTH, &tl); + (void)TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw); ++ if (tw == 0 || tl == 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } + for (row = 0; row < imagelength; row += tilelength) + { + uint32_t nrow = (row + tl > imagelength) ? imagelength - row : tl; +@@ -1962,9 +2016,23 @@ DECLAREwriteFunc(writeBufferToContigTiles) + _TIFFfree(obuf); + return 0; + } ++ if (tilew > UINT32_MAX - colb) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } + colb += tilew; + } +- bufp += nrow * imagew; ++ { ++ tmsize_t row_advance = ++ _TIFFComputeRowOffset(out, imagew, nrow, "image row offset"); ++ if (row_advance == 0 && nrow != 0 && imagew != 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } ++ bufp += row_advance; ++ } + } + _TIFFfree(obuf); + return 1; +@@ -1990,6 +2058,11 @@ DECLAREwriteFunc(writeBufferToSeparateTiles) + (void)TIFFGetField(out, TIFFTAG_TILELENGTH, &tl); + (void)TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw); + (void)TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps); ++ if (tw == 0 || tl == 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } + if (bps == 0) + { + TIFFError(TIFFFileName(out), "Error, cannot read BitsPerSample"); +@@ -2045,9 +2118,23 @@ DECLAREwriteFunc(writeBufferToSeparateTiles) + return 0; + } + } ++ if (tilew > UINT32_MAX - colb) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } + colb += tilew; + } +- bufp += nrow * iimagew; ++ { ++ tmsize_t row_advance = ++ _TIFFComputeRowOffset(out, iimagew, nrow, "image row offset"); ++ if (row_advance == 0 && nrow != 0 && iimagew != 0) ++ { ++ _TIFFfree(obuf); ++ return 0; ++ } ++ bufp += row_advance; ++ } + } + _TIFFfree(obuf); + return 1; +diff --git a/tools/tiffcp.c.rej b/tools/tiffcp.c.rej +new file mode 100644 +index 0000000..02e5bcb +--- /dev/null ++++ b/tools/tiffcp.c.rej +@@ -0,0 +1,321 @@ ++diff a/tools/tiffcp.c b/tools/tiffcp.c (rejected hunks) ++@@ -226,10 +228,8 @@ int main(int argc, char *argv[]) ++ switch (c) ++ { ++ case 'm': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ break; ++ case ',': ++ if (optarg[0] != '=') ++@@ -1660,13 +1660,13 @@ static int cpImage(TIFF *in, TIFF *out, readFunc fin, writeFunc fout, ++ int status = 0; ++ tdata_t buf = NULL; ++ tsize_t scanlinesize = TIFFRasterScanlineSize(in); ++- /* ++- * XXX: Check for integer overflow. ++- */ ++- if (scanlinesize && imagelength && ++- ((TIFF_TMSIZE_T_MAX / (tmsize_t)imagelength) > scanlinesize)) +++ +++ if (scanlinesize && imagelength) ++ { ++- tsize_t bytes = scanlinesize * (tsize_t)imagelength; +++ tsize_t bytes = +++ _TIFFMultiplySSize(in, scanlinesize, imagelength, "image buffer"); +++ if (bytes == 0) +++ return 0; ++ buf = limitMalloc(bytes); ++ if (buf) ++ { ++@@ -1823,7 +1833,7 @@ DECLAREreadFunc(readContigTilesIntoBuffer) ++ status = 0; ++ goto done; ++ } ++- if (colb > iskew) +++ if (tilew > imagew - colb) ++ { ++ uint32_t width = imagew - colb; ++ int64_t oskew = (int64_t)tilew - (int64_t)width; ++@@ -1833,9 +1843,23 @@ DECLAREreadFunc(readContigTilesIntoBuffer) ++ else ++ cpStripToTile(bufp + colb, (uint8_t *)tilebuf, nrow, tilew, ++ iskew, 0); +++ if (tilew > UINT32_MAX - colb) +++ { +++ status = 0; +++ goto done; +++ } ++ colb += tilew; ++ } ++- bufp += imagew * nrow; +++ { +++ tmsize_t row_advance = +++ _TIFFComputeRowOffset(in, imagew, nrow, "image row offset"); +++ if (row_advance == 0 && nrow != 0 && imagew != 0) +++ { +++ status = 0; +++ goto done; +++ } +++ bufp += row_advance; +++ } ++ } ++ done: ++ _TIFFfree(tilebuf); ++@@ -1856,23 +1880,31 @@ DECLAREreadFunc(readSeparateTilesIntoBuffer) ++ uint32_t tw, tl; ++ uint32_t row; ++ uint16_t bps = 0, bytes_per_sample; +++ uint32_t tilew_spp; +++ uint32_t sample_stride; ++ ++- if (tilew && spp > (INT_MAX / tilew)) ++ { ++- TIFFError(TIFFFileName(in), ++- "Error, cannot handle that much samples per tile row (Tile " ++- "Width * Samples/Pixel)"); ++- return 0; +++ uint64_t tilew_spp64 = +++ _TIFFMultiply64(in, tilew, spp, "tile row stride"); +++ tilew_spp = _TIFFCastUInt64ToUInt32(in, tilew_spp64, "tile row stride"); +++ if ((tilew_spp64 == 0 && tilew != 0 && spp != 0) || +++ (tilew_spp == 0 && tilew_spp64 != 0)) +++ { +++ TIFFError(TIFFFileName(in), +++ "Error, cannot handle that much samples per tile row " +++ "(Tile Width * Samples/Pixel)"); +++ return 0; +++ } ++ } ++ ++- if ((imagew - tilew * spp) > INT_MAX) +++ if (tilew_spp > imagew || (imagew - tilew_spp) > INT_MAX) ++ { ++ TIFFError(TIFFFileName(in), ++ "Error, image raster scan line size is too large"); ++ return 0; ++ } ++ ++- iskew = (int64_t)imagew - (int64_t)tilew * (int64_t)spp; +++ iskew = (int64_t)imagew - (int64_t)tilew_spp; ++ tilebuf = limitMalloc(tilesize); ++ if (tilebuf == 0) ++ return 0; ++@@ -1922,24 +1979,67 @@ DECLAREreadFunc(readSeparateTilesIntoBuffer) ++ * Tile is clipped horizontally. Calculate ++ * visible portion and skewing factors. ++ */ ++- if (colb + tilew * spp > imagew) +++ if (tilew_spp > imagew - colb) ++ { ++ uint32_t width = imagew - colb; ++- int64_t oskew = ++- (int64_t)tilew * (int64_t)spp - (int64_t)width; +++ int64_t oskew = (int64_t)tilew_spp - (int64_t)width; +++ uint64_t sample_offset64 = _TIFFMultiply64( +++ in, s, bytes_per_sample, "sample offset"); +++ tmsize_t sample_offset = _TIFFCastUInt64ToSSize( +++ in, sample_offset64, "sample offset"); +++ tmsize_t input_offset = +++ _TIFFAddSSize(in, colb, sample_offset, "input offset"); +++ if ((sample_offset64 == 0 && s != 0) || +++ (sample_offset == 0 && sample_offset64 != 0) || +++ (input_offset == 0 && +++ (colb != 0 || sample_offset != 0))) +++ { +++ status = 0; +++ goto done; +++ } ++ cpSeparateBufToContigBuf( ++- bufp + colb + s * bytes_per_sample, (uint8_t *)tilebuf, ++- nrow, width / (uint32_t)(spp * bytes_per_sample), ++- oskew + iskew, oskew / spp, spp, bytes_per_sample); +++ bufp + input_offset, (uint8_t *)tilebuf, nrow, +++ width / sample_stride, oskew + iskew, oskew / spp, spp, +++ bytes_per_sample); ++ } ++ else ++- cpSeparateBufToContigBuf(bufp + colb + s * bytes_per_sample, +++ { +++ uint64_t sample_offset64 = _TIFFMultiply64( +++ in, s, bytes_per_sample, "sample offset"); +++ tmsize_t sample_offset = _TIFFCastUInt64ToSSize( +++ in, sample_offset64, "sample offset"); +++ tmsize_t input_offset = +++ _TIFFAddSSize(in, colb, sample_offset, "input offset"); +++ if ((sample_offset64 == 0 && s != 0) || +++ (sample_offset == 0 && sample_offset64 != 0) || +++ (input_offset == 0 && +++ (colb != 0 || sample_offset != 0))) +++ { +++ status = 0; +++ goto done; +++ } +++ cpSeparateBufToContigBuf(bufp + input_offset, ++ (uint8_t *)tilebuf, nrow, tw, ++ iskew, 0, spp, bytes_per_sample); +++ } +++ } +++ if (tilew_spp > UINT32_MAX - colb) +++ { +++ status = 0; +++ goto done; ++ } ++- colb += tilew * spp; +++ colb += tilew_spp; +++ } +++ { +++ tmsize_t row_advance = +++ _TIFFComputeRowOffset(in, imagew, nrow, "image row offset"); +++ if (row_advance == 0 && nrow != 0 && imagew != 0) +++ { +++ status = 0; +++ goto done; +++ } +++ bufp += row_advance; ++ } ++- bufp += imagew * nrow; ++ } ++ done: ++ _TIFFfree(tilebuf); ++@@ -1972,7 +2072,8 @@ DECLAREwriteFunc(writeBufferToContigStrips) ++ ++ DECLAREwriteFunc(writeBufferToSeparateStrips) ++ { ++- uint32_t rowsize = imagewidth * spp; +++ tmsize_t rowsize; +++ uint64_t rowsize64; ++ tsize_t stripsize = TIFFStripSize(out); ++ tdata_t obuf; ++ tstrip_t strip = 0; ++@@ -2010,9 +2123,30 @@ DECLAREwriteFunc(writeBufferToSeparateStrips) ++ : rowsperstrip; ++ stripsize = TIFFVStripSize(out, nrows); ++ ++- cpContigBufToSeparateBuf((uint8_t *)obuf, ++- (uint8_t *)buf + row * rowsize + s, nrows, ++- imagewidth, 0, 0, spp, bytes_per_sample); +++ { +++ tmsize_t row_offset; +++ tmsize_t in_offset; +++ if (row == 0 || rowsize == 0) +++ row_offset = 0; +++ else +++ row_offset = +++ _TIFFComputeRowOffset(out, rowsize, row, "row offset"); +++ if (row_offset == 0 && row != 0 && rowsize != 0) +++ { +++ _TIFFfree(obuf); +++ return 0; +++ } +++ in_offset = +++ _TIFFAddSSize(out, row_offset, s, "input buffer offset"); +++ if (in_offset == 0 && (row_offset != 0 || s != 0)) +++ { +++ _TIFFfree(obuf); +++ return 0; +++ } +++ cpContigBufToSeparateBuf( +++ (uint8_t *)obuf, (uint8_t *)buf + in_offset, nrows, +++ imagewidth, 0, 0, spp, bytes_per_sample); +++ } ++ if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0) ++ { ++ TIFFError(TIFFFileName(out), ++@@ -2059,7 +2198,7 @@ DECLAREwriteFunc(writeBufferToContigTiles) ++ * Tile is clipped horizontally. Calculate ++ * visible portion and skewing factors. ++ */ ++- if (colb + tilew > imagew) +++ if (tilew > imagew - colb) ++ { ++ uint32_t width = imagew - colb; ++ int64_t oskew = (int64_t)tilew - (int64_t)width; ++@@ -2093,14 +2246,20 @@ DECLAREwriteFunc(writeBufferToSeparateTiles) ++ "writeBufferToSeparateTiles"); ++ uint32_t iimagew = _TIFFCastSSizeToUInt32(TIFFRasterScanlineSize(out), ++ "writeBufferToSeparateTiles"); ++- int64_t iskew = (int64_t)iimagew - (int64_t)tilew * (int64_t)spp; +++ int64_t iskew; ++ tsize_t tilesize = TIFFTileSize(out); ++ tdata_t obuf; ++ uint8_t *bufp = (uint8_t *)buf; ++ uint32_t tl, tw; ++ uint32_t row; ++ uint16_t bps = 0, bytes_per_sample; +++ uint64_t tilew_spp64; ++ +++ tilew_spp64 = _TIFFMultiply64(out, tilew, spp, "tile row stride"); +++ if ((tilew_spp64 == 0 && tilew != 0 && spp != 0) || +++ tilew_spp64 > (uint64_t)INT64_MAX) +++ return 0; +++ iskew = (int64_t)iimagew - (int64_t)tilew_spp64; ++ obuf = limitMalloc(TIFFTileSize(out)); ++ if (obuf == NULL) ++ return 0; ++@@ -2133,26 +2297,56 @@ DECLAREwriteFunc(writeBufferToSeparateTiles) ++ for (col = 0; col < imagewidth; col += tw) ++ { ++ tsample_t s; +++ if (colb >= imagew) +++ break; ++ for (s = 0; s < spp; s++) ++ { +++ uint64_t col_offset64 = +++ _TIFFMultiply64(out, colb, spp, "input buffer offset"); +++ uint64_t input_offset64 = +++ _TIFFAdd64(out, col_offset64, s, "input buffer offset"); +++ tmsize_t input_offset = _TIFFCastUInt64ToSSize( +++ out, input_offset64, "input buffer offset"); +++ if ((col_offset64 == 0 && colb != 0 && spp != 0) || +++ (input_offset64 == 0 && (col_offset64 != 0 || s != 0)) || +++ (input_offset == 0 && input_offset64 != 0)) +++ { +++ _TIFFfree(obuf); +++ return 0; +++ } ++ /* ++ * Tile is clipped horizontally. Calculate ++ * visible portion and skewing factors. ++ */ ++- if (colb + tilew > imagew) +++ if (tilew > imagew - colb) ++ { ++ uint32_t width = (imagew - colb); ++ int64_t oskew = (int64_t)tilew - (int64_t)width; +++ uint64_t oskew_spp64 = +++ _TIFFMultiply64(out, (uint64_t)oskew, spp, "tile skew"); +++ int64_t clipped_iskew; +++ if ((oskew_spp64 == 0 && oskew != 0 && spp != 0) || +++ oskew_spp64 > (uint64_t)INT64_MAX) +++ { +++ _TIFFfree(obuf); +++ return 0; +++ } +++ if (iskew > 0 && (int64_t)oskew_spp64 > INT64_MAX - iskew) +++ { +++ _TIFFfree(obuf); +++ return 0; +++ } +++ clipped_iskew = (int64_t)oskew_spp64 + iskew; ++ ++ cpContigBufToSeparateBuf( ++- (uint8_t *)obuf, bufp + (colb * spp) + s, nrow, ++- width / bytes_per_sample, oskew, (oskew * spp) + iskew, ++- spp, bytes_per_sample); +++ (uint8_t *)obuf, bufp + input_offset, nrow, +++ width / bytes_per_sample, oskew, clipped_iskew, spp, +++ bytes_per_sample); ++ } ++ else ++ cpContigBufToSeparateBuf( ++- (uint8_t *)obuf, bufp + (colb * spp) + s, nrow, ++- tilewidth, 0, iskew, spp, bytes_per_sample); +++ (uint8_t *)obuf, bufp + input_offset, nrow, tilewidth, +++ 0, iskew, spp, bytes_per_sample); ++ if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) ++ { ++ TIFFError(TIFFFileName(out), +diff --git a/tools/tiffdump.c b/tools/tiffdump.c +index df1f935..085f53b 100644 +--- a/tools/tiffdump.c ++++ b/tools/tiffdump.c +@@ -311,6 +311,8 @@ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) + void *dirmem = NULL; + uint64_t nextdiroff = 0; + uint32_t n; ++ ssize_t nread; ++ tmsize_t dirsize; + uint8_t *dp; + + if (off == 0) /* no more directories */ +@@ -527,9 +529,20 @@ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: +- TIFFSwabArrayOfLong((uint32_t *)datamem, +- (tmsize_t)count * 2); ++ { ++ tmsize_t count_s = _TIFFCastUInt64ToSSize( ++ NULL, count, "rational word count"); ++ tmsize_t word_count = _TIFFMultiplySSize( ++ NULL, count_s, 2, "rational word count"); ++ if ((count_s == 0 && count != 0) || ++ (word_count == 0 && count_s != 0)) ++ { ++ Error("Integer overflow swabbing tag %u", tag); ++ break; ++ } ++ TIFFSwabArrayOfLong((uint32_t *)datamem, word_count); + break; ++ } + case TIFF_DOUBLE: + case TIFF_LONG8: + case TIFF_SLONG8: +diff --git a/tools/tiffdump.c.rej b/tools/tiffdump.c.rej +new file mode 100644 +index 0000000..13bbb41 +--- /dev/null ++++ b/tools/tiffdump.c.rej +@@ -0,0 +1,52 @@ ++diff a/tools/tiffdump.c b/tools/tiffdump.c (rejected hunks) ++@@ -25,7 +25,9 @@ ++ #include "libport.h" ++ #include "tif_config.h" ++ +++#include ++ #include /* for isfinite() */ +++#include ++ #include ++ #include ++ #include ++@@ -356,17 +360,35 @@ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) ++ dircount = (uint16_t)dircount64; ++ direntrysize = 20; ++ } ++- dirmem = ++- _TIFFmalloc((tmsize_t)TIFFSafeMultiply(size_t, dircount, direntrysize)); +++ dirsize = +++ _TIFFMultiplySSize(NULL, dircount, direntrysize, "directory size"); +++ if (dirsize == 0 && dircount != 0) +++ { +++ Fatal("Integer overflow reading TIFF directory"); +++ goto done; +++ } +++ +++ if (dirsize > INT_MAX) +++ { +++ Fatal("TIFF directory too large"); +++ goto done; +++ } +++ +++ dirmem = _TIFFmalloc(dirsize); ++ if (dirmem == NULL) ++ { ++ Fatal("No space for TIFF directory"); ++ goto done; ++ } ++- n = (uint32_t)read(fd, (char *)dirmem, dircount * direntrysize); ++- if (n != dircount * direntrysize) +++ +++ nread = read(fd, (char *)dirmem, (size_t)dirsize); +++ if (nread < 0 || (tmsize_t)nread != dirsize) ++ { ++- n /= direntrysize; +++ if (nread <= 0) +++ n = 0; +++ else +++ n = (uint32_t)((tmsize_t)nread / direntrysize); +++ ++ Error("Could only read %" PRIu32 " of %" PRIu16 ++ " entries in directory at offset %" PRIu64, ++ n, dircount, off); +diff --git a/tools/tiffinfo.c b/tools/tiffinfo.c +index 6e24d0f..454c6ca 100644 +--- a/tools/tiffinfo.c ++++ b/tools/tiffinfo.c +@@ -37,6 +37,7 @@ + #include + #endif + ++#include "tiff_tools.h" + #include "tiffiop.h" + + #ifndef EXIT_SUCCESS +@@ -45,7 +46,6 @@ + #ifndef EXIT_FAILURE + #define EXIT_FAILURE 1 + #endif +- + static TIFFErrorHandler old_error_handler = 0; + static int status = EXIT_SUCCESS; /* exit status */ + static int showdata = 0; /* show data */ +@@ -246,7 +246,7 @@ int main(int argc, char *argv[]) + } + } + TIFFSetDirectory(tif, curdir); +- free(subIFDoffsets); ++ _TIFFfree(subIFDoffsets); + subIFDoffsets = NULL; + } + else +@@ -339,7 +339,11 @@ void TIFFReadContigStripData(TIFF *tif) + { + uint32_t nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, 0); +- if (TIFFReadEncodedStrip(tif, strip, buf, nrow * scanline) < 0) ++ tmsize_t readsize = ++ _TIFFMultiplySSize(tif, scanline, nrow, "strip read size"); ++ if (readsize == 0) ++ break; ++ if (TIFFReadEncodedStrip(tif, strip, buf, readsize) < 0) + { + if (stoponerr) + break; +@@ -387,7 +391,11 @@ void TIFFReadSeparateStripData(TIFF *tif) + uint32_t nrow = + (row + rowsperstrip > h ? h - row : rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, s); +- if (TIFFReadEncodedStrip(tif, strip, buf, nrow * scanline) < 0) ++ tmsize_t readsize = ++ _TIFFMultiplySSize(tif, scanline, nrow, "strip read size"); ++ if (readsize == 0) ++ break; ++ if (TIFFReadEncodedStrip(tif, strip, buf, readsize) < 0) + { + if (stoponerr) + break; +@@ -591,24 +599,28 @@ static void TIFFReadRawDataStriped(TIFF *tif, int bitrev) + TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbc); + if (stripbc != NULL && nstrips > 0) + { +- uint32_t bufsize = 0; ++ tmsize_t bufsize = 0; + tdata_t buf = NULL; + tstrip_t s; + + for (s = 0; s < nstrips; s++) + { +- if (stripbc[s] > bufsize || buf == NULL) ++ tmsize_t bytecount = ++ _TIFFCastUInt64ToSSize(tif, stripbc[s], "raw strip byte count"); ++ if (bytecount == 0 && stripbc[s] != 0) ++ break; ++ if (bytecount > bufsize || buf == NULL) + { + tdata_t newbuf; +- if (maxMalloc != 0 && stripbc[s] > (uint64_t)maxMalloc) ++ if (maxMalloc != 0 && bytecount > maxMalloc) + { + fprintf(stderr, + "Memory allocation attempt %" TIFF_SSIZE_FORMAT + " over memory limit (%" TIFF_SSIZE_FORMAT ")\n", +- (tmsize_t)stripbc[s], maxMalloc); ++ bytecount, maxMalloc); + break; + } +- newbuf = _TIFFrealloc(buf, (tmsize_t)stripbc[s]); ++ newbuf = _TIFFrealloc(buf, bytecount); + if (newbuf == NULL) + { + fprintf(stderr, +@@ -617,10 +629,10 @@ static void TIFFReadRawDataStriped(TIFF *tif, int bitrev) + s); + break; + } +- bufsize = (uint32_t)stripbc[s]; ++ bufsize = bytecount; + buf = newbuf; + } +- if (TIFFReadRawStrip(tif, s, buf, (tmsize_t)stripbc[s]) < 0) ++ if (TIFFReadRawStrip(tif, s, buf, bytecount) < 0) + { + fprintf(stderr, "Error reading strip %" PRIu32 "\n", s); + if (stoponerr) +@@ -655,24 +667,28 @@ static void TIFFReadRawDataTiled(TIFF *tif, int bitrev) + TIFFGetField(tif, TIFFTAG_TILEBYTECOUNTS, &tilebc); + if (tilebc != NULL && ntiles > 0) + { +- uint64_t bufsize = 0; ++ tmsize_t bufsize = 0; + tdata_t buf = NULL; + uint32_t t; + + for (t = 0; t < ntiles; t++) + { +- if (tilebc[t] > bufsize || buf == NULL) ++ tmsize_t bytecount = ++ _TIFFCastUInt64ToSSize(tif, tilebc[t], "raw tile byte count"); ++ if (bytecount == 0 && tilebc[t] != 0) ++ break; ++ if (bytecount > bufsize || buf == NULL) + { + tdata_t newbuf; +- if (maxMalloc != 0 && tilebc[t] > (uint64_t)maxMalloc) ++ if (maxMalloc != 0 && bytecount > maxMalloc) + { + fprintf(stderr, + "Memory allocation attempt %" TIFF_SSIZE_FORMAT + " over memory limit (%" TIFF_SSIZE_FORMAT ")\n", +- (tmsize_t)tilebc[t], maxMalloc); ++ bytecount, maxMalloc); + break; + } +- newbuf = _TIFFrealloc(buf, (tmsize_t)tilebc[t]); ++ newbuf = _TIFFrealloc(buf, bytecount); + if (newbuf == NULL) + { + fprintf(stderr, +@@ -680,10 +696,10 @@ static void TIFFReadRawDataTiled(TIFF *tif, int bitrev) + t); + break; + } +- bufsize = (uint32_t)tilebc[t]; ++ bufsize = bytecount; + buf = newbuf; + } +- if (TIFFReadRawTile(tif, t, buf, (tmsize_t)tilebc[t]) < 0) ++ if (TIFFReadRawTile(tif, t, buf, bytecount) < 0) + { + fprintf(stderr, "Error reading tile %" PRIu32 "\n", t); + if (stoponerr) +@@ -702,11 +718,19 @@ static void TIFFReadRawDataTiled(TIFF *tif, int bitrev) + } + if (showwords) + { +- ShowRawWords((uint16_t *)buf, (uint32_t)(tilebc[t] >> 1)); ++ uint32_t wordcount = _TIFFCastUInt64ToUInt32( ++ tif, (uint64_t)bytecount >> 1, "raw word count"); ++ if (wordcount == 0 && bytecount > 1) ++ break; ++ ShowRawWords((uint16_t *)buf, wordcount); + } + else + { +- ShowRawBytes((unsigned char *)buf, (uint32_t)tilebc[t]); ++ uint32_t display_count = _TIFFCastUInt64ToUInt32( ++ tif, (uint64_t)bytecount, "raw byte count"); ++ if (display_count == 0 && bytecount != 0) ++ break; ++ ShowRawBytes((unsigned char *)buf, display_count); + } + } + } +diff --git a/tools/tiffinfo.c.rej b/tools/tiffinfo.c.rej +new file mode 100644 +index 0000000..488bde5 +--- /dev/null ++++ b/tools/tiffinfo.c.rej +@@ -0,0 +1,75 @@ ++diff a/tools/tiffinfo.c b/tools/tiffinfo.c (rejected hunks) ++@@ -120,10 +120,8 @@ int main(int argc, char *argv[]) ++ stoponerr = 0; ++ break; ++ case 'M': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ break; ++ case 'o': ++ v = strtol(optarg, NULL, 0); ++@@ -231,12 +229,18 @@ int main(int argc, char *argv[]) ++ { ++ if (nCount > 0) ++ { ++- subIFDoffsets = ++- (uint64_t *)malloc(nCount * sizeof(uint64_t)); +++ tmsize_t subIFDoffsets_size = _TIFFMultiplySSize( +++ tif, nCount, sizeof(uint64_t), +++ "SubIFD offsets"); +++ if (subIFDoffsets_size == 0) +++ break; +++ subIFDoffsets = (uint64_t *)_TIFFCheckMalloc( +++ tif, nCount, sizeof(uint64_t), +++ "SubIFD offsets"); ++ if (subIFDoffsets != NULL) ++ { ++ memcpy(subIFDoffsets, vPtr, ++- nCount * sizeof(subIFDoffsets[0])); +++ (size_t)subIFDoffsets_size); ++ printf("--- SubIFD image descriptor tag within " ++ "TIFF directory %u with array of %d " ++ "SubIFD chains ---\n", ++@@ -647,15 +663,27 @@ static void TIFFReadRawDataStriped(TIFF *tif, int bitrev) ++ { ++ if (bitrev) ++ { ++- TIFFReverseBits((uint8_t *)buf, (tmsize_t)stripbc[s]); +++ TIFFReverseBits((uint8_t *)buf, bytecount); ++ printf("%s %" PRIu32 ": (bit reversed)\n ", what, s); ++ } ++ else ++ printf("%s %" PRIu32 ":\n ", what, s); ++ if (showwords) ++- ShowRawWords((uint16_t *)buf, (uint32_t)stripbc[s] >> 1); +++ { +++ uint32_t wordcount = _TIFFCastUInt64ToUInt32( +++ tif, (uint64_t)bytecount >> 1, "raw word count"); +++ if (wordcount == 0 && bytecount > 1) +++ break; +++ ShowRawWords((uint16_t *)buf, wordcount); +++ } ++ else ++- ShowRawBytes((unsigned char *)buf, (uint32_t)stripbc[s]); +++ { +++ uint32_t display_count = _TIFFCastUInt64ToUInt32( +++ tif, (uint64_t)bytecount, "raw byte count"); +++ if (display_count == 0 && bytecount != 0) +++ break; +++ ShowRawBytes((unsigned char *)buf, display_count); +++ } ++ } ++ } ++ if (buf != NULL) ++@@ -710,7 +742,7 @@ static void TIFFReadRawDataTiled(TIFF *tif, int bitrev) ++ { ++ if (bitrev) ++ { ++- TIFFReverseBits((uint8_t *)buf, (tmsize_t)tilebc[t]); +++ TIFFReverseBits((uint8_t *)buf, bytecount); ++ printf("%s %" PRIu32 ": (bit reversed)\n ", what, t); ++ } ++ else +diff --git a/tools/tiffset.c b/tools/tiffset.c +index c7f9c5a..c3dac15 100644 +--- a/tools/tiffset.c ++++ b/tools/tiffset.c +@@ -33,7 +33,9 @@ + #include + #include + ++#include "tiff_tools.h" + #include "tiffio.h" ++#include "tiffiop.h" + + #ifdef NEED_LIBPORT + #include "libport.h" +@@ -119,7 +121,7 @@ static const TIFFField *GetField(TIFF *tiff, const char *tagname) + */ + static void *limitMalloc(tmsize_t s) + { +- if (maxMalloc && (s > maxMalloc)) ++ if (s < 0 || (maxMalloc && (s > maxMalloc))) + { + fprintf(stderr, + "MemoryLimitError: allocation of %" TIFF_SSIZE_FORMAT +@@ -282,7 +284,18 @@ int main(int argc, char *argv[]) + break; + } + +- array = limitMalloc((tmsize_t)wc * size); ++ { ++ tmsize_t array_size; ++ array_size = _TIFFMultiplySSize(NULL, (tmsize_t)wc, ++ size, "tag array size"); ++ if (array_size == 0) ++ { ++ fprintf(stderr, "Invalid size for %s tag\n", ++ tagname); ++ return EXIT_FAILURE; ++ } ++ array = limitMalloc(array_size); ++ } + if (!array) + { + fprintf(stderr, "No space for %s tag\n", tagname); +diff --git a/tools/tiffset.c.rej b/tools/tiffset.c.rej +new file mode 100644 +index 0000000..4b1022d +--- /dev/null ++++ b/tools/tiffset.c.rej +@@ -0,0 +1,13 @@ ++diff a/tools/tiffset.c b/tools/tiffset.c (rejected hunks) ++@@ -516,10 +529,8 @@ int main(int argc, char *argv[]) ++ else if (strcmp(argv[arg_index], "-m") == 0) ++ { ++ arg_index++; ++- long v = strtol(argv[arg_index], NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(argv[arg_index], &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ } ++ else if (strcmp(argv[arg_index], "-h") == 0 || ++ strcmp(argv[arg_index], "--help") == 0) +diff --git a/tools/tiffsplit.c b/tools/tiffsplit.c +index fcbec1d..4faa15d 100644 +--- a/tools/tiffsplit.c ++++ b/tools/tiffsplit.c +@@ -29,6 +29,7 @@ + #include + #include + ++#include "tiff_tools.h" + #include "tiffio.h" + + #ifndef EXIT_SUCCESS +diff --git a/tools/tiffsplit.c.rej b/tools/tiffsplit.c.rej +new file mode 100644 +index 0000000..4654111 +--- /dev/null ++++ b/tools/tiffsplit.c.rej +@@ -0,0 +1,28 @@ ++diff a/tools/tiffsplit.c b/tools/tiffsplit.c (rejected hunks) ++@@ -115,25 +116,14 @@ int main(int argc, char *argv[]) ++ extern int optind; ++ #endif ++ int c; ++- long v; ++ ++ while ((c = getopt(argc, argv, "M:")) != -1) ++ { ++ switch (c) ++ { ++ case 'M': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++- if ((maxMalloc == 0) && (optarg[0] != '0')) ++- { ++- fprintf(stderr, ++- "tiffsplit: Error: Option -M was not followed by a " ++- "number but <%s>\n", ++- optarg); ++- usage(EXIT_FAILURE); ++- } ++ break; ++ case '?': ++ usage(EXIT_SUCCESS); +diff --git a/tools/unsupported/tiff2pdf.c b/tools/unsupported/tiff2pdf.c +index 9ab4a9b..f75f625 100644 +--- a/tools/unsupported/tiff2pdf.c ++++ b/tools/unsupported/tiff2pdf.c +@@ -46,6 +46,7 @@ + + #include "libport.h" + #include "tif_config.h" ++#include "tiff_tools.h" + #include "tiffio.h" + #include "tiffiop.h" + +@@ -320,7 +321,7 @@ int t2p_process_ojpeg_tables(T2P *, TIFF *); + int t2p_process_jpeg_strip(unsigned char *, tsize_t *, unsigned char *, tsize_t, + tsize_t *, tstrip_t, uint32_t); + #endif +-void t2p_tile_collapse_left(tdata_t, tsize_t, uint32_t, uint32_t, uint32_t); ++int t2p_tile_collapse_left(tdata_t, tsize_t, uint32_t, uint32_t, uint32_t); + void t2p_write_advance_directory(T2P *, TIFF *); + tsize_t t2p_sample_planar_separate_to_contig(T2P *, unsigned char *, + unsigned char *, tsize_t); +@@ -476,13 +477,13 @@ static void t2p_unmapproc(thandle_t handle, void *data, toff_t offset) + #if defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) + static uint64_t checkAdd64(uint64_t summand1, uint64_t summand2, T2P *t2p) + { +- uint64_t bytes = summand1 + summand2; ++ uint64_t bytes = ++ _TIFFAdd64(NULL, summand1, summand2, "tiff2pdf size computation"); + +- if (bytes < summand1) ++ if (bytes == 0 && (summand1 != 0 || summand2 != 0)) + { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; +- bytes = 0; + } + + return bytes; +@@ -491,18 +492,90 @@ static uint64_t checkAdd64(uint64_t summand1, uint64_t summand2, T2P *t2p) + + static uint64_t checkMultiply64(uint64_t first, uint64_t second, T2P *t2p) + { +- uint64_t bytes = first * second; ++ uint64_t bytes = ++ _TIFFMultiply64(NULL, first, second, "tiff2pdf size computation"); + +- if (second && bytes / second != first) ++ if (bytes == 0 && first != 0 && second != 0) + { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; +- bytes = 0; + } + + return bytes; + } + ++static tsize_t t2p_sample_count_to_rgb_size(uint32_t samplecount, ++ const char *where) ++{ ++ uint64_t size64 = _TIFFMultiply64(NULL, samplecount, 3U, where); ++ tmsize_t size; ++ ++ if (size64 == 0 && samplecount != 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Integer overflow"); ++ return 0; ++ } ++ size = _TIFFCastUInt64ToSSize(NULL, size64, where); ++ if (size == 0 && size64 != 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Integer overflow"); ++ return 0; ++ } ++ return size; ++} ++ ++static int t2p_check_sample_byte_count(uint32_t samplecount, ++ uint32_t bytes_per_sample, ++ const char *where) ++{ ++ uint64_t size64 = ++ _TIFFMultiply64(NULL, samplecount, bytes_per_sample, where); ++ tmsize_t size; ++ ++ if (size64 == 0 && samplecount != 0 && bytes_per_sample != 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Integer overflow"); ++ return 0; ++ } ++ size = _TIFFCastUInt64ToSSize(NULL, size64, where); ++ if (size == 0 && size64 != 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Integer overflow"); ++ return 0; ++ } ++ return 1; ++} ++ ++static int t2p_transfer_function_sizes(T2P *t2p, uint32_t *entry_count, ++ tmsize_t *stream_size) ++{ ++ uint16_t bps = t2p->tiff_bitspersample; ++ uint64_t entry_count64; ++ uint64_t stream_size64; ++ ++ if (bps >= 32) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing transfer function size"); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return 0; ++ } ++ entry_count64 = 1ULL << bps; ++ stream_size64 = 1ULL << (bps + 1); ++ *entry_count = ++ _TIFFCastUInt64ToUInt32(NULL, entry_count64, "transfer function size"); ++ *stream_size = ++ _TIFFCastUInt64ToSSize(NULL, stream_size64, "transfer function size"); ++ if (*entry_count == 0 || *stream_size == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing transfer function size"); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return 0; ++ } ++ return 1; ++} ++ + /* + + This is the main function. +@@ -2860,15 +2933,31 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) + samplebufferoffset = 0; + for (j = 0; j < t2p->tiff_samplesperpixel; j++) + { ++ uint64_t sampleoffset64 = _TIFFMultiply64( ++ input, j, stripcount, "separate strip index"); ++ uint64_t stripindex64 = _TIFFAdd64(input, sampleoffset64, i, ++ "separate strip index"); ++ tstrip_t stripindex = _TIFFCastUInt64ToUInt32( ++ input, stripindex64, "separate strip index"); ++ if ((sampleoffset64 == 0 && j != 0 && stripcount != 0) || ++ (stripindex64 == 0 && ++ (sampleoffset64 != 0 || i != 0)) || ++ (stripindex == 0 && stripindex64 != 0)) ++ { ++ t2p->t2p_error = T2P_ERR_ERROR; ++ _TIFFfree(samplebuffer); ++ _TIFFfree(buffer); ++ return (0); ++ } + read = TIFFReadEncodedStrip( +- input, i + j * stripcount, ++ input, stripindex, + (tdata_t) & (samplebuffer[samplebufferoffset]), + TIFFmin(sepstripsize, stripsize - samplebufferoffset)); + if (read == -1) + { + TIFFError(TIFF2PDF_MODULE, + "Error on decoding strip %" PRIu32 " of %s", +- i + j * stripcount, TIFFFileName(input)); ++ stripindex, TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + _TIFFfree(samplebuffer); + _TIFFfree(buffer); +@@ -2981,14 +3070,27 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) + t2p->t2p_error = T2P_ERR_ERROR; + return (0); + } +- t2p->tiff_datasize = t2p_sample_abgr_to_rgb( +- (tdata_t)buffer, t2p->tiff_width * t2p->tiff_length); ++ t2p->tiff_datasize = ++ t2p_sample_abgr_to_rgb((tdata_t)buffer, samplecount); + } + + if (t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED) + { +- t2p->tiff_datasize = t2p_sample_lab_signed_to_unsigned( +- (tdata_t)buffer, t2p->tiff_width * t2p->tiff_length); ++ uint64_t samplecount64 = _TIFFMultiply64( ++ input, t2p->tiff_width, t2p->tiff_length, "sample count"); ++ uint32_t samplecount = ++ _TIFFCastUInt64ToUInt32(input, samplecount64, "sample count"); ++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing sample count for %s", ++ TIFFFileName(input)); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ _TIFFfree(buffer); ++ return (0); ++ } ++ t2p->tiff_datasize = ++ t2p_sample_lab_signed_to_unsigned((tdata_t)buffer, samplecount); + } + } + +@@ -3103,8 +3205,19 @@ dataready: + if (t2p->pdf_compression == T2P_COMPRESS_JPEG && + t2p->tiff_photometric == PHOTOMETRIC_YCBCR) + { +- bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0, buffer, +- stripsize * stripcount); ++ tmsize_t write_size = _TIFFMultiplySSize(output, stripsize, stripcount, ++ "JPEG strip buffer size"); ++ if (write_size == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing JPEG strip buffer size"); ++ if (buffer != NULL) ++ _TIFFfree(buffer); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return (0); ++ } ++ bufferoffset = ++ TIFFWriteEncodedStrip(output, (tstrip_t)0, buffer, write_size); + } + else + #endif /* ifdef JPEG_SUPPORT */ +@@ -3426,15 +3539,30 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + samplebufferoffset = 0; + for (i = 0; i < t2p->tiff_samplesperpixel; i++) + { ++ uint64_t sampleoffset64 = ++ _TIFFMultiply64(input, i, tilecount, "separate tile index"); ++ uint64_t tileindex64 = _TIFFAdd64(input, sampleoffset64, tile, ++ "separate tile index"); ++ ttile_t tileindex = _TIFFCastUInt64ToUInt32( ++ input, tileindex64, "separate tile index"); ++ if ((sampleoffset64 == 0 && i != 0 && tilecount != 0) || ++ (tileindex64 == 0 && (sampleoffset64 != 0 || tile != 0)) || ++ (tileindex == 0 && tileindex64 != 0)) ++ { ++ _TIFFfree(samplebuffer); ++ _TIFFfree(buffer); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return (0); ++ } + read = TIFFReadEncodedTile( +- input, tile + i * tilecount, ++ input, tileindex, + (tdata_t) & (samplebuffer[samplebufferoffset]), + septilesize); + if (read == -1) + { + TIFFError(TIFF2PDF_MODULE, + "Error on decoding tile %" PRIu32 " of %s", +- tile + i * tilecount, TIFFFileName(input)); ++ tileindex, TIFFFileName(input)); + _TIFFfree(samplebuffer); + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; +@@ -3504,10 +3632,23 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + + if (t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED) + { +- t2p->tiff_datasize = t2p_sample_lab_signed_to_unsigned( +- (tdata_t)buffer, +- t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth * +- t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); ++ uint64_t samplecount64 = _TIFFMultiply64( ++ input, t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, ++ t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength, ++ "tile sample count"); ++ uint32_t samplecount = _TIFFCastUInt64ToUInt32(input, samplecount64, ++ "tile sample count"); ++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing tile sample count for %s", ++ TIFFFileName(input)); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ _TIFFfree(buffer); ++ return (0); ++ } ++ t2p->tiff_datasize = ++ t2p_sample_lab_signed_to_unsigned((tdata_t)buffer, samplecount); + } + } + +@@ -3524,11 +3665,19 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + } + else + { +- t2p_tile_collapse_left( +- buffer, TIFFTileRowSize(input), +- t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, +- t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth, +- t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); ++ if (!t2p_tile_collapse_left( ++ buffer, TIFFTileRowSize(input), ++ t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, ++ t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth, ++ t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength)) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow while collapsing tile for %s", ++ TIFFFileName(input)); ++ _TIFFfree(buffer); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return (0); ++ } + } + } + +@@ -4169,13 +4318,24 @@ tsize_t t2p_sample_realize_palette(T2P *t2p, unsigned char *buffer) + { + + uint32_t sample_count = 0; ++ uint64_t sample_count64 = 0; + uint16_t component_count = 0; + uint32_t palette_offset = 0; + uint32_t sample_offset = 0; + uint32_t i = 0; + uint32_t j = 0; + size_t data_size; +- sample_count = t2p->tiff_width * t2p->tiff_length; ++ sample_count64 = _TIFFMultiply64(NULL, t2p->tiff_width, t2p->tiff_length, ++ "palette sample count"); ++ sample_count = ++ _TIFFCastUInt64ToUInt32(NULL, sample_count64, "palette sample count"); ++ if (sample_count64 == 0 || sample_count == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing palette sample count"); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return 1; ++ } + component_count = t2p->tiff_samplesperpixel; + data_size = TIFFSafeMultiply(size_t, sample_count, component_count); + if ((data_size == 0U) || (t2p->tiff_datasize < 0) || +@@ -4214,10 +4374,15 @@ tsize_t t2p_sample_realize_palette(T2P *t2p, unsigned char *buffer) + + tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32_t samplecount) + { +- uint32_t i = 0; ++ tmsize_t i = 0; ++ tmsize_t samplecount_s; + uint32_t sample = 0; + +- for (i = 0; i < samplecount; i++) ++ if (!t2p_check_sample_byte_count(samplecount, 4, "ABGR input size") || ++ !t2p_check_sample_byte_count(samplecount, 3, "ABGR sample size")) ++ return 0; ++ samplecount_s = (tmsize_t)samplecount; ++ for (i = 0; i < samplecount_s; i++) + { + sample = ((uint32_t *)data)[i]; + ((char *)data)[i * 3] = (char)(sample & 0xff); +@@ -4225,7 +4390,7 @@ tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32_t samplecount) + ((char *)data)[i * 3 + 2] = (char)((sample >> 16) & 0xff); + } + +- return (i * 3); ++ return t2p_sample_count_to_rgb_size(samplecount, "ABGR sample size"); + } + + /* +@@ -4235,18 +4400,23 @@ tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32_t samplecount) + + tsize_t t2p_sample_rgbaa_to_rgb(tdata_t data, uint32_t samplecount) + { +- uint32_t i; ++ tmsize_t i; ++ tmsize_t samplecount_s; + + /* For the 3 first samples, there is overlap between source and + * destination, so use memmove(). + * See http://bugzilla.maptools.org/show_bug.cgi?id=2577 + */ +- for (i = 0; i < 3 && i < samplecount; i++) ++ if (!t2p_check_sample_byte_count(samplecount, 4, "RGBAA input size") || ++ !t2p_check_sample_byte_count(samplecount, 3, "RGBAA sample size")) ++ return 0; ++ samplecount_s = (tmsize_t)samplecount; ++ for (i = 0; i < 3 && i < samplecount_s; i++) + memmove((uint8_t *)data + i * 3, (uint8_t *)data + i * 4, 3); +- for (; i < samplecount; i++) ++ for (; i < samplecount_s; i++) + memcpy((uint8_t *)data + i * 3, (uint8_t *)data + i * 4, 3); + +- return (i * 3); ++ return t2p_sample_count_to_rgb_size(samplecount, "RGBAA sample size"); + } + + /* +@@ -4256,11 +4426,16 @@ tsize_t t2p_sample_rgbaa_to_rgb(tdata_t data, uint32_t samplecount) + + tsize_t t2p_sample_rgba_to_rgb(tdata_t data, uint32_t samplecount) + { +- uint32_t i = 0; ++ tmsize_t i = 0; ++ tmsize_t samplecount_s; + uint32_t sample = 0; + uint8_t alpha = 0; + +- for (i = 0; i < samplecount; i++) ++ if (!t2p_check_sample_byte_count(samplecount, 4, "RGBA input size") || ++ !t2p_check_sample_byte_count(samplecount, 3, "RGBA sample size")) ++ return 0; ++ samplecount_s = (tmsize_t)samplecount; ++ for (i = 0; i < samplecount_s; i++) + { + sample = ((uint32_t *)data)[i]; + alpha = (uint8_t)((255 - ((sample >> 24) & 0xff))); +@@ -4280,9 +4455,13 @@ tsize_t t2p_sample_rgba_to_rgb(tdata_t data, uint32_t samplecount) + tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32_t samplecount) + { + +- uint32_t i = 0; ++ tmsize_t i = 0; ++ tmsize_t samplecount_s; + +- for (i = 0; i < samplecount; i++) ++ if (!t2p_check_sample_byte_count(samplecount, 3, "Lab sample size")) ++ return 0; ++ samplecount_s = (tmsize_t)samplecount; ++ for (i = 0; i < samplecount_s; i++) + { + if ((((unsigned char *)buffer)[(i * 3) + 1] & 0x80) != 0) + { +@@ -4304,7 +4483,7 @@ tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32_t samplecount) + } + } + +- return (samplecount * 3); ++ return t2p_sample_count_to_rgb_size(samplecount, "Lab sample size"); + } + + /* +@@ -5671,10 +5850,15 @@ tsize_t t2p_write_pdf_transfer_stream(T2P *t2p, TIFF *output, uint16_t i) + { + + tsize_t written = 0; ++ uint32_t entry_count; ++ tmsize_t stream_size; ++ ++ if (!t2p_transfer_function_sizes(t2p, &entry_count, &stream_size)) ++ return 0; ++ (void)entry_count; + +- written += t2p_write_pdf_stream( +- t2p->tiff_transferfunction[i], +- (((tsize_t)1) << (t2p->tiff_bitspersample + 1)), output); ++ written += t2p_write_pdf_stream(t2p->tiff_transferfunction[i], stream_size, ++ output); + + return (written); + } +diff --git a/tools/unsupported/tiff2pdf.c.rej b/tools/unsupported/tiff2pdf.c.rej +new file mode 100644 +index 0000000..117f68b +--- /dev/null ++++ b/tools/unsupported/tiff2pdf.c.rej +@@ -0,0 +1,265 @@ ++diff a/tools/unsupported/tiff2pdf.c b/tools/unsupported/tiff2pdf.c (rejected hunks) ++@@ -712,7 +785,6 @@ int main(int argc, char **argv) ++ T2P *t2p = NULL; ++ TIFF *input = NULL, *output = NULL; ++ int c, ret = EXIT_SUCCESS; ++- long v; ++ ++ t2p = t2p_init(); ++ ++@@ -729,10 +801,9 @@ int main(int argc, char **argv) ++ switch (c) ++ { ++ case 'm': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, +++ &t2p->tiff_maxdatasize)) ++ usage_info(EXIT_FAILURE); ++- t2p->tiff_maxdatasize = (tsize_t)v << 20; ++ break; ++ case 'o': ++ outfilename = optarg; ++@@ -2967,7 +3038,18 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) ++ sepstripsize = TIFFStripSize(input); ++ sepstripcount = TIFFNumberOfStrips(input); ++ ++- stripsize = sepstripsize * t2p->tiff_samplesperpixel; +++ stripsize = _TIFFMultiplySSize(input, sepstripsize, +++ t2p->tiff_samplesperpixel, +++ "separate strip buffer size"); +++ if (stripsize == 0) +++ { +++ TIFFError(TIFF2PDF_MODULE, +++ "Integer overflow computing separate strip buffer " +++ "size for %s", +++ TIFFFileName(input)); +++ t2p->t2p_error = T2P_ERR_ERROR; +++ return (0); +++ } ++ stripcount = _TIFFCastSSizeToUInt32(sepstripcount / ++ t2p->tiff_samplesperpixel, ++ "t2p_readwrite_pdf_image"); ++@@ -3093,9 +3191,11 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) ++ ++ if (t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB) ++ { +++ uint64_t samplecount64 = _TIFFMultiply64( +++ input, t2p->tiff_width, t2p->tiff_length, "sample count"); ++ uint32_t samplecount = ++- TIFFSafeMultiply(uint32_t, t2p->tiff_width, t2p->tiff_length); ++- if (samplecount == 0) +++ _TIFFCastUInt64ToUInt32(input, samplecount64, "sample count"); +++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing sample count for %s", ++@@ -3110,9 +3210,11 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) ++ ++ if (t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB) ++ { +++ uint64_t samplecount64 = _TIFFMultiply64( +++ input, t2p->tiff_width, t2p->tiff_length, "sample count"); ++ uint32_t samplecount = ++- TIFFSafeMultiply(uint32_t, t2p->tiff_width, t2p->tiff_length); ++- if (samplecount == 0) +++ _TIFFCastUInt64ToUInt32(input, samplecount64, "sample count"); +++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing sample count for %s", ++@@ -3127,15 +3229,30 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) ++ ++ if (t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB) ++ { +++ uint64_t samplecount64 = _TIFFMultiply64( +++ input, t2p->tiff_width, t2p->tiff_length, "RGBA raster size"); +++ uint64_t raster_size64; +++ uint32_t samplecount; +++ tmsize_t raster_size; ++ ++- /* Safe computation of width * height */ ++- tmsize_t raster_size = ++- TIFFSafeMultiply(tmsize_t, t2p->tiff_width, t2p->tiff_length); ++- ++- /* Safe computation of * 4 (RGBA) */ ++- raster_size = TIFFSafeMultiply(tmsize_t, raster_size, 4); +++ if (samplecount64 == 0) +++ { +++ TIFFError( +++ TIFF2PDF_MODULE, +++ "Integer overflow while allocating RGBA raster for %s", +++ TIFFFileName(input)); ++ ++- if (raster_size == 0) +++ t2p->t2p_error = T2P_ERR_ERROR; +++ _TIFFfree(buffer); +++ return (0); +++ } +++ raster_size64 = _TIFFMultiply64( +++ input, samplecount64, sizeof(uint32_t), "RGBA raster size"); +++ samplecount = +++ _TIFFCastUInt64ToUInt32(input, samplecount64, "sample count"); +++ raster_size = _TIFFCastUInt64ToSSize(input, raster_size64, +++ "RGBA raster size"); +++ if (raster_size64 == 0 || samplecount == 0 || raster_size == 0) ++ { ++ TIFFError( ++ TIFF2PDF_MODULE, ++@@ -3680,10 +3836,13 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, ++ ++ if (t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB) ++ { ++- uint32_t samplecount = TIFFSafeMultiply( ++- uint32_t, t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, ++- t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); ++- if (samplecount == 0) +++ uint64_t samplecount64 = _TIFFMultiply64( +++ input, t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, +++ t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength, +++ "tile sample count"); +++ uint32_t samplecount = _TIFFCastUInt64ToUInt32(input, samplecount64, +++ "tile sample count"); +++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing tile sample count for %s", ++@@ -3698,10 +3857,13 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, ++ ++ if (t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB) ++ { ++- uint32_t samplecount = TIFFSafeMultiply( ++- uint32_t, t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, ++- t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); ++- if (samplecount == 0) +++ uint64_t samplecount64 = _TIFFMultiply64( +++ input, t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, +++ t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength, +++ "tile sample count"); +++ uint32_t samplecount = _TIFFCastUInt64ToUInt32(input, samplecount64, +++ "tile sample count"); +++ if (samplecount64 == 0 || samplecount == 0) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Integer overflow computing tile sample count for %s", ++@@ -4330,24 +4513,45 @@ int t2p_process_jpeg_strip(unsigned char *strip, tsize_t *striplength, ++ This functions converts a tilewidth x tilelength buffer of samples into ++ an edgetilewidth x tilelength buffer of samples. ++ */ ++-void t2p_tile_collapse_left(tdata_t buffer, tsize_t scanwidth, ++- uint32_t tilewidth, uint32_t edgetilewidth, ++- uint32_t tilelength) +++int t2p_tile_collapse_left(tdata_t buffer, tsize_t scanwidth, +++ uint32_t tilewidth, uint32_t edgetilewidth, +++ uint32_t tilelength) ++ { ++ ++ uint32_t i; ++ tsize_t edgescanwidth = 0; +++ uint64_t edgebytes64; +++ uint64_t edgebytes_rounded64; ++ ++- edgescanwidth = (scanwidth * edgetilewidth + (tilewidth - 1)) / tilewidth; +++ if (scanwidth <= 0 || tilewidth == 0) +++ return 0; +++ edgebytes64 = _TIFFMultiply64(NULL, (uint64_t)scanwidth, edgetilewidth, +++ "edge tile scanline width"); +++ if (edgebytes64 == 0 && edgetilewidth != 0) +++ return 0; +++ edgebytes_rounded64 = _TIFFAdd64(NULL, edgebytes64, tilewidth - 1, +++ "edge tile scanline width"); +++ if (edgebytes_rounded64 == 0 && (edgebytes64 != 0 || tilewidth != 1)) +++ return 0; +++ edgescanwidth = _TIFFCastUInt64ToSSize( +++ NULL, edgebytes_rounded64 / tilewidth, "edge tile scanline width"); +++ if (edgescanwidth == 0 && edgebytes_rounded64 != 0) +++ return 0; ++ for (i = 0; i < tilelength; i++) ++ { +++ tmsize_t dst_offset = +++ _TIFFComputeRowOffset(NULL, edgescanwidth, i, "tile row offset"); +++ tmsize_t src_offset = +++ _TIFFComputeRowOffset(NULL, scanwidth, i, "tile row offset"); +++ if ((dst_offset == 0 && i != 0) || (src_offset == 0 && i != 0)) +++ return 0; ++ /* We use memmove() since there can be overlaps in src and dst buffers ++ * for the first items */ ++- memmove(&(((char *)buffer)[edgescanwidth * i]), ++- &(((char *)buffer)[scanwidth * i]), (size_t)edgescanwidth); +++ memmove(&(((char *)buffer)[dst_offset]), +++ &(((char *)buffer)[src_offset]), (size_t)edgescanwidth); ++ } ++ ++- return; +++ return 1; ++ } ++ ++ /* ++@@ -4417,9 +4632,24 @@ tsize_t t2p_sample_realize_palette(T2P *t2p, unsigned char *buffer) ++ ++ for (i = sample_count; i > 0; i--) ++ { +++ uint64_t palette_end; +++ uint64_t sample_offset64; ++ palette_offset = (uint32_t)(buffer[i - 1] * component_count); ++- sample_offset = (i - 1) * component_count; ++- if (palette_offset + component_count > t2p->pdf_palettesize) +++ sample_offset64 = _TIFFMultiply64(NULL, i - 1, component_count, +++ "palette sample offset"); +++ sample_offset = _TIFFCastUInt64ToUInt32(NULL, sample_offset64, +++ "palette sample offset"); +++ palette_end = +++ _TIFFAdd64(NULL, palette_offset, component_count, "palette offset"); +++ if ((sample_offset64 == 0 && i != 1) || +++ (sample_offset == 0 && sample_offset64 != 0) || palette_end == 0) +++ { +++ TIFFError(TIFF2PDF_MODULE, +++ "Integer overflow computing palette sample offset"); +++ t2p->t2p_error = T2P_ERR_ERROR; +++ return 1; +++ } +++ if (palette_end > t2p->pdf_palettesize) ++ { ++ TIFFError(TIFF2PDF_MODULE, ++ "Error: palette_offset + component_count > " ++@@ -4499,7 +4744,7 @@ tsize_t t2p_sample_rgba_to_rgb(tdata_t data, uint32_t samplecount) ++ ((uint8_t *)data)[i * 3] = (uint8_t)((sample & 0xff) + alpha); ++ } ++ ++- return (i * 3); +++ return t2p_sample_count_to_rgb_size(samplecount, "RGBA sample size"); ++ } ++ ++ /* ++@@ -5986,23 +6235,27 @@ tsize_t t2p_write_pdf_transfer_dict(T2P *t2p, TIFF *output, uint16_t i) ++ tsize_t written = 0; ++ char buffer[32]; ++ int buflen = 0; +++ uint32_t entry_count; +++ tmsize_t stream_size; ++ (void)i; /* XXX */ ++ const char mod[] = "t2p_write_pdf_transfer_dict()"; ++ +++ if (!t2p_transfer_function_sizes(t2p, &entry_count, &stream_size)) +++ return 0; +++ ++ add_t2pWriteFile_check(output, (tdata_t) "/FunctionType 0 \n", 17, mod, ++ written); ++ add_t2pWriteFile_check(output, (tdata_t) "/Domain [0.0 1.0] \n", 19, mod, ++ written); ++ add_t2pWriteFile_check(output, (tdata_t) "/Range [0.0 1.0] \n", 18, mod, ++ written); ++- buflen = snprintf(buffer, sizeof(buffer), "/Size [%" PRIu16 "] \n", ++- (uint16_t)(1u << t2p->tiff_bitspersample)); +++ buflen = +++ snprintf(buffer, sizeof(buffer), "/Size [%" PRIu32 "] \n", entry_count); ++ check_snprintf_ret(t2p, buflen, buffer); ++ add_t2pWriteFile_check(output, (tdata_t)buffer, buflen, mod, written); ++ add_t2pWriteFile_check(output, (tdata_t) "/BitsPerSample 16 \n", 19, mod, ++ written); ++- written += t2p_write_pdf_stream_dict( ++- ((tsize_t)1) << (t2p->tiff_bitspersample + 1), 0, output); +++ written += t2p_write_pdf_stream_dict(stream_size, 0, output); ++ ++ return (written); ++ } +diff --git a/tools/unsupported/tiff2ps.c b/tools/unsupported/tiff2ps.c +index d6a54b4..a6503c7 100644 +--- a/tools/unsupported/tiff2ps.c ++++ b/tools/unsupported/tiff2ps.c +@@ -2664,8 +2664,19 @@ void PSpage(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) + case PHOTOMETRIC_PALETTE: + fprintf(fd, "%s", RGBcolorimage); + PhotoshopBanner(fd, w, h, 1, 3, "false 3 colorimage"); +- fprintf(fd, "/scanLine %" TIFF_SSIZE_FORMAT " string def\n", +- ps_bytesperrow * 3); ++ { ++ tmsize_t palette_row_size = _TIFFMultiplySSize( ++ tif, ps_bytesperrow, 3, "palette row size"); ++ if (palette_row_size == 0 && ps_bytesperrow != 0) ++ { ++ TIFFError(TIFFFileName(tif), ++ "Integer overflow detected while calculating " ++ "palette row size"); ++ return; ++ } ++ fprintf(fd, "/scanLine %" TIFF_SSIZE_FORMAT " string def\n", ++ palette_row_size); ++ } + fprintf(fd, "%" PRIu32 " %" PRIu32 " 8\n", w, h); + fprintf(fd, "[%" PRIu32 " 0 0 -%" PRIu32 " 0 %" PRIu32 "]\n", w, h, + h); +@@ -3101,7 +3112,8 @@ void PSDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) + void PSRawDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) + { + uint64_t *bc; +- uint32_t bufsize; ++ uint64_t max_bytecount; ++ tmsize_t bufsize; + int breaklen = MAXLINE; + tmsize_t cc; + uint16_t fillorder; +@@ -3127,13 +3139,16 @@ void PSRawDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) + * Find largest strip: + */ + +- bufsize = (uint32_t)bc[0]; ++ max_bytecount = bc[0]; + + for (s = 0; ++s < tf_numberstrips;) + { +- if (bc[s] > bufsize) +- bufsize = (uint32_t)bc[s]; ++ if (bc[s] > max_bytecount) ++ max_bytecount = bc[s]; + } ++ bufsize = _TIFFCastUInt64ToSSize(tif, max_bytecount, "PSRawDataBW"); ++ if (bufsize == 0 && max_bytecount != 0) ++ return; + + tf_buf = (unsigned char *)limitMalloc(bufsize); + if (tf_buf == NULL) +diff --git a/tools/unsupported/tiff2ps.c.rej b/tools/unsupported/tiff2ps.c.rej +new file mode 100644 +index 0000000..9e157b0 +--- /dev/null ++++ b/tools/unsupported/tiff2ps.c.rej +@@ -0,0 +1,155 @@ ++diff a/tools/unsupported/tiff2ps.c b/tools/unsupported/tiff2ps.c (rejected hunks) ++@@ -24,6 +24,7 @@ ++ ++ #include "libport.h" ++ #include "tif_config.h" +++#include "tiff_tools.h" ++ #include "tiffiop.h" ++ ++ #include ++@@ -288,7 +289,6 @@ int main(int argc, char *argv[]) ++ extern int optind; ++ #endif ++ FILE *output = stdout; ++- long v; ++ ++ pageOrientation[0] = '\0'; ++ ++@@ -298,10 +298,8 @@ int main(int argc, char *argv[]) ++ switch (c) ++ { ++ case 'M': ++- v = strtol(optarg, NULL, 0); ++- if (v < 0) +++ if (!TIFFToolsParseMemoryLimitMiB(optarg, &maxMalloc)) ++ usage(EXIT_FAILURE); ++- maxMalloc = (tmsize_t)v << 20; ++ break; ++ case 'b': ++ bottommargin = atof(optarg); ++@@ -2623,6 +2621,7 @@ static int PS_Lvl2page(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ #if defined(EXP_ASCII85ENCODER) ++ if (ascii85_g) ++ { +++ tmsize_t ascii85_size; ++ /* ++ * Allocate a buffer to hold the ASCII85 encoded data. Note ++ * that it is allocated with sufficient room to hold the ++@@ -2632,7 +2631,22 @@ static int PS_Lvl2page(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ * 5*chunk_size/4. ++ */ ++ ++- ascii85_p = (uint8_t *)limitMalloc((chunk_size + (chunk_size / 2)) + 8); +++ ascii85_size = +++ _TIFFAddSSize(tif, chunk_size, chunk_size / 2, "ASCII85 buffer"); +++ if (ascii85_size == 0 && chunk_size != 0) +++ { +++ _TIFFfree(buf_data); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return (FALSE); +++ } +++ ascii85_size = _TIFFAddSSize(tif, ascii85_size, 8, "ASCII85 buffer"); +++ if (ascii85_size == 0) +++ { +++ _TIFFfree(buf_data); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return (FALSE); +++ } +++ ascii85_p = (uint8_t *)limitMalloc(ascii85_size); ++ ++ if (!ascii85_p) ++ { ++@@ -2785,8 +2799,27 @@ void PSpage(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ ++ if ((level2 || level3) && PS_Lvl2page(fd, tif, w, h)) ++ return; ++- ps_bytesperrow = ++- tf_bytesperrow - (uint32_t)extrasamples * bitspersample / 8 * w; +++ { +++ uint64_t extra_sample_bits = +++ _TIFFMultiply64(tif, extrasamples, bitspersample, "PS row size"); +++ uint64_t extra_sample_bytes = extra_sample_bits / 8; +++ uint64_t extra_row_bytes = +++ _TIFFMultiply64(tif, extra_sample_bytes, w, "PS row size"); +++ tmsize_t extra_row_size = +++ _TIFFCastUInt64ToSSize(tif, extra_row_bytes, "PS row size"); +++ if ((extra_sample_bits == 0 && extrasamples != 0 && +++ bitspersample != 0) || +++ (extra_row_bytes == 0 && extra_sample_bytes != 0 && w != 0) || +++ (extra_row_size == 0 && extra_row_bytes != 0) || +++ extra_row_size > tf_bytesperrow) +++ { +++ TIFFError( +++ TIFFFileName(tif), +++ "Integer overflow detected while calculating PS row size"); +++ return; +++ } +++ ps_bytesperrow = tf_bytesperrow - extra_row_size; +++ } ++ switch (photometric) ++ { ++ case PHOTOMETRIC_RGB: ++@@ -3147,6 +3191,7 @@ void PSDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ #if defined(EXP_ASCII85ENCODER) ++ if (ascii85_g) ++ { +++ tmsize_t ascii85_size; ++ /* ++ * Allocate a buffer to hold the ASCII85 encoded data. Note ++ * that it is allocated with sufficient room to hold the ++@@ -3156,7 +3201,22 @@ void PSDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ * 5*stripsize/4. ++ */ ++ ++- ascii85_p = (uint8_t *)limitMalloc((stripsize + (stripsize / 2)) + 8); +++ ascii85_size = +++ _TIFFAddSSize(tif, stripsize, stripsize / 2, "ASCII85 buffer"); +++ if (ascii85_size == 0 && stripsize != 0) +++ { +++ _TIFFfree(tf_buf); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return; +++ } +++ ascii85_size = _TIFFAddSSize(tif, ascii85_size, 8, "ASCII85 buffer"); +++ if (ascii85_size == 0) +++ { +++ _TIFFfree(tf_buf); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return; +++ } +++ ascii85_p = (uint8_t *)limitMalloc(ascii85_size); ++ ++ if (!ascii85_p) ++ { ++@@ -3314,6 +3378,7 @@ void PSRawDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ #if defined(EXP_ASCII85ENCODER) ++ if (ascii85_g) ++ { +++ tmsize_t ascii85_size; ++ /* ++ * Allocate a buffer to hold the ASCII85 encoded data. Note ++ * that it is allocated with sufficient room to hold the ++@@ -3323,7 +3388,22 @@ void PSRawDataBW(FILE *fd, TIFF *tif, uint32_t w, uint32_t h) ++ * 5*bufsize/4. ++ */ ++ ++- ascii85_p = (uint8_t *)limitMalloc((bufsize + (bufsize / 2)) + 8); +++ ascii85_size = +++ _TIFFAddSSize(tif, bufsize, bufsize / 2, "ASCII85 buffer"); +++ if (ascii85_size == 0 && bufsize != 0) +++ { +++ _TIFFfree(tf_buf); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return; +++ } +++ ascii85_size = _TIFFAddSSize(tif, ascii85_size, 8, "ASCII85 buffer"); +++ if (ascii85_size == 0) +++ { +++ _TIFFfree(tf_buf); +++ TIFFError(filename, "Cannot allocate ASCII85 encoding buffer."); +++ return; +++ } +++ ascii85_p = (uint8_t *)limitMalloc(ascii85_size); ++ ++ if (!ascii85_p) ++ { +-- +2.45.4 + diff --git a/SPECS/libtiff/libtiff.spec b/SPECS/libtiff/libtiff.spec index 1cd49be2945..b19d15b05e5 100644 --- a/SPECS/libtiff/libtiff.spec +++ b/SPECS/libtiff/libtiff.spec @@ -1,7 +1,7 @@ Summary: TIFF libraries and associated utilities. Name: libtiff Version: 4.6.0 -Release: 14%{?dist} +Release: 15%{?dist} License: libtiff Vendor: Microsoft Corporation Distribution: Azure Linux @@ -25,6 +25,7 @@ Patch13: CVE-2025-61143.patch Patch14: CVE-2025-61144.patch Patch15: CVE-2026-4775.patch Patch16: CVE-2026-12912.patch +Patch17: CVE-2026-52490.patch BuildRequires: autoconf BuildRequires: automake @@ -81,6 +82,9 @@ make %{?_smp_mflags} -k check %exclude %{_docdir}/tiff-%{version}/LICENSE.md %changelog +* Thu Aug 27 2026 Azure Linux Security Servicing Account - 4.6.0-15 +- Patch for CVE-2026-52490 + * Fri Jul 03 2026 Azure Linux Security Servicing Account - 4.6.0-14 - Patch for CVE-2026-12912