Skip to content

Commit d047ab6

Browse files
committed
Internal libtiff: add TIFFGetMaxCompressionRatio() and use it in _TIFFReadEncoded[Tile|Strip)AndAllocBuffer()
1 parent 9de6014 commit d047ab6

14 files changed

Lines changed: 200 additions & 14 deletions

File tree

frmts/gtiff/libtiff/tif_compress.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ void _TIFFSetDefaultPostDecode(TIFF *tif)
169169
}
170170
}
171171

172+
static uint64_t _TIFFDefaultGetMaxCompressionRatio(TIFF *tif)
173+
{
174+
(void)tif;
175+
return 0; /* unknown */
176+
}
177+
178+
static uint64_t _TIFFGetMaxCompressionRatioOne(TIFF *tif)
179+
{
180+
(void)tif;
181+
return 1; /* no compression */
182+
}
183+
172184
void _TIFFSetDefaultCompressionState(TIFF *tif)
173185
{
174186
tif->tif_fixuptags = _TIFFNoFixupTags;
@@ -191,6 +203,7 @@ void _TIFFSetDefaultCompressionState(TIFF *tif)
191203
tif->tif_cleanup = _TIFFvoid;
192204
tif->tif_defstripsize = _TIFFDefaultStripSize;
193205
tif->tif_deftilesize = _TIFFDefaultTileSize;
206+
tif->tif_getmaxcompressionratio = _TIFFDefaultGetMaxCompressionRatio;
194207
tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW);
195208
}
196209

@@ -199,6 +212,8 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme)
199212
const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme);
200213

201214
_TIFFSetDefaultCompressionState(tif);
215+
if (scheme == COMPRESSION_NONE)
216+
tif->tif_getmaxcompressionratio = _TIFFGetMaxCompressionRatioOne;
202217
/*
203218
* Don't treat an unknown compression scheme as an error.
204219
* This permits applications to open files with data that
@@ -208,6 +223,13 @@ int TIFFSetCompressionScheme(TIFF *tif, int scheme)
208223
return (c ? (*c->init)(tif, scheme) : 1);
209224
}
210225

226+
uint64_t TIFFGetMaxCompressionRatio(TIFF *tif)
227+
{
228+
if (tif->tif_getmaxcompressionratio)
229+
return tif->tif_getmaxcompressionratio(tif);
230+
return 0;
231+
}
232+
211233
/*
212234
* Other compression schemes may be registered. Registered
213235
* schemes can also override the builtin versions provided

frmts/gtiff/libtiff/tif_fax3.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,18 @@ static void Fax3PrintDir(TIFF *tif, FILE *fd, long flags)
15181518
(*sp->printdir)(tif, fd, flags);
15191519
}
15201520

1521+
static uint64_t Fax3GetMaxCompressionRatio(TIFF *tif)
1522+
{
1523+
(void)tif;
1524+
/* 1024x1024: 36 */
1525+
/* 4096x4096: 100 */
1526+
/* 16383x16383: 163 */
1527+
/* 65536x65536: 200 */
1528+
/* 200000x200000: 208 */
1529+
1530+
return 250;
1531+
}
1532+
15211533
static int InitCCITTFax3(TIFF *tif)
15221534
{
15231535
static const char module[] = "InitCCITTFax3";
@@ -1582,6 +1594,7 @@ static int InitCCITTFax3(TIFF *tif)
15821594
tif->tif_encodetile = Fax3Encode;
15831595
tif->tif_close = Fax3Close;
15841596
tif->tif_cleanup = Fax3Cleanup;
1597+
tif->tif_getmaxcompressionratio = Fax3GetMaxCompressionRatio;
15851598

15861599
return (1);
15871600
}
@@ -1731,6 +1744,12 @@ static int Fax4PostEncode(TIFF *tif)
17311744
return (1);
17321745
}
17331746

1747+
static uint64_t Fax4GetMaxCompressionRatio(TIFF *tif)
1748+
{
1749+
return isTiled(tif) ? tif->tif_dir.td_tilewidth
1750+
: tif->tif_dir.td_imagewidth;
1751+
}
1752+
17341753
int TIFFInitCCITTFax4(TIFF *tif, int scheme)
17351754
{
17361755
(void)scheme;
@@ -1753,6 +1772,7 @@ int TIFFInitCCITTFax4(TIFF *tif, int scheme)
17531772
tif->tif_encodestrip = Fax4Encode;
17541773
tif->tif_encodetile = Fax4Encode;
17551774
tif->tif_postencode = Fax4PostEncode;
1775+
tif->tif_getmaxcompressionratio = Fax4GetMaxCompressionRatio;
17561776
/*
17571777
* Suppress RTC at the end of each strip.
17581778
*/
@@ -1824,6 +1844,18 @@ static int Fax3DecodeRLE(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
18241844
return (1);
18251845
}
18261846

1847+
static uint64_t Fax3RLEGetMaxCompressionRatio(TIFF *tif)
1848+
{
1849+
(void)tif;
1850+
/* 1024x1024: 43 */
1851+
/* 4096x4096: 128 */
1852+
/* 16383x16383: 171 */
1853+
/* 65536x65536: 205 */
1854+
/* 200000x200000: 211 */
1855+
1856+
return 250;
1857+
}
1858+
18271859
int TIFFInitCCITTRLE(TIFF *tif, int scheme)
18281860
{
18291861
(void)scheme;
@@ -1832,6 +1864,7 @@ int TIFFInitCCITTRLE(TIFF *tif, int scheme)
18321864
tif->tif_decoderow = Fax3DecodeRLE;
18331865
tif->tif_decodestrip = Fax3DecodeRLE;
18341866
tif->tif_decodetile = Fax3DecodeRLE;
1867+
tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
18351868
/*
18361869
* Suppress RTC+EOLs when encoding and byte-align data.
18371870
*/
@@ -1850,6 +1883,7 @@ int TIFFInitCCITTRLEW(TIFF *tif, int scheme)
18501883
tif->tif_decoderow = Fax3DecodeRLE;
18511884
tif->tif_decodestrip = Fax3DecodeRLE;
18521885
tif->tif_decodetile = Fax3DecodeRLE;
1886+
tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
18531887
/*
18541888
* Suppress RTC+EOLs when encoding and word-align data.
18551889
*/

frmts/gtiff/libtiff/tif_jpeg.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,6 +2809,30 @@ static int JPEGInitializeLibJPEG(TIFF *tif, int decompress)
28092809
return 1;
28102810
}
28112811

2812+
static uint64_t JPEGGetMaxCompressionRatio(TIFF *tif)
2813+
{
2814+
JPEGState *sp = JState(tif);
2815+
if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) &&
2816+
(tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) &&
2817+
(tif->tif_dir.td_samplesperpixel == 3))
2818+
{
2819+
if (sp->h_sampling == 2 && sp->v_sampling == 2)
2820+
{
2821+
if (tif->tif_dir.td_bitspersample == 12)
2822+
return 768;
2823+
else
2824+
return 512;
2825+
}
2826+
2827+
return 0; /* unknown */
2828+
}
2829+
2830+
if (tif->tif_dir.td_bitspersample == 12)
2831+
return 384;
2832+
else
2833+
return 256;
2834+
}
2835+
28122836
/* Common to tif_jpeg.c and tif_jpeg_12.c */
28132837
static void TIFFInitJPEGCommon(TIFF *tif)
28142838
{
@@ -2845,6 +2869,7 @@ static void TIFFInitJPEGCommon(TIFF *tif)
28452869
tif->tif_encoderow = JPEGEncode;
28462870
tif->tif_encodestrip = JPEGEncode;
28472871
tif->tif_encodetile = JPEGEncode;
2872+
tif->tif_getmaxcompressionratio = JPEGGetMaxCompressionRatio;
28482873
tif->tif_cleanup = JPEGCleanup;
28492874

28502875
tif->tif_defstripsize = JPEGDefaultStripSize;

frmts/gtiff/libtiff/tif_lerc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,16 @@ static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap)
14881488
return 1;
14891489
}
14901490

1491+
static uint64_t LERCGetMaxCompressionRatio(TIFF *tif)
1492+
{
1493+
(void)tif;
1494+
1495+
/* LERC compression ratio can grow to several millions */
1496+
/* eg. 5703725 for Lerc deflate on 16383x16383 array */
1497+
/* or 3829644 for regular Lerc */
1498+
return 0;
1499+
}
1500+
14911501
int TIFFInitLERC(TIFF *tif, int scheme)
14921502
{
14931503
static const char module[] = "TIFFInitLERC";
@@ -1538,6 +1548,7 @@ int TIFFInitLERC(TIFF *tif, int scheme)
15381548
tif->tif_encodestrip = LERCEncode;
15391549
tif->tif_encodetile = LERCEncode;
15401550
#endif
1551+
tif->tif_getmaxcompressionratio = LERCGetMaxCompressionRatio;
15411552
tif->tif_cleanup = LERCCleanup;
15421553

15431554
/* Default values for codec-specific fields */

frmts/gtiff/libtiff/tif_lzma.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,17 @@ static const TIFFField lzmaFields[] = {
486486
FALSE, "LZMA2 Compression Preset", NULL},
487487
};
488488

489+
static uint64_t LZMAGetMaxCompressionRatio(TIFF *tif)
490+
{
491+
(void)tif;
492+
/* 1024x1024: 3800 */
493+
/* 4096x4096: 6534 */
494+
/* 16383x16383: 6846 */
495+
/* 65536x65536: 6874 */
496+
497+
return 7000;
498+
}
499+
489500
int TIFFInitLZMA(TIFF *tif, int scheme)
490501
{
491502
static const char module[] = "TIFFInitLZMA";
@@ -561,6 +572,8 @@ int TIFFInitLZMA(TIFF *tif, int scheme)
561572
tif->tif_encodestrip = LZMAEncode;
562573
tif->tif_encodetile = LZMAEncode;
563574
tif->tif_cleanup = LZMACleanup;
575+
tif->tif_getmaxcompressionratio = LZMAGetMaxCompressionRatio;
576+
564577
/*
565578
* Setup predictor setup.
566579
*/

frmts/gtiff/libtiff/tif_lzw.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,17 @@ static void LZWCleanup(TIFF *tif)
13991399
_TIFFSetDefaultCompressionState(tif);
14001400
}
14011401

1402+
static uint64_t LZWGetMaxCompressionRatio(TIFF *tif)
1403+
{
1404+
(void)tif;
1405+
/* 1024x1024: 562 */
1406+
/* 4096x4096: 1243 */
1407+
/* 16383x16383: 1353 */
1408+
/* 65536x65536: 1362 */
1409+
1410+
return 1400;
1411+
}
1412+
14021413
int TIFFInitLZW(TIFF *tif, int scheme)
14031414
{
14041415
static const char module[] = "TIFFInitLZW";
@@ -1432,6 +1443,7 @@ int TIFFInitLZW(TIFF *tif, int scheme)
14321443
tif->tif_encodestrip = LZWEncode;
14331444
tif->tif_encodetile = LZWEncode;
14341445
#endif
1446+
tif->tif_getmaxcompressionratio = LZWGetMaxCompressionRatio;
14351447
tif->tif_cleanup = LZWCleanup;
14361448
/*
14371449
* Setup predictor setup.

frmts/gtiff/libtiff/tif_packbits.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
317317
return (1);
318318
}
319319

320+
static uint64_t PackBitsGetMaxCompressionRatio(TIFF *tif)
321+
{
322+
(void)tif;
323+
return 64;
324+
}
325+
320326
int TIFFInitPackBits(TIFF *tif, int scheme)
321327
{
322328
(void)scheme;
@@ -330,6 +336,8 @@ int TIFFInitPackBits(TIFF *tif, int scheme)
330336
tif->tif_encodestrip = PackBitsEncodeChunk;
331337
tif->tif_encodetile = PackBitsEncodeChunk;
332338
#endif
339+
tif->tif_getmaxcompressionratio = PackBitsGetMaxCompressionRatio;
340+
333341
return (1);
334342
}
335343
#endif /* PACKBITS_SUPPORT */

frmts/gtiff/libtiff/tif_pixarlog.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,15 @@ static const TIFFField pixarlogFields[] = {
16191619
{TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
16201620
FALSE, FALSE, "", NULL}};
16211621

1622+
static uint64_t PixarLogGetMaxCompressionRatio(TIFF *tif)
1623+
{
1624+
(void)tif;
1625+
/* cf https://zlib.net/zlib_tech.html */
1626+
const uint64_t MAX_DEFLATE_RATIO = 1032;
1627+
1628+
/* security margin as I don't understand what this codec does */
1629+
return MAX_DEFLATE_RATIO * (uint64_t)4;
1630+
}
16221631
int TIFFInitPixarLog(TIFF *tif, int scheme)
16231632
{
16241633
static const char module[] = "TIFFInitPixarLog";
@@ -1666,6 +1675,7 @@ int TIFFInitPixarLog(TIFF *tif, int scheme)
16661675
tif->tif_encodetile = PixarLogEncode;
16671676
tif->tif_close = PixarLogClose;
16681677
tif->tif_cleanup = PixarLogCleanup;
1678+
tif->tif_getmaxcompressionratio = PixarLogGetMaxCompressionRatio;
16691679

16701680
/* Override SetField so we can handle our private pseudo-tag */
16711681
sp->vgetparent = tif->tif_tagmethods.vgetfield;

frmts/gtiff/libtiff/tif_read.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -618,13 +618,31 @@ tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif, uint32_t strip,
618618
if (!TIFFFillStrip(tif, strip))
619619
return ((tmsize_t)(-1));
620620

621-
*buf = _TIFFmallocExt(tif, bufsizetoalloc);
621+
/* Sanity checks to avoid excessive memory allocation */
622+
/* Max compression ratio experimentally determined. Might be fragile...
623+
* Only apply this heuristics to situations where the memory allocation
624+
* would be big, to avoid breaking nominal use cases.
625+
*/
626+
const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif);
627+
if (maxCompressionRatio > 0 && bufsizetoalloc > 100 * 1000 * 1000 &&
628+
(uint64_t)tif->tif_rawdatasize <
629+
(uint64_t)this_stripsize / maxCompressionRatio)
630+
{
631+
TIFFErrorExtR(tif, TIFFFileName(tif),
632+
"Likely invalid strip byte count for strip %u. "
633+
"Uncompressed strip size is %" PRIu64 ", "
634+
"compressed one is %" PRIu64,
635+
strip, (uint64_t)this_stripsize,
636+
(uint64_t)tif->tif_rawdatasize);
637+
return ((tmsize_t)(-1));
638+
}
639+
640+
*buf = _TIFFcallocExt(tif, 1, bufsizetoalloc);
622641
if (*buf == NULL)
623642
{
624643
TIFFErrorExtR(tif, TIFFFileName(tif), "No space for strip buffer");
625644
return ((tmsize_t)(-1));
626645
}
627-
_TIFFmemset(*buf, 0, bufsizetoalloc);
628646

629647
if ((*tif->tif_decodestrip)(tif, (uint8_t *)*buf, this_stripsize, plane) <=
630648
0)
@@ -1088,17 +1106,10 @@ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF *tif, uint32_t tile,
10881106
* Only apply this heuristics to situations where the memory allocation
10891107
* would be big, to avoid breaking nominal use cases.
10901108
*/
1091-
const int maxCompressionRatio =
1092-
td->td_compression == COMPRESSION_ZSTD ? 33000
1093-
: td->td_compression == COMPRESSION_JXL
1094-
?
1095-
/* Evaluated on a 8000x8000 tile */
1096-
25000 * (td->td_planarconfig == PLANARCONFIG_CONTIG
1097-
? td->td_samplesperpixel
1098-
: 1)
1099-
: td->td_compression == COMPRESSION_LZMA ? 7000 : 1000;
1100-
if (bufsizetoalloc > 100 * 1000 * 1000 &&
1101-
tif->tif_rawdatasize < tilesize / maxCompressionRatio)
1109+
const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif);
1110+
if (maxCompressionRatio > 0 && bufsizetoalloc > 100 * 1000 * 1000 &&
1111+
(uint64_t)tif->tif_rawdatasize <
1112+
(uint64_t)tilesize / maxCompressionRatio)
11021113
{
11031114
TIFFErrorExtR(tif, TIFFFileName(tif),
11041115
"Likely invalid tile byte count for tile %u. "

frmts/gtiff/libtiff/tif_webp.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,14 @@ static const TIFFField TWebPFields[] = {
847847
FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless", NULL},
848848
};
849849

850+
static uint64_t TWebPGetMaxCompressionRatio(TIFF *tif)
851+
{
852+
/* lossy compression: */
853+
/* return (tif->tif_dir.td_samplesperpixel == 4) ? 2199 : 1685; */
854+
/* lossless compression: */
855+
return (tif->tif_dir.td_samplesperpixel == 4) ? 104194 : 78146;
856+
}
857+
850858
int TIFFInitWebP(TIFF *tif, int scheme)
851859
{
852860
static const char module[] = "TIFFInitWebP";
@@ -910,6 +918,7 @@ int TIFFInitWebP(TIFF *tif, int scheme)
910918
tif->tif_encodestrip = TWebPEncode;
911919
tif->tif_encodetile = TWebPEncode;
912920
tif->tif_cleanup = TWebPCleanup;
921+
tif->tif_getmaxcompressionratio = TWebPGetMaxCompressionRatio;
913922

914923
return 1;
915924
bad:

0 commit comments

Comments
 (0)