Hi! Thanks for you reply!
On 2026-10-08 14:30, Sylvain Beucler wrote: > Hi, > > On 06/10/2026 21:43, Emmanuel Arias wrote: > > Hello team, > > > > I've worked in tiff for bookworm. Please, could you review the patches? > > > > The patches are here: > > > > https://salsa.debian.org/lts-team/packages/tiff/-/tree/debian/bookworm?pow_referer=&ref_type=heads > > Please provide a proper debdiff, because reviewing each commit on Salsa is > not practical. Attaching > > (also, the Git history is weird, jumping straight from bullseye-security to > bookworm-security, but given this repo was initially from scratch, I guess > we can't do much about it.) Sorry, as I didn't find a bookworm branch in salsa, So I started from bullseye-security branch and I imported the last bookworm version in a new branch. Probably there's a better approach. > > CVE-2026-36849 is marked <ignored> in trixie, maybe check with the security > team and/or maintainer if it's a good idea to fix it. Contacted, thanks! > > What kind of testing did you do? > We have some notes from the maintainer at > https://lts-team.pages.debian.net/wiki/TestSuites/tiff.html , did you check > them? > There are many reverse dependencies for this package so thorough testing is > needed. I uploaded it to debusine [0]. But I trying to reproduce the Test Suites you mentioned. [0] https://debusine.debian.net/debian/developers/work-request/1426324/ > > Cheers! > Sylvain -- cheers, Emmanuel Arias ⢀⣴⠾⠻⢶⣦⠀ ⣾⠁⢠⠒⠀⣿⡁ [email protected] ⢿⡄⠘⠷⠚⠋⠀ OpenPGP: 13796755BBC72BB8ABE2AEB5 FA9DEC5DE11C63F1 ⠈⠳⣄
diff -Nru tiff-4.5.0/debian/changelog tiff-4.5.0/debian/changelog --- tiff-4.5.0/debian/changelog 2026-04-07 17:22:16.000000000 +0000 +++ tiff-4.5.0/debian/changelog 2026-09-22 23:02:07.000000000 +0000 @@ -1,3 +1,28 @@ +tiff (4.5.0-6+deb12u5) bookworm-security; urgency=high + + * Non-maintainer upload by the LTS Team. + * CVE-2024-13978: Affected by this vulnerability is the function + t2p_read_tiff_init of the file tools/tiff2pdf.c of the component fax2ps. + The manipulation leads to null pointer dereference. The attack needs to be + approached locally. The complexity of an attack is rather high. The + exploitation appears to be difficult. + * Address heap-based buffer overflow in pixarlog (CVE-2026-12912) + (Closes: #1141320) + - pixarlog: fix heap-buffer-overflow in 8BITABGR decode with stride 3 + - pixarlog: add comment explaining 4-byte advance in ABGR decode + - pixarlog: complete ABGR bounds check for multi-row strip decoding + - pixarlog: error out on invalid ABGR output buffer sizes + * CVE-2026-52490: Integer overflow in the tiffcrop -S subdivision count + computation, which could lead to out-of-bounds access (Closes: #1147247) + * CVE-2026-18495: fix heap-based buffer overflow caused by + truncation of 64-bit StripByteCounts values in crafted BigTIFF files. + * CVE-2026-36849: denial of service via large SamplesPerPixel tag + (Closes: #1140300). + - Add TIFFGetMaxCompressionRatio symbol. + * Enable salsa-ci. + + -- Emmanuel Arias <[email protected]> Tue, 22 Sep 2026 20:02:07 -0300 + tiff (4.5.0-6+deb12u4) bookworm-security; urgency=medium * CVE-2026-4775 (Closes: #1132632) diff -Nru tiff-4.5.0/debian/libtiff6.symbols tiff-4.5.0/debian/libtiff6.symbols --- tiff-4.5.0/debian/libtiff6.symbols 2022-12-10 09:16:36.000000000 +0000 +++ tiff-4.5.0/debian/libtiff6.symbols 2026-09-22 23:02:07.000000000 +0000 @@ -61,6 +61,7 @@ TIFFGetField@LIBTIFF_4.0 4.0.3 TIFFGetFieldDefaulted@LIBTIFF_4.0 4.0.3 TIFFGetMapFileProc@LIBTIFF_4.0 4.0.3 + TIFFGetMaxCompressionRatio@LIBTIFF_4.5 4.5.0 TIFFGetMode@LIBTIFF_4.0 4.0.3 TIFFGetReadProc@LIBTIFF_4.0 4.0.3 TIFFGetSeekProc@LIBTIFF_4.0 4.0.3 diff -Nru tiff-4.5.0/debian/patches/CVE-2024-13978.patch tiff-4.5.0/debian/patches/CVE-2024-13978.patch --- tiff-4.5.0/debian/patches/CVE-2024-13978.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/CVE-2024-13978.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,41 @@ +From: Lee Howard <[email protected]> +Date: Sat, 5 Oct 2024 09:45:30 -0700 +Subject: Check TIFFTAG_TILELENGTH and TIFFTAGTILEWIDTH for valid input, + addresses issue #650 + +Origin: backport, https://gitlab.com/libtiff/libtiff/-/commit/2ebfffb0e8836bfb1cd7d85c059cd285c59761a4 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2024-13978 +Bug-Freexian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2024-13978 +--- + tools/tiff2pdf.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c +index 1dbdc87..6feb0cd 100644 +--- a/tools/tiff2pdf.c ++++ b/tools/tiff2pdf.c +@@ -1337,8 +1337,24 @@ void t2p_read_tiff_init(T2P *t2p, TIFF *input) + t2p->pdf_xrefcount += (t2p->tiff_tiles[i].tiles_tilecount - 1) * 2; + TIFFGetField(input, TIFFTAG_TILEWIDTH, + &(t2p->tiff_tiles[i].tiles_tilewidth)); ++ if (t2p->tiff_tiles[i].tiles_tilewidth < 1) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Invalid tile width (%d), %s", ++ t2p->tiff_tiles[i].tiles_tilewidth, ++ TIFFFileName(input)); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return; ++ } + TIFFGetField(input, TIFFTAG_TILELENGTH, + &(t2p->tiff_tiles[i].tiles_tilelength)); ++ if (t2p->tiff_tiles[i].tiles_tilelength < 1) ++ { ++ TIFFError(TIFF2PDF_MODULE, "Invalid tile length (%d), %s", ++ t2p->tiff_tiles[i].tiles_tilelength, ++ TIFFFileName(input)); ++ t2p->t2p_error = T2P_ERR_ERROR; ++ return; ++ } + t2p->tiff_tiles[i].tiles_tiles = (T2P_TILE *)_TIFFmalloc( + TIFFSafeMultiply(tmsize_t, t2p->tiff_tiles[i].tiles_tilecount, + sizeof(T2P_TILE))); diff -Nru tiff-4.5.0/debian/patches/CVE-2026-18495.patch tiff-4.5.0/debian/patches/CVE-2026-18495.patch --- tiff-4.5.0/debian/patches/CVE-2026-18495.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/CVE-2026-18495.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,460 @@ +From: Su Laus <[email protected]> +Date: Tue, 3 Jun 2025 17:47:49 +0000 +Subject: [PATCH] Fixing MSVC compiler warnings in some tools. + +Origin: backport, https://gitlab.com/libtiff/libtiff/-/commit/67fd283d276f09db54dc39b9ef7b979d4b45c4b1 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-18495 +Bug-Freexian-Security: https://security.freexian.com/extended-lts/tracker/CVE-2026-18495 +--- + tools/fax2ps.c | 4 ++- + tools/raw2tiff.c | 8 +++++- + tools/tiff2pdf.c | 88 +++++++++++++++++++++++++++++++++++++++++--------------- + tools/tiff2ps.c | 9 +++--- + tools/tiffcp.c | 65 +++++++++++++++++++++++++++++++++-------- + tools/tiffdump.c | 4 +-- + 6 files changed, 135 insertions(+), 43 deletions(-) + +diff --git a/tools/fax2ps.c b/tools/fax2ps.c +index 5024541..18ff35f 100644 +--- a/tools/fax2ps.c ++++ b/tools/fax2ps.c +@@ -438,7 +438,9 @@ int main(int argc, char **argv) + } + _TIFF_lseek_f(fileno(fd), 0, SEEK_SET); + #if defined(_WIN32) && defined(USE_WIN32_FILEIO) +- tif = TIFFFdOpen(_get_osfhandle(fileno(fd)), "temp", "r"); ++ /* Avoid compiler warnings by using successive casts. */ ++ tif = TIFFFdOpen((int)(intptr_t)(HANDLE)_get_osfhandle(fileno(fd)), ++ "temp", "r"); + #else + tif = TIFFFdOpen(fileno(fd), "temp", "r"); + #endif +diff --git a/tools/raw2tiff.c b/tools/raw2tiff.c +index 0d6b0b6..71bc135 100644 +--- a/tools/raw2tiff.c ++++ b/tools/raw2tiff.c +@@ -430,7 +430,13 @@ static int guessSize(int fd, TIFFDataType dtype, _TIFF_off_t hdr_size, + return -1; + } + +- imagesize = (filestat.st_size - hdr_size) / nbands / depth; ++ if (((filestat.st_size - hdr_size) / nbands / depth) > UINT32_MAX) ++ { ++ fprintf(stderr, "Too large image size calculated.\n"); ++ return -1; ++ } ++ else ++ imagesize = (uint32_t)((filestat.st_size - hdr_size) / nbands / depth); + + if (*width != 0 && *length == 0) + { +diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c +index 6feb0cd..4352bd4 100644 +--- a/tools/tiff2pdf.c ++++ b/tools/tiff2pdf.c +@@ -281,6 +281,31 @@ typedef struct + tsize_t outputwritten; + } T2P; + ++/* This is a helper function. */ ++static uint32_t _TIFFCastSSizeToUInt32(tmsize_t val, const char *module) ++{ ++ if (val < 0) ++ { ++ TIFFError(module, "Unsigned integer underflow (negative)"); ++ return 0; ++ } ++ /* sizeof(tmsize_t) is determined by SIZEOF_SIZE_T */ ++#ifdef SIZEOF_SIZE_T ++#if SIZEOF_SIZE_T > 4 ++ if (val > UINT32_MAX) ++ { ++ TIFFError(module, "Integer overflow"); ++ return 0; ++ } ++#endif ++#else ++#pragma message( \ ++ "---- Error: SIZEOF_SIZE_T not defined. Generate a compile error. ----") ++ SIZEOF_SIZE_T ++#endif ++ return (uint32_t)val; ++} ++ + /* These functions are called by main. */ + + static void usage_info(int); +@@ -2226,7 +2251,8 @@ void t2p_read_tiff_size(T2P *t2p, TIFF *input) + "Input file %s has short JPEG " + "interchange file byte count", + TIFFFileName(input)); +- t2p->pdf_ojpegiflength = t2p->tiff_datasize; ++ t2p->pdf_ojpegiflength = _TIFFCastSSizeToUInt32( ++ t2p->tiff_datasize, "t2p_read_tiff_size"); + k = checkAdd64(k, t2p->tiff_datasize, t2p); + k = checkAdd64(k, 6, t2p); + k = checkAdd64(k, stripcount, t2p); +@@ -2499,7 +2525,7 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) + uint64_t *sbc; + unsigned char *stripbuffer; + tsize_t striplength = 0; +- uint32_t max_striplength = 0; ++ uint64_t max_striplength = 0; + #endif /* ifdef JPEG_SUPPORT */ + + /* Fail if prior error (in particular, can't trust tiff_datasize) */ +@@ -2746,7 +2772,7 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) + if (stripbuffer == NULL) + { + TIFFError(TIFF2PDF_MODULE, +- "Can't allocate %" PRId32 ++ "Can't allocate %" PRId64 + " bytes of memory for t2p_readwrite_pdf_image, %s", + max_striplength, TIFFFileName(input)); + _TIFFfree(buffer); +@@ -2831,7 +2857,9 @@ tsize_t t2p_readwrite_pdf_image(T2P *t2p, TIFF *input, TIFF *output) + sepstripcount = TIFFNumberOfStrips(input); + + stripsize = sepstripsize * t2p->tiff_samplesperpixel; +- stripcount = sepstripcount / t2p->tiff_samplesperpixel; ++ stripcount = _TIFFCastSSizeToUInt32(sepstripcount / ++ t2p->tiff_samplesperpixel, ++ "t2p_readwrite_pdf_image"); + + buffer = (unsigned char *)_TIFFmalloc(t2p->tiff_datasize); + if (buffer == NULL) +@@ -3156,7 +3184,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + #ifdef JPEG_SUPPORT + unsigned char *jpt; + float *xfloatp; +- uint32_t xuint32 = 0; ++ tmsize_t xint = 0; + #endif + + /* Fail if prior error (in particular, can't trust tiff_datasize) */ +@@ -3335,7 +3363,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + /* Store last 2 bytes of the JpegTables */ + table_end[0] = buffer[bufferoffset - 2]; + table_end[1] = buffer[bufferoffset - 1]; +- xuint32 = bufferoffset; ++ xint = bufferoffset; + bufferoffset -= 2; + retTIFFReadRawTile = TIFFReadRawTile( + input, tile, +@@ -3350,8 +3378,8 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P *t2p, TIFF *input, TIFF *output, + bufferoffset += retTIFFReadRawTile; + /* Overwrite SOI marker of image scan with previously */ + /* saved end of JpegTables */ +- buffer[xuint32 - 2] = table_end[0]; +- buffer[xuint32 - 1] = table_end[1]; ++ buffer[xint - 2] = table_end[0]; ++ buffer[xint - 1] = table_end[1]; + } + } + t2pWriteFile(output, (tdata_t)buffer, bufferoffset); +@@ -6151,17 +6179,20 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + t2p->pdf_info = 2; + t2p->pdf_pages = 3; + written += t2p_write_pdf_header(t2p, output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + t2p->pdf_catalog = t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_catalog(t2p, output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + t2p->pdf_info = t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_info(t2p, input, output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + t2p->pdf_pages = t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_pages(t2p, output); +@@ -6174,11 +6205,13 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + { + return (0); + } +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_page(t2p->pdf_xrefcount, t2p, output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount + 1, output); +@@ -6189,19 +6222,22 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + streamlen = written - streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); + if (t2p->tiff_transferfunctioncount != 0) + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_transfer(t2p, output); + written += t2p_write_pdf_obj_end(output); + for (i = 0; i < t2p->tiff_transferfunctioncount; i++) + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_transfer_dict(t2p, output, i); +@@ -6216,7 +6252,8 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + } + if ((t2p->pdf_colorspace & T2P_CS_PALETTE) != 0) + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + t2p->pdf_palettecs = t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); +@@ -6232,7 +6269,8 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + } + if ((t2p->pdf_colorspace & T2P_CS_ICCBASED) != 0) + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + t2p->pdf_icccs = t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); +@@ -6250,7 +6288,8 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + for (i2 = 0; i2 < t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount; + i2++) + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += +@@ -6280,7 +6319,8 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + streamlen = written - streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); +@@ -6288,7 +6328,8 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + } + else + { +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_xobject_stream_dict(0, t2p, output); +@@ -6317,13 +6358,14 @@ tsize_t t2p_write_pdf(T2P *t2p, TIFF *input, TIFF *output) + streamlen = written - streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); +- t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = written; ++ t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++] = ++ _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); + } + } +- t2p->pdf_startxref = written; ++ t2p->pdf_startxref = _TIFFCastSSizeToUInt32(written, "t2p_write_pdf"); + written += t2p_write_pdf_xreftable(t2p, output); + written += t2p_write_pdf_trailer(t2p, output); + t2p_disable(output); +diff --git a/tools/tiff2ps.c b/tools/tiff2ps.c +index 541495d..6b56aa8 100644 +--- a/tools/tiff2ps.c ++++ b/tools/tiff2ps.c +@@ -675,10 +675,12 @@ static const char RGBcolorimage[] = "\ + * + * It is claimed to be part of some future revision of the EPS spec. + */ +-static void PhotoshopBanner(FILE *fd, uint32_t w, uint32_t h, int bs, int nc, +- const char *startline) ++static void PhotoshopBanner(FILE *fd, uint32_t w, uint32_t h, tmsize_t bs, ++ int nc, const char *startline) + { +- fprintf(fd, "%%ImageData: %" PRIu32 " %" PRIu32 " %" PRIu16 " %d 0 %d 2 \"", ++ fprintf(fd, ++ "%%ImageData: %" PRIu32 " %" PRIu32 " %" PRIu16 ++ " %d 0 %" TIFF_SSIZE_FORMAT " 2 \"", + w, h, bitspersample, nc, bs); + fprintf(fd, startline, nc); + fprintf(fd, "\"\n"); +@@ -2694,7 +2696,6 @@ void PSColorContigPreamble(FILE *fd, uint32_t w, uint32_t h, int nc) + void PSColorSeparatePreamble(FILE *fd, uint32_t w, uint32_t h, int nc) + { + int i; +- + PhotoshopBanner(fd, w, h, ps_bytesperrow, nc, "true %d colorimage"); + for (i = 0; i < nc; i++) + fprintf(fd, "/line%d %" TIFF_SSIZE_FORMAT " string def\n", i, +diff --git a/tools/tiffcp.c b/tools/tiffcp.c +index 80b3982..0baf3a6 100644 +--- a/tools/tiffcp.c ++++ b/tools/tiffcp.c +@@ -1077,7 +1077,7 @@ static int tiffcp(TIFF *in, TIFF *out) + TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks); + if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) + { +- int inknameslen = strlen(inknames) + 1; ++ size_t inknameslen = strlen(inknames) + 1; + const char *cp = inknames; + while (ninks > 1) + { +@@ -1086,7 +1086,14 @@ static int tiffcp(TIFF *in, TIFF *out) + inknameslen += (strlen(cp) + 1); + ninks--; + } +- TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames); ++ if (inknameslen <= INT_MAX) ++ TIFFSetField(out, TIFFTAG_INKNAMES, (int)inknameslen, ++ inknames); ++ else ++ TIFFError(TIFFFileName(in), ++ "Error, length of inknames= %" PRIu64 ++ " exceeds size of int ", ++ (uint64_t)inknameslen); + } + } + } +@@ -1519,7 +1526,7 @@ bad: + } + + static void cpStripToTile(uint8_t *out, uint8_t *in, uint32_t rows, +- uint32_t cols, int outskew, int64_t inskew) ++ uint32_t cols, int64_t outskew, int64_t inskew) + { + while (rows-- > 0) + { +@@ -1680,13 +1687,40 @@ done: + return status; + } + ++/* This is a helper function. */ ++static uint32_t _TIFFCastSSizeToUInt32(tmsize_t val, const char *module) ++{ ++ if (val < 0) ++ { ++ TIFFError(module, "Unsigned integer underflow (negative)"); ++ return 0; ++ } ++ /* sizeof(tmsize_t) is determined by SIZEOF_SIZE_T */ ++#ifdef SIZEOF_SIZE_T ++#if SIZEOF_SIZE_T > 4 ++ if (val > UINT32_MAX) ++ { ++ TIFFError(module, "Integer overflow"); ++ return 0; ++ } ++#endif ++#else ++#pragma message( \ ++ "---- Error: SIZEOF_SIZE_T not defined. Generate a compile error. ----") ++ SIZEOF_SIZE_T ++#endif ++ return (uint32_t)val; ++} ++ + DECLAREreadFunc(readContigTilesIntoBuffer) + { + int status = 1; + tsize_t tilesize = TIFFTileSize(in); + tdata_t tilebuf; +- uint32_t imagew = TIFFScanlineSize(in); +- uint32_t tilew = TIFFTileRowSize(in); ++ uint32_t imagew = _TIFFCastSSizeToUInt32(TIFFScanlineSize(in), ++ "readContigTilesIntoBuffer"); ++ uint32_t tilew = _TIFFCastSSizeToUInt32(TIFFTileRowSize(in), ++ "readContigTilesIntoBuffer"); + int64_t iskew = (int64_t)imagew - (int64_t)tilew; + uint8_t *bufp = (uint8_t *)buf; + uint32_t tw, tl; +@@ -1737,8 +1771,10 @@ done: + DECLAREreadFunc(readSeparateTilesIntoBuffer) + { + int status = 1; +- uint32_t imagew = TIFFRasterScanlineSize(in); +- uint32_t tilew = TIFFTileRowSize(in); ++ uint32_t imagew = _TIFFCastSSizeToUInt32(TIFFRasterScanlineSize(in), ++ "readSeparateTilesIntoBuffer"); ++ uint32_t tilew = _TIFFCastSSizeToUInt32(TIFFTileRowSize(in), ++ "readSeparateTilesIntoBuffer"); + int iskew; + tsize_t tilesize = TIFFTileSize(in); + tdata_t tilebuf; +@@ -1917,8 +1953,10 @@ DECLAREwriteFunc(writeBufferToSeparateStrips) + + DECLAREwriteFunc(writeBufferToContigTiles) + { +- uint32_t imagew = TIFFScanlineSize(out); +- uint32_t tilew = TIFFTileRowSize(out); ++ uint32_t imagew = _TIFFCastSSizeToUInt32(TIFFScanlineSize(out), ++ "writeBufferToContigTiles"); ++ uint32_t tilew = _TIFFCastSSizeToUInt32(TIFFTileRowSize(out), ++ "writeBufferToContigTiles"); + int iskew = imagew - tilew; + tsize_t tilesize = TIFFTileSize(out); + tdata_t obuf; +@@ -1973,9 +2011,12 @@ DECLAREwriteFunc(writeBufferToContigTiles) + + DECLAREwriteFunc(writeBufferToSeparateTiles) + { +- uint32_t imagew = TIFFScanlineSize(out); +- tsize_t tilew = TIFFTileRowSize(out); +- uint32_t iimagew = TIFFRasterScanlineSize(out); ++ uint32_t imagew = _TIFFCastSSizeToUInt32(TIFFScanlineSize(out), ++ "writeBufferToSeparateTiles"); ++ uint32_t tilew = _TIFFCastSSizeToUInt32(TIFFTileRowSize(out), ++ "writeBufferToSeparateTiles"); ++ uint32_t iimagew = _TIFFCastSSizeToUInt32(TIFFRasterScanlineSize(out), ++ "writeBufferToSeparateTiles"); + int iskew = iimagew - tilew * spp; + tsize_t tilesize = TIFFTileSize(out); + tdata_t obuf; +diff --git a/tools/tiffdump.c b/tools/tiffdump.c +index df1f935..d5f58f5 100644 +--- a/tools/tiffdump.c ++++ b/tools/tiffdump.c +@@ -481,7 +481,7 @@ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) + } + if (!datafits) + { +- datamem = _TIFFmalloc(datasize); ++ datamem = _TIFFmalloc((tmsize_t)datasize); + if (datamem) + { + if (_TIFF_lseek_f(fd, (_TIFF_off_t)dataoffset, 0) != +@@ -491,7 +491,7 @@ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) + _TIFFfree(datamem); + datamem = NULL; + } +- else if (read(fd, datamem, (size_t)datasize) != ++ else if (read(fd, datamem, (unsigned int)datasize) != + (tmsize_t)datasize) + { + Error("Read error accessing tag %u value", tag); diff -Nru tiff-4.5.0/debian/patches/CVE-2026-36849.patch tiff-4.5.0/debian/patches/CVE-2026-36849.patch --- tiff-4.5.0/debian/patches/CVE-2026-36849.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/CVE-2026-36849.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,645 @@ +From: Even Rouault <[email protected]> +Date: Tue, 21 Apr 2026 19:52:02 +0200 +Subject: Add TIFFGetMaxCompressionRatio() and use it in + _TIFFReadEncoded[Tile|Strip)AndAllocBuffer() + +```rst + +.. c:function:: uint64_t TIFFGetMaxCompressionRatio(TIFF *tif); + +Description +----------- + +:c:func:`TIFFGetMaxCompressionRatio` returns the maximum compression ratio +for the current codec, which is typically achieved for a uncompressed buffer +with all bytes at zero. + +This function can be used to determine if the compressed size of a strip or tile +is realistic compared to the expected uncompressed size, to prevent some +denial-of-service scenarios. + +Depending on the codec, it may take into account the strip or tile size, +number of samples per pixel, etc. + +Some codecs don't implement that method, or only for a subset of configurations, +and may return 0 when the maximum compression ratio is unknown. + +Return values +------------- + +0 is returned if no maximum compression ratio is known. +1 is returned when there is no compression. +Values strictly bigger than 1 are returned when a maximum compression ratio is +known. +``` + +Fixes #781 + +Origin: backport, https://gitlab.com/libtiff/libtiff/-/commit/eedba405d3695b52faae65994c5904f228eca0bf +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-36849 +Bug-Freexian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2026-36849 +--- + doc/Makefile.am | 1 + + doc/conf.py | 1 + + doc/functions/TIFFGetMaxCompressionRatio.rst | 40 ++++++++++++++++++++++++++++ + doc/functions/libtiff.rst | 2 ++ + libtiff/libtiff.def | 1 + + libtiff/libtiff.map | 1 + + libtiff/tif_compress.c | 22 +++++++++++++++ + libtiff/tif_fax3.c | 34 +++++++++++++++++++++++ + libtiff/tif_jpeg.c | 25 +++++++++++++++++ + libtiff/tif_lerc.c | 11 ++++++++ + libtiff/tif_lzma.c | 13 +++++++++ + libtiff/tif_lzw.c | 12 +++++++++ + libtiff/tif_packbits.c | 7 +++++ + libtiff/tif_pixarlog.c | 11 ++++++++ + libtiff/tif_read.c | 38 +++++++++++++++++--------- + libtiff/tif_webp.c | 9 +++++++ + libtiff/tif_zip.c | 8 ++++++ + libtiff/tiffio.h | 1 + + libtiff/tiffiop.h | 5 +++- + 19 files changed, 228 insertions(+), 14 deletions(-) + create mode 100644 doc/functions/TIFFGetMaxCompressionRatio.rst + +diff --git a/doc/Makefile.am b/doc/Makefile.am +index 1449cec..44e8256 100644 +--- a/doc/Makefile.am ++++ b/doc/Makefile.am +@@ -256,6 +256,7 @@ rst_sources = \ + functions/TIFFReadFromUserBuffer.rst \ + functions/TIFFSetTagExtender.rst \ + functions/TIFFStrileQuery.rst \ ++ functions/TIFFGetMaxCompressionRatio.rst \ + libtiff.rst \ + images.rst + +diff --git a/doc/conf.py b/doc/conf.py +index 1039ff9..8687f8e 100644 +--- a/doc/conf.py ++++ b/doc/conf.py +@@ -137,6 +137,7 @@ man_pages = [ + ('functions/TIFFFieldWriteCount', 'TIFFFieldWriteCount', 'get number of values to be written to field', author, '3tiff'), + ('functions/TIFFFlush', 'TIFFFlush', 'flush pending writes to an open TIFF file', author, '3tiff'), + ('functions/TIFFGetField', 'TIFFGetField', 'get the value(s) of a tag in an open TIFF file', author, '3tiff'), ++ ('functions/TIFFGetMaxCompressionRatio', 'TIFFGetMaxCompressionRatio', 'return maximum compression ratio for current codec', author, '3tiff'), + ('functions/TIFFmemory', 'TIFFmemory', 'memory management-related functions for use with TIFF files', author, '3tiff'), + ('functions/TIFFMergeFieldInfo', 'TIFFMergeFieldInfo', 'add application-defined TIFF tags to the list of known libtiff tags', author, '3tiff'), + ('functions/TIFFOpen', 'TIFFOpen', 'open a TIFF file for reading or writing', author, '3tiff'), +diff --git a/doc/functions/TIFFGetMaxCompressionRatio.rst b/doc/functions/TIFFGetMaxCompressionRatio.rst +new file mode 100644 +index 0000000..274788c +--- /dev/null ++++ b/doc/functions/TIFFGetMaxCompressionRatio.rst +@@ -0,0 +1,40 @@ ++TIFFGetMaxCompressionRatio ++========================== ++ ++.. versionadded:: 4.7.2 ++ ++Synopsis ++-------- ++ ++.. highlight:: c ++ ++:: ++ ++ #include <tiffio.h> ++ ++.. c:function:: uint64_t TIFFGetMaxCompressionRatio(TIFF *tif); ++ ++Description ++----------- ++ ++:c:func:`TIFFGetMaxCompressionRatio` returns the maximum compression ratio ++for the current codec, which is typically achieved for a uncompressed buffer ++with all bytes at zero. ++ ++This function can be used to determine if the compressed size of a strip or tile ++is realistic compared to the expected uncompressed size, to prevent some ++denial-of-service scenarios. ++ ++Depending on the codec, it may take into account the strip or tile size, ++number of samples per pixel, etc. ++ ++Some codecs don't implement that method, or only for a subset of configurations, ++and may return 0 when the maximum compression ratio is unknown. ++ ++Return values ++------------- ++ ++0 is returned if no maximum compression ratio is known. ++1 is returned when there is no compression. ++Values strictly bigger than 1 are returned when a maximum compression ratio is ++known. +diff --git a/doc/functions/libtiff.rst b/doc/functions/libtiff.rst +index b4ad327..1bde2fc 100644 +--- a/doc/functions/libtiff.rst ++++ b/doc/functions/libtiff.rst +@@ -257,6 +257,8 @@ will work. + * - :c:func:`TIFFGetFieldDefaulted` + - return tag value in current directory with default value set if the + value is not already set and a default is defined ++ * - :c:func:`TIFFGetMaxCompressionRatio` ++ - return maximum compression ratio for current codec + * - :c:func:`TIFFGetMapFileProc` + - returns a pointer to memory mapping method + * - :c:func:`TIFFGetMode` +diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def +index 22cbb1a..5bb84ab 100644 +--- a/libtiff/libtiff.def ++++ b/libtiff/libtiff.def +@@ -54,6 +54,7 @@ EXPORTS TIFFAccessTagMethods + TIFFGetField + TIFFGetFieldDefaulted + TIFFGetMapFileProc ++ TIFFGetMaxCompressionRatio + TIFFGetMode + TIFFGetReadProc + TIFFGetSeekProc +diff --git a/libtiff/libtiff.map b/libtiff/libtiff.map +index 05da6d7..402c6b0 100644 +--- a/libtiff/libtiff.map ++++ b/libtiff/libtiff.map +@@ -213,4 +213,5 @@ LIBTIFF_4.5 { + TIFFOpenOptionsSetMaxSingleMemAlloc; + TIFFOpenOptionsSetErrorHandlerExtR; + TIFFOpenOptionsSetWarningHandlerExtR; ++ TIFFGetMaxCompressionRatio; + } LIBTIFF_4.4; +diff --git a/libtiff/tif_compress.c b/libtiff/tif_compress.c +index c6e17d3..6d79bf7 100644 +--- a/libtiff/tif_compress.c ++++ b/libtiff/tif_compress.c +@@ -139,6 +139,18 @@ static int _TIFFtrue(TIFF *tif) + } + static void _TIFFvoid(TIFF *tif) { (void)tif; } + ++static uint64_t _TIFFDefaultGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ return 0; /* unknown */ ++} ++ ++static uint64_t _TIFFGetMaxCompressionRatioOne(TIFF *tif) ++{ ++ (void)tif; ++ return 1; /* no compression */ ++} ++ + void _TIFFSetDefaultCompressionState(TIFF *tif) + { + tif->tif_fixuptags = _TIFFNoFixupTags; +@@ -160,6 +172,7 @@ void _TIFFSetDefaultCompressionState(TIFF *tif) + tif->tif_cleanup = _TIFFvoid; + tif->tif_defstripsize = _TIFFDefaultStripSize; + tif->tif_deftilesize = _TIFFDefaultTileSize; ++ tif->tif_getmaxcompressionratio = _TIFFDefaultGetMaxCompressionRatio; + tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW); + } + +@@ -168,6 +181,8 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme) + const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme); + + _TIFFSetDefaultCompressionState(tif); ++ if (scheme == COMPRESSION_NONE) ++ tif->tif_getmaxcompressionratio = _TIFFGetMaxCompressionRatioOne; + /* + * Don't treat an unknown compression scheme as an error. + * This permits applications to open files with data that +@@ -177,6 +192,13 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme) + return (c ? (*c->init)(tif, scheme) : 1); + } + ++uint64_t TIFFGetMaxCompressionRatio(TIFF *tif) ++{ ++ if (tif->tif_getmaxcompressionratio) ++ return tif->tif_getmaxcompressionratio(tif); ++ return 0; ++} ++ + /* + * Other compression schemes may be registered. Registered + * schemes can also override the builtin versions provided +diff --git a/libtiff/tif_fax3.c b/libtiff/tif_fax3.c +index 9d66fc0..ab06641 100644 +--- a/libtiff/tif_fax3.c ++++ b/libtiff/tif_fax3.c +@@ -1398,6 +1398,18 @@ static void Fax3PrintDir(TIFF *tif, FILE *fd, long flags) + (*sp->printdir)(tif, fd, flags); + } + ++static uint64_t Fax3GetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* 1024x1024: 36 */ ++ /* 4096x4096: 100 */ ++ /* 16383x16383: 163 */ ++ /* 65536x65536: 200 */ ++ /* 200000x200000: 208 */ ++ ++ return 250; ++} ++ + static int InitCCITTFax3(TIFF *tif) + { + static const char module[] = "InitCCITTFax3"; +@@ -1462,6 +1474,7 @@ static int InitCCITTFax3(TIFF *tif) + tif->tif_encodetile = Fax3Encode; + tif->tif_close = Fax3Close; + tif->tif_cleanup = Fax3Cleanup; ++ tif->tif_getmaxcompressionratio = Fax3GetMaxCompressionRatio; + + return (1); + } +@@ -1606,6 +1619,12 @@ static int Fax4PostEncode(TIFF *tif) + return (1); + } + ++static uint64_t Fax4GetMaxCompressionRatio(TIFF *tif) ++{ ++ return isTiled(tif) ? tif->tif_dir.td_tilewidth ++ : tif->tif_dir.td_imagewidth; ++} ++ + int TIFFInitCCITTFax4(TIFF *tif, int scheme) + { + (void)scheme; +@@ -1628,6 +1647,7 @@ int TIFFInitCCITTFax4(TIFF *tif, int scheme) + tif->tif_encodestrip = Fax4Encode; + tif->tif_encodetile = Fax4Encode; + tif->tif_postencode = Fax4PostEncode; ++ tif->tif_getmaxcompressionratio = Fax4GetMaxCompressionRatio; + /* + * Suppress RTC at the end of each strip. + */ +@@ -1697,6 +1717,18 @@ static int Fax3DecodeRLE(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) + return (1); + } + ++static uint64_t Fax3RLEGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* 1024x1024: 43 */ ++ /* 4096x4096: 128 */ ++ /* 16383x16383: 171 */ ++ /* 65536x65536: 205 */ ++ /* 200000x200000: 211 */ ++ ++ return 250; ++} ++ + int TIFFInitCCITTRLE(TIFF *tif, int scheme) + { + (void)scheme; +@@ -1705,6 +1737,7 @@ int TIFFInitCCITTRLE(TIFF *tif, int scheme) + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; ++ tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio; + /* + * Suppress RTC+EOLs when encoding and byte-align data. + */ +@@ -1723,6 +1756,7 @@ int TIFFInitCCITTRLEW(TIFF *tif, int scheme) + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; ++ tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio; + /* + * Suppress RTC+EOLs when encoding and word-align data. + */ +diff --git a/libtiff/tif_jpeg.c b/libtiff/tif_jpeg.c +index 250144f..5f62ccd 100644 +--- a/libtiff/tif_jpeg.c ++++ b/libtiff/tif_jpeg.c +@@ -2777,6 +2777,30 @@ static int JPEGInitializeLibJPEG(TIFF *tif, int decompress) + return 1; + } + ++static uint64_t JPEGGetMaxCompressionRatio(TIFF *tif) ++{ ++ JPEGState *sp = JState(tif); ++ if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) && ++ (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) && ++ (tif->tif_dir.td_samplesperpixel == 3)) ++ { ++ if (sp->h_sampling == 2 && sp->v_sampling == 2) ++ { ++ if (tif->tif_dir.td_bitspersample == 12) ++ return 768; ++ else ++ return 512; ++ } ++ ++ return 0; /* unknown */ ++ } ++ ++ if (tif->tif_dir.td_bitspersample == 12) ++ return 384; ++ else ++ return 256; ++} ++ + /* Common to tif_jpeg.c and tif_jpeg_12.c */ + static void TIFFInitJPEGCommon(TIFF *tif) + { +@@ -2813,6 +2837,7 @@ static void TIFFInitJPEGCommon(TIFF *tif) + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; ++ tif->tif_getmaxcompressionratio = JPEGGetMaxCompressionRatio; + tif->tif_cleanup = JPEGCleanup; + + tif->tif_defstripsize = JPEGDefaultStripSize; +diff --git a/libtiff/tif_lerc.c b/libtiff/tif_lerc.c +index 99de713..0262a73 100644 +--- a/libtiff/tif_lerc.c ++++ b/libtiff/tif_lerc.c +@@ -1140,6 +1140,16 @@ static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap) + return 1; + } + ++static uint64_t LERCGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ ++ /* LERC compression ratio can grow to several millions */ ++ /* eg. 5703725 for Lerc deflate on 16383x16383 array */ ++ /* or 3829644 for regular Lerc */ ++ return 0; ++} ++ + int TIFFInitLERC(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitLERC"; +@@ -1188,6 +1198,7 @@ int TIFFInitLERC(TIFF *tif, int scheme) + tif->tif_encoderow = LERCEncode; + tif->tif_encodestrip = LERCEncode; + tif->tif_encodetile = LERCEncode; ++ tif->tif_getmaxcompressionratio = LERCGetMaxCompressionRatio; + tif->tif_cleanup = LERCCleanup; + + /* Default values for codec-specific fields */ +diff --git a/libtiff/tif_lzma.c b/libtiff/tif_lzma.c +index 4cfd5e8..951529c 100644 +--- a/libtiff/tif_lzma.c ++++ b/libtiff/tif_lzma.c +@@ -433,6 +433,17 @@ static const TIFFField lzmaFields[] = { + "LZMA2 Compression Preset", NULL}, + }; + ++static uint64_t LZMAGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* 1024x1024: 3800 */ ++ /* 4096x4096: 6534 */ ++ /* 16383x16383: 6846 */ ++ /* 65536x65536: 6874 */ ++ ++ return 7000; ++} ++ + int TIFFInitLZMA(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitLZMA"; +@@ -508,6 +519,8 @@ int TIFFInitLZMA(TIFF *tif, int scheme) + tif->tif_encodestrip = LZMAEncode; + tif->tif_encodetile = LZMAEncode; + tif->tif_cleanup = LZMACleanup; ++ tif->tif_getmaxcompressionratio = LZMAGetMaxCompressionRatio; ++ + /* + * Setup predictor setup. + */ +diff --git a/libtiff/tif_lzw.c b/libtiff/tif_lzw.c +index d631fa1..eab6dc3 100644 +--- a/libtiff/tif_lzw.c ++++ b/libtiff/tif_lzw.c +@@ -1393,6 +1393,17 @@ static void LZWCleanup(TIFF *tif) + _TIFFSetDefaultCompressionState(tif); + } + ++static uint64_t LZWGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* 1024x1024: 562 */ ++ /* 4096x4096: 1243 */ ++ /* 16383x16383: 1353 */ ++ /* 65536x65536: 1362 */ ++ ++ return 1400; ++} ++ + int TIFFInitLZW(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitLZW"; +@@ -1424,6 +1435,7 @@ int TIFFInitLZW(TIFF *tif, int scheme) + tif->tif_encoderow = LZWEncode; + tif->tif_encodestrip = LZWEncode; + tif->tif_encodetile = LZWEncode; ++ tif->tif_getmaxcompressionratio = LZWGetMaxCompressionRatio; + tif->tif_cleanup = LZWCleanup; + /* + * Setup predictor setup. +diff --git a/libtiff/tif_packbits.c b/libtiff/tif_packbits.c +index 62849f8..706ed6a 100644 +--- a/libtiff/tif_packbits.c ++++ b/libtiff/tif_packbits.c +@@ -307,6 +307,12 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + return (1); + } + ++static uint64_t PackBitsGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ return 64; ++} ++ + int TIFFInitPackBits(TIFF *tif, int scheme) + { + (void)scheme; +@@ -318,6 +324,7 @@ int TIFFInitPackBits(TIFF *tif, int scheme) + tif->tif_encoderow = PackBitsEncode; + tif->tif_encodestrip = PackBitsEncodeChunk; + tif->tif_encodetile = PackBitsEncodeChunk; ++ tif->tif_getmaxcompressionratio = PackBitsGetMaxCompressionRatio; + return (1); + } + #endif /* PACKBITS_SUPPORT */ +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index fde985a..eef6f49 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -1648,6 +1648,16 @@ static const TIFFField pixarlogFields[] = { + {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL}}; + ++static uint64_t PixarLogGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* cf https://zlib.net/zlib_tech.html */ ++ const uint64_t MAX_DEFLATE_RATIO = 1032; ++ ++ /* security margin as I don't understand what this codec does */ ++ return MAX_DEFLATE_RATIO * (uint64_t)4; ++} ++ + int TIFFInitPixarLog(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitPixarLog"; +@@ -1695,6 +1705,7 @@ int TIFFInitPixarLog(TIFF *tif, int scheme) + tif->tif_encodetile = PixarLogEncode; + tif->tif_close = PixarLogClose; + tif->tif_cleanup = PixarLogCleanup; ++ tif->tif_getmaxcompressionratio = PixarLogGetMaxCompressionRatio; + + /* Override SetField so we can handle our private pseudo-tag */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; +diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c +index 4fec839..c72a79c 100644 +--- a/libtiff/tif_read.c ++++ b/libtiff/tif_read.c +@@ -579,13 +579,32 @@ tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif, uint32_t strip, + if (!TIFFFillStrip(tif, strip)) + return ((tmsize_t)(-1)); + +- *buf = _TIFFmallocExt(tif, bufsizetoalloc); ++ /* Sanity checks to avoid excessive memory allocation */ ++ /* Max compression ratio experimentally determined. Might be fragile... ++ * Only apply this heuristics to situations where the memory allocation ++ * would be big, to avoid breaking nominal use cases. ++ */ ++ const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif); ++ if (maxCompressionRatio > 0 && bufsizetoalloc > 100 * 1000 * 1000 && ++ (uint64_t)tif->tif_rawdatasize < ++ (uint64_t)this_stripsize / maxCompressionRatio) ++ { ++ TIFFErrorExtR(tif, TIFFFileName(tif), ++ "Likely invalid strip byte count for strip %u. " ++ "Uncompressed strip size is %" PRIu64 ", " ++ "compressed one is %" PRIu64, ++ strip, (uint64_t)this_stripsize, ++ (uint64_t)tif->tif_rawdatasize); ++ return ((tmsize_t)(-1)); ++ } ++ ++ ++ *buf = _TIFFcallocExt(tif, 1, bufsizetoalloc); + if (*buf == NULL) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "No space for strip buffer"); + return ((tmsize_t)(-1)); + } +- _TIFFmemset(*buf, 0, bufsizetoalloc); + + if ((*tif->tif_decodestrip)(tif, *buf, this_stripsize, plane) <= 0) + return ((tmsize_t)(-1)); +@@ -1042,17 +1061,10 @@ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF *tif, uint32_t tile, + * Only apply this heuristics to situations where the memory allocation + * would be big, to avoid breaking nominal use cases. + */ +- const int maxCompressionRatio = +- td->td_compression == COMPRESSION_ZSTD ? 33000 +- : td->td_compression == COMPRESSION_JXL +- ? +- /* Evaluated on a 8000x8000 tile */ +- 25000 * (td->td_planarconfig == PLANARCONFIG_CONTIG +- ? td->td_samplesperpixel +- : 1) +- : td->td_compression == COMPRESSION_LZMA ? 7000 : 1000; +- if (bufsizetoalloc > 100 * 1000 * 1000 && +- tif->tif_rawdatasize < tilesize / maxCompressionRatio) ++ const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif); ++ if (maxCompressionRatio > 0 && bufsizetoalloc > 100 * 1000 * 1000 && ++ (uint64_t)tif->tif_rawdatasize < ++ (uint64_t)tilesize / maxCompressionRatio) + { + TIFFErrorExtR(tif, TIFFFileName(tif), + "Likely invalid tile byte count for tile %u. " +diff --git a/libtiff/tif_webp.c b/libtiff/tif_webp.c +index 07db7cc..f66d739 100644 +--- a/libtiff/tif_webp.c ++++ b/libtiff/tif_webp.c +@@ -728,6 +728,14 @@ static const TIFFField TWebPFields[] = { + NULL}, + }; + ++static uint64_t TWebPGetMaxCompressionRatio(TIFF *tif) ++{ ++ /* lossy compression: */ ++ /* return (tif->tif_dir.td_samplesperpixel == 4) ? 2199 : 1685; */ ++ /* lossless compression: */ ++ return (tif->tif_dir.td_samplesperpixel == 4) ? 104194 : 78146; ++} ++ + int TIFFInitWebP(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitWebP"; +@@ -790,6 +798,7 @@ int TIFFInitWebP(TIFF *tif, int scheme) + tif->tif_encodestrip = TWebPEncode; + tif->tif_encodetile = TWebPEncode; + tif->tif_cleanup = TWebPCleanup; ++ tif->tif_getmaxcompressionratio = TWebPGetMaxCompressionRatio; + + return 1; + bad: +diff --git a/libtiff/tif_zip.c b/libtiff/tif_zip.c +index fcf5100..0467417 100644 +--- a/libtiff/tif_zip.c ++++ b/libtiff/tif_zip.c +@@ -653,6 +653,13 @@ static const TIFFField zipFields[] = { + TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL}, + }; + ++static uint64_t ZIPGetMaxCompressionRatio(TIFF *tif) ++{ ++ (void)tif; ++ /* cf https://zlib.net/zlib_tech.html */ ++ return 1032; ++} ++ + int TIFFInitZIP(TIFF *tif, int scheme) + { + static const char module[] = "TIFFInitZIP"; +@@ -719,6 +726,7 @@ int TIFFInitZIP(TIFF *tif, int scheme) + tif->tif_encodestrip = ZIPEncode; + tif->tif_encodetile = ZIPEncode; + tif->tif_cleanup = ZIPCleanup; ++ tif->tif_getmaxcompressionratio = ZIPGetMaxCompressionRatio; + /* + * Setup predictor setup. + */ +diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h +index 4df5766..5577cb1 100644 +--- a/libtiff/tiffio.h ++++ b/libtiff/tiffio.h +@@ -560,6 +560,7 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *, + tmsize_t cc); + extern tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, + tmsize_t cc); ++ extern uint64_t TIFFGetMaxCompressionRatio(TIFF *tif); + extern int TIFFDataWidth( + TIFFDataType); /* table of tag datatype widths within TIFF file. */ + extern void TIFFSetWriteOffset(TIFF *tif, toff_t off); +diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h +index 791881a..b40b1b2 100644 +--- a/libtiff/tiffiop.h ++++ b/libtiff/tiffiop.h +@@ -94,6 +94,7 @@ typedef int (*TIFFSeekMethod)(TIFF *, uint32_t); + typedef void (*TIFFPostMethod)(TIFF *tif, uint8_t *buf, tmsize_t size); + typedef uint32_t (*TIFFStripMethod)(TIFF *, uint32_t); + typedef void (*TIFFTileMethod)(TIFF *, uint32_t *, uint32_t *); ++typedef uint64_t (*TIFFGetMaxCompressionRatioMethod)(TIFF *); + + struct TIFFOffsetAndDirNumber + { +@@ -195,7 +196,9 @@ struct tiff + TIFFVoidMethod tif_cleanup; /* cleanup state routine */ + TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */ + TIFFTileMethod tif_deftilesize; /* calculate/constrain tile size */ +- uint8_t *tif_data; /* compression scheme private data */ ++ /* returns maximum compression ratio for current compression method */ ++ TIFFGetMaxCompressionRatioMethod tif_getmaxcompressionratio; ++ uint8_t *tif_data; /* compression scheme private data */ + /* input/output buffering */ + tmsize_t tif_scanlinesize; /* # of bytes in a scanline */ + tmsize_t tif_scanlineskew; /* scanline skew for reading strips */ diff -Nru tiff-4.5.0/debian/patches/CVE-2026-52490.patch tiff-4.5.0/debian/patches/CVE-2026-52490.patch --- tiff-4.5.0/debian/patches/CVE-2026-52490.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/CVE-2026-52490.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,135 @@ +From: waugustus <[email protected]> +Date: Fri, 12 Jun 2026 15:40:11 +0800 +Subject: Harden integer size and offset calculations in libtiff, tools, and + contrib + +Backport only the tiffcrop -S subdivision count hardening, which is the +part addressing CVE-2026-52490. The row/column zero and division based +MAX_SECTIONS guards come from the earlier upstream commits e12d1cf7 and +2f0509b0, which this change builds on. _TIFFCastUInt64ToUInt32() does not +exist in 4.5.0, so the uint64_t product is checked against UINT32_MAX +directly instead. + +Origin: backport, https://gitlab.com/libtiff/libtiff/-/commit/b04e935cb6242f22cc8b63c99a372cf3ea825e4e +Bug-Debian: https://bugs.debian.org/1147247 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-52490 +Bug-Freexian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2026-52490 +--- +--- a/tools/tiffcrop.c ++++ b/tools/tiffcrop.c +@@ -459,6 +459,7 @@ struct pagedef + 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 */ + }; + +@@ -2392,13 +2393,30 @@ void process_command_opts(int argc, char + page->cols = atoi(optarg); + page->rows = atoi(optarg); + } +- if ((page->cols * page->rows) > MAX_SECTIONS) ++ if ((page->cols == 0) || (page->rows == 0)) ++ { ++ TIFFError("Invalid subdivisions", ++ "Rows and columns must be non-zero"); ++ exit(EXIT_FAILURE); ++ } ++ ++ if (page->cols > (MAX_SECTIONS / page->rows)) + { + TIFFError( + "Limit for subdivisions, ie rows x columns, exceeded", + "%d", MAX_SECTIONS); + exit(EXIT_FAILURE); + } ++ { ++ uint64_t total_sections64 = ++ (uint64_t)page->cols * (uint64_t)page->rows; ++ if (total_sections64 == 0 || total_sections64 > UINT32_MAX) ++ { ++ TIFFError("No subdivisions", "%u", 0U); ++ exit(EXIT_FAILURE); ++ } ++ page->total_sections = (uint32_t)total_sections64; ++ } + page->mode |= PAGE_MODE_ROWSCOLS; + break; + case 'U': /* units for measurements and offsets */ +@@ -5710,6 +5728,7 @@ static void initPageSetup(struct pagedef + 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++) +@@ -6698,13 +6717,23 @@ static int computeOutputPixelOffsets(str + + 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 = (uint64_t)orows * (uint64_t)ocols; ++ if (total_sections64 == 0 || total_sections64 > UINT32_MAX) ++ { ++ TIFFError("computeOutputPixelOffsets", ++ "Integer overflow computing subdivision count"); ++ return (-1); ++ } ++ page->total_sections = (uint32_t)total_sections64; ++ } + + /* build the list of offsets for each output section */ + for (k = 0, i = 0; i < orows; i++) +@@ -6725,7 +6754,7 @@ static int computeOutputPixelOffsets(str + sections[k].y2 = y2; + sections[k].buffsize = line_bytes * olength; + sections[k].position = k + 1; +- sections[k].total = orows * ocols; ++ sections[k].total = (int)page->total_sections; + } + } + return (0); +@@ -8046,10 +8075,32 @@ static int writeImageSections(TIFF *in, + uint32_t i, k, width, length, sectsize; + unsigned char *sect_buff = *sect_buff_ptr; + ++ if ((page->cols == 0) || (page->rows == 0)) ++ { ++ TIFFError("Invalid subdivisions", "Rows and columns must be non-zero"); ++ return (-1); ++ } ++ ++ if (page->cols > (MAX_SECTIONS / page->rows)) ++ { ++ TIFFError("writeImageSections", ++ "Rows and Columns exceed maximum sections\n" ++ "Increase resolution or reduce sections"); ++ return (-1); ++ } ++ if (page->total_sections == 0) ++ { ++ uint64_t total_sections64 = ++ (uint64_t)page->cols * (uint64_t)page->rows; ++ if (total_sections64 == 0 || total_sections64 > UINT32_MAX) ++ return (-1); ++ page->total_sections = (uint32_t)total_sections64; ++ } ++ + hres = page->hres; + vres = page->vres; + +- k = page->cols * page->rows; ++ k = page->total_sections; + if ((k < 1) || (k > MAX_SECTIONS)) + { + TIFFError("writeImageSections", diff -Nru tiff-4.5.0/debian/patches/pixarlog-add-comment-explaining-4-byte-advance-in-AB.patch tiff-4.5.0/debian/patches/pixarlog-add-comment-explaining-4-byte-advance-in-AB.patch --- tiff-4.5.0/debian/patches/pixarlog-add-comment-explaining-4-byte-advance-in-AB.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/pixarlog-add-comment-explaining-4-byte-advance-in-AB.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,29 @@ +From: waugustus <[email protected]> +Date: Fri, 24 Apr 2026 09:16:55 +0800 +Subject: pixarlog: add comment explaining 4-byte advance in ABGR decode +Origin: https://gitlab.com/libtiff/libtiff/-/commit/51fa6dfe93f20da0d38f079fbc61c7c960bcbc16 +Bug: https://gitlab.com/libtiff/libtiff/-/merge_requests/873 +Bug-Debian: https://bugs.debian.org/1141320 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12912 + +--- + libtiff/tif_pixarlog.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index 18466144522a..8efd92737bd0 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -1004,6 +1004,9 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + case PIXARLOGDATAFMT_8BITABGR: + horizontalAccumulate8abgr(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); ++ ++ /* For stride == 3 (RGB), horizontalAccumulate8abgr expands to 4 ++ * bytes/pixel (ABGR) */ + if (sp->stride == 3) + op += (unsigned long)td->td_imagewidth * 4; + else +-- +2.53.0 + diff -Nru tiff-4.5.0/debian/patches/pixarlog-complete-ABGR-bounds-check-for-multi-row-st.patch tiff-4.5.0/debian/patches/pixarlog-complete-ABGR-bounds-check-for-multi-row-st.patch --- tiff-4.5.0/debian/patches/pixarlog-complete-ABGR-bounds-check-for-multi-row-st.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/pixarlog-complete-ABGR-bounds-check-for-multi-row-st.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,59 @@ +From: waugustus <[email protected]> +Date: Thu, 7 May 2026 12:48:42 +0800 +Subject: pixarlog: complete ABGR bounds check for multi-row strip decoding +Origin: https://gitlab.com/libtiff/libtiff/-/commit/f9bda11bf2fc819b971517582666d56f18b1bc3f +Bug: https://gitlab.com/libtiff/libtiff/-/merge_requests/883 +Bug-Debian: https://bugs.debian.org/1141320 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12912 + +--- + libtiff/tif_pixarlog.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index f35f3fb01588..a6f62f18b3b7 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -880,6 +880,12 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + if (sp->user_datafmt == PIXARLOGDATAFMT_8BITABGR && sp->stride == 3) + { + tmsize_t required = (tmsize_t)td->td_imagewidth * 4; ++ tmsize_t max_rows; ++ tmsize_t max_nsamples; ++ ++ /* ++ * Ensure at least one expanded output row fits. ++ */ + if (occ < required) + { + TIFFErrorExtR(tif, module, +@@ -887,6 +893,26 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + memset(op, 0, (size_t)occ); + return (0); + } ++ ++ /* ++ * PixarLogDecode() may process multiple rows per call ++ * (e.g. strip decoding). Limit nsamples so the total ++ * output written by the loop below never exceeds occ. ++ */ ++ max_rows = occ / required; ++ max_nsamples = max_rows * llen; ++ ++ /* ++ * Truncate excess rows to preserve as much decoded data ++ * as possible while avoiding output buffer overflow. ++ */ ++ if (nsamples > max_nsamples) ++ { ++ TIFFWarningExtR(tif, module, ++ "PixarLog ABGR decode truncated to avoid " ++ "output buffer overflow"); ++ nsamples = max_nsamples; ++ } + } + + (void)s; +-- +2.53.0 + diff -Nru tiff-4.5.0/debian/patches/pixarlog-error-out-on-invalid-ABGR-output-buffer-siz.patch tiff-4.5.0/debian/patches/pixarlog-error-out-on-invalid-ABGR-output-buffer-siz.patch --- tiff-4.5.0/debian/patches/pixarlog-error-out-on-invalid-ABGR-output-buffer-siz.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/pixarlog-error-out-on-invalid-ABGR-output-buffer-siz.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,60 @@ +From: waugustus <[email protected]> +Date: Thu, 7 May 2026 16:22:27 +0800 +Subject: pixarlog: error out on invalid ABGR output buffer sizes +Origin: https://gitlab.com/libtiff/libtiff/-/commit/90601d9a23382d98f3695ec14441145c37a77574 +Bug: https://gitlab.com/libtiff/libtiff/-/merge_requests/883 +Bug-Debian: https://bugs.debian.org/1141320 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12912 + +--- + libtiff/tif_pixarlog.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index a6f62f18b3b7..fa267dfbff20 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -894,6 +894,19 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + return (0); + } + ++ /* ++ * The caller-provided output buffer size must represent a whole ++ * number of expanded ABGR scanlines. ++ */ ++ if (occ % required) ++ { ++ TIFFErrorExtR( ++ tif, module, ++ "Fractional scanline not supported for PixarLog ABGR data"); ++ memset(op, 0, (size_t)occ); ++ return (0); ++ } ++ + /* + * PixarLogDecode() may process multiple rows per call + * (e.g. strip decoding). Limit nsamples so the total +@@ -902,16 +915,12 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + max_rows = occ / required; + max_nsamples = max_rows * llen; + +- /* +- * Truncate excess rows to preserve as much decoded data +- * as possible while avoiding output buffer overflow. +- */ + if (nsamples > max_nsamples) + { +- TIFFWarningExtR(tif, module, +- "PixarLog ABGR decode truncated to avoid " +- "output buffer overflow"); +- nsamples = max_nsamples; ++ TIFFErrorExtR(tif, module, ++ "Output buffer too small for PixarLog ABGR data"); ++ memset(op, 0, (size_t)occ); ++ return (0); + } + } + +-- +2.53.0 + diff -Nru tiff-4.5.0/debian/patches/pixarlog-fix-heap-buffer-overflow-in-8BITABGR-decode.patch tiff-4.5.0/debian/patches/pixarlog-fix-heap-buffer-overflow-in-8BITABGR-decode.patch --- tiff-4.5.0/debian/patches/pixarlog-fix-heap-buffer-overflow-in-8BITABGR-decode.patch 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/patches/pixarlog-fix-heap-buffer-overflow-in-8BITABGR-decode.patch 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,47 @@ +From: waugustus <[email protected]> +Date: Thu, 23 Apr 2026 17:05:53 +0800 +Subject: pixarlog: fix heap-buffer-overflow in 8BITABGR decode with stride 3 + (#824) +Origin: https://gitlab.com/libtiff/libtiff/-/commit/ba2b04b114c5dd945107ccc613cedfcca3af73bb +Bug: https://gitlab.com/libtiff/libtiff/-/merge_requests/873 +Bug-Debian: https://bugs.debian.org/1141320 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12912 + +--- + libtiff/tif_pixarlog.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -865,6 +865,19 @@ static int PixarLogDecode(TIFF *tif, uin + + llen = sp->stride * td->td_imagewidth; + ++ /* Fix: ABGR with stride=3 expands 3 samples to 4 output bytes per pixel */ ++ if (sp->user_datafmt == PIXARLOGDATAFMT_8BITABGR && sp->stride == 3) ++ { ++ tmsize_t required = (tmsize_t)td->td_imagewidth * 4; ++ if (occ < required) ++ { ++ TIFFErrorExtR(tif, module, ++ "Output buffer too small for PixarLog ABGR data"); ++ memset(op, 0, (size_t)occ); ++ return (0); ++ } ++ } ++ + (void)s; + assert(sp != NULL); + +@@ -978,7 +991,10 @@ static int PixarLogDecode(TIFF *tif, uin + case PIXARLOGDATAFMT_8BITABGR: + horizontalAccumulate8abgr(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); +- op += llen * sizeof(unsigned char); ++ if (sp->stride == 3) ++ op += (unsigned long)td->td_imagewidth * 4; ++ else ++ op += (unsigned long)llen * sizeof(unsigned char); + break; + default: + TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16, diff -Nru tiff-4.5.0/debian/patches/series tiff-4.5.0/debian/patches/series --- tiff-4.5.0/debian/patches/series 2026-04-07 17:21:56.000000000 +0000 +++ tiff-4.5.0/debian/patches/series 2026-09-22 23:02:07.000000000 +0000 @@ -20,3 +20,11 @@ CVE-2024-7006.patch CVE-2025-9900.patch CVE-2026-4775.patch +CVE-2024-13978.patch +pixarlog-fix-heap-buffer-overflow-in-8BITABGR-decode.patch +pixarlog-add-comment-explaining-4-byte-advance-in-AB.patch +pixarlog-complete-ABGR-bounds-check-for-multi-row-st.patch +pixarlog-error-out-on-invalid-ABGR-output-buffer-siz.patch +CVE-2026-52490.patch +CVE-2026-18495.patch +CVE-2026-36849.patch diff -Nru tiff-4.5.0/debian/salsa-ci.yml tiff-4.5.0/debian/salsa-ci.yml --- tiff-4.5.0/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ tiff-4.5.0/debian/salsa-ci.yml 2026-09-22 23:02:07.000000000 +0000 @@ -0,0 +1,2 @@ +include: +- https://salsa.debian.org/lts-team/pipeline/raw/master/recipes/bookworm.yml
signature.asc
Description: PGP signature
