From e01a3de226c179df0e32f37e7fa7dd8c3a3c28a2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 5 Dec 2021 15:10:12 +0100 Subject: tiffinfo: add a -M switch to define the maximum heap allocation, and default it to 256 MiB (fixes #287) --- tools/tiffinfo.c | 67 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/tools/tiffinfo.c b/tools/tiffinfo.c index 0ab8ca95..3db22280 100644 --- a/tools/tiffinfo.c +++ b/tools/tiffinfo.c @@ -57,6 +57,11 @@ static int stoponerr = 1; /* stop on first read error */ static void usage(int); static void tiffinfo(TIFF*, uint16_t, long, int); +#define DEFAULT_MAX_MALLOC (256 * 1024 * 1024) +/* malloc size limit (in bytes) + * disabled when set to 0 */ +static tmsize_t maxMalloc = DEFAULT_MAX_MALLOC; + static void PrivateErrorHandler(const char* module, const char* fmt, va_list ap) { @@ -79,7 +84,7 @@ main(int argc, char* argv[]) uint64_t diroff = 0; int chopstrips = 0; /* disable strip chopping */ - while ((c = getopt(argc, argv, "f:o:cdDSjilmrsvwz0123456789h")) != -1) + while ((c = getopt(argc, argv, "f:o:M:cdDSjilmrsvwz0123456789h")) != -1) switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': @@ -106,6 +111,9 @@ main(int argc, char* argv[]) case 'i': stoponerr = 0; break; + case 'M': + maxMalloc = (tmsize_t)strtoul(optarg, NULL, 0) << 20; + break; case 'o': diroff = strtoul(optarg, NULL, 0); break; @@ -197,6 +205,7 @@ static const char usage_info[] = " -s display strip offsets and byte counts\n" " -w display raw data in words rather than bytes\n" " -z enable strip chopping\n" +" -M size set the memory allocation limit in MiB. 0 to disable limit\n" " -# set initial directory (first directory is # 0)\n" ; @@ -432,20 +441,29 @@ TIFFReadRawDataStriped(TIFF* tif, int bitrev) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbc); if (stripbc != NULL && nstrips > 0) { - uint32_t bufsize = (uint32_t) stripbc[0]; - tdata_t buf = _TIFFmalloc(bufsize); + uint32_t bufsize = 0; + tdata_t buf = NULL; tstrip_t s; for (s = 0; s < nstrips; s++) { - if (stripbc[s] > bufsize) { - buf = _TIFFrealloc(buf, (tmsize_t)stripbc[s]); + if (stripbc[s] > bufsize || buf == NULL) { + tdata_t newbuf; + if (maxMalloc != 0 && stripbc[s] > (uint64_t)maxMalloc) + { + fprintf(stderr, + "Memory allocation attempt %" TIFF_SSIZE_FORMAT " over memory limit (%" TIFF_SSIZE_FORMAT ")", + (tmsize_t)stripbc[s], maxMalloc); + break; + } + newbuf = _TIFFrealloc(buf, (tmsize_t)stripbc[s]); + if (newbuf == NULL) { + fprintf(stderr, + "Cannot allocate buffer to read strip %"PRIu32"\n", + s); + break; + } bufsize = (uint32_t) stripbc[s]; - } - if (buf == NULL) { - fprintf(stderr, - "Cannot allocate buffer to read strip %"PRIu32"\n", - s); - break; + buf = newbuf; } if (TIFFReadRawStrip(tif, s, buf, (tmsize_t) stripbc[s]) < 0) { fprintf(stderr, "Error reading strip %"PRIu32"\n", @@ -485,15 +503,24 @@ TIFFReadRawDataTiled(TIFF* tif, int bitrev) uint32_t t; for (t = 0; t < ntiles; t++) { - if (buf == NULL || tilebc[t] > bufsize) { - buf = _TIFFrealloc(buf, (tmsize_t)tilebc[t]); - bufsize = tilebc[t]; - } - if (buf == NULL) { - fprintf(stderr, - "Cannot allocate buffer to read tile %"PRIu32"\n", - t); - break; + if (tilebc[t] > bufsize || buf == NULL) { + tdata_t newbuf; + if (maxMalloc != 0 && tilebc[t] > (uint64_t)maxMalloc) + { + fprintf(stderr, + "Memory allocation attempt %" TIFF_SSIZE_FORMAT " over memory limit (%" TIFF_SSIZE_FORMAT ")", + (tmsize_t)tilebc[t], maxMalloc); + break; + } + newbuf = _TIFFrealloc(buf, (tmsize_t)tilebc[t]); + if (newbuf == NULL) { + fprintf(stderr, + "Cannot allocate buffer to read tile %"PRIu32"\n", + t); + break; + } + bufsize = (uint32_t) tilebc[t]; + buf = newbuf; } if (TIFFReadRawTile(tif, t, buf, (tmsize_t)tilebc[t]) < 0) { fprintf(stderr, "Error reading tile %"PRIu32"\n", -- cgit v1.2.1