tiffcrop: enforce memory allocation limit

uses -k option to change limit (default to 256MiB)
fixes #117 / http://bugzilla.maptools.org/show_bug.cgi?id=2757
This commit is contained in:
Thomas Bernard 2020-04-03 19:11:09 +00:00 committed by Even Rouault
parent 57449991d7
commit 1f3e801d96
2 changed files with 50 additions and 22 deletions

View File

@ -350,6 +350,10 @@ will force data to be written with the FillOrder tag set to
.TP
.B \-i
Ignore non\-fatal read errors and continue processing of the input file.
.TP
.B "\-k size"
Set maximum memory allocation size (in MiB). The default is 256MiB.
Set to 0 to disable the limit.
.TP
.B \-l
Specify the length of a tile (in pixels).

View File

@ -333,7 +333,7 @@ struct paperdef {
/* European page sizes corrected from update sent by
* thomas . jarosch @ intra2net . com on 5/7/2010
* Paper Size Width Length Aspect Ratio */
struct paperdef PaperTable[MAX_PAPERNAMES] = {
const struct paperdef PaperTable[MAX_PAPERNAMES] = {
{"default", 8.500, 14.000, 0.607},
{"pa4", 8.264, 11.000, 0.751},
{"letter", 8.500, 11.000, 0.773},
@ -617,6 +617,27 @@ static int dump_buffer (FILE *, int, uint32, uint32, uint32, unsigned char *);
/* Functions derived in whole or in part from tiffcp */
/* The following functions are taken largely intact from tiffcp */
#define DEFAULT_MAX_MALLOC (256 * 1024 * 1024)
/* malloc size limit (in bytes)
* disabled when set to 0 */
static tmsize_t maxMalloc = DEFAULT_MAX_MALLOC;
/**
* This custom malloc function enforce a maximum allocation size
*/
static void* limitMalloc(tmsize_t s)
{
if (maxMalloc && (s > maxMalloc)) {
fprintf(stderr, "MemoryLimitError: allocation of " TIFF_UINT64_FORMAT " bytes is forbidden. Limit is " TIFF_UINT64_FORMAT ".\n",
(uint64)s, (uint64)maxMalloc);
fprintf(stderr, " use -k option to change limit.\n"); return NULL;
}
return _TIFFmalloc(s);
}
static char* usage_info[] = {
"usage: tiffcrop [options] source1 ... sourceN destination",
"where options are:",
@ -630,6 +651,7 @@ static char* usage_info[] = {
" -s Write output in strips",
" -t Write output in tiles",
" -i Ignore read errors",
" -k size set the memory allocation limit in MiB. 0 to disable limit",
" ",
" -r # Make each strip have no more than # rows",
" -w # Set output tile width (pixels)",
@ -822,7 +844,7 @@ static int readContigTilesIntoBuffer (TIFF* in, uint8* buf,
TIFFError("readContigTilesIntoBuffer", "Integer overflow when calculating buffer size.");
exit(-1);
}
tilebuf = _TIFFmalloc(tile_buffsize + 3);
tilebuf = limitMalloc(tile_buffsize + 3);
if (tilebuf == 0)
return 0;
tilebuf[tile_buffsize] = 0;
@ -986,7 +1008,7 @@ static int readSeparateTilesIntoBuffer (TIFF* in, uint8 *obuf,
for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
{
srcbuffs[sample] = NULL;
tbuff = (unsigned char *)_TIFFmalloc(tilesize + 8);
tbuff = (unsigned char *)limitMalloc(tilesize + 8);
if (!tbuff)
{
TIFFError ("readSeparateTilesIntoBuffer",
@ -1181,7 +1203,7 @@ writeBufferToSeparateStrips (TIFF* out, uint8* buf,
}
rowstripsize = rowsperstrip * bytes_per_sample * (width + 1);
obuf = _TIFFmalloc (rowstripsize);
obuf = limitMalloc (rowstripsize);
if (obuf == NULL)
return 1;
@ -1275,7 +1297,7 @@ static int writeBufferToContigTiles (TIFF* out, uint8* buf, uint32 imagelength,
}
src_rowsize = ((imagewidth * spp * bps) + 7U) / 8;
tilebuf = _TIFFmalloc(tile_buffsize);
tilebuf = limitMalloc(tile_buffsize);
if (tilebuf == 0)
return 1;
for (row = 0; row < imagelength; row += tl)
@ -1323,7 +1345,7 @@ static int writeBufferToSeparateTiles (TIFF* out, uint8* buf, uint32 imagelength
uint32 imagewidth, tsample_t spp,
struct dump_opts * dump)
{
tdata_t obuf = _TIFFmalloc(TIFFTileSize(out));
tdata_t obuf = limitMalloc(TIFFTileSize(out));
uint32 tl, tw;
uint32 row, col, nrow, ncol;
uint32 src_rowsize, col_offset;
@ -1612,7 +1634,7 @@ void process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32
*mp++ = 'w';
*mp = '\0';
while ((c = getopt(argc, argv,
"ac:d:e:f:hil:m:p:r:stvw:z:BCD:E:F:H:I:J:K:LMN:O:P:R:S:U:V:X:Y:Z:")) != -1)
"ac:d:e:f:hik:l:m:p:r:stvw:z:BCD:E:F:H:I:J:K:LMN:O:P:R:S:U:V:X:Y:Z:")) != -1)
{
good_args++;
switch (c) {
@ -1671,6 +1693,8 @@ void process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32
break;
case 'i': ignore = TRUE; /* ignore errors */
break;
case 'k': maxMalloc = (tmsize_t)strtoul(optarg, NULL, 0) << 20;
break;
case 'l': outtiled = TRUE; /* tile length */
*deftilelength = atoi(optarg);
break;
@ -4831,7 +4855,7 @@ static int readSeparateStripsIntoBuffer (TIFF *in, uint8 *obuf, uint32 length,
for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
{
srcbuffs[s] = NULL;
buff = _TIFFmalloc(stripsize + 3);
buff = limitMalloc(stripsize + 3);
if (!buff)
{
TIFFError ("readSeparateStripsIntoBuffer",
@ -6138,7 +6162,7 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
return (-1);
}
read_buff = (unsigned char *)_TIFFmalloc(buffsize+3);
read_buff = (unsigned char *)limitMalloc(buffsize+3);
}
else
{
@ -6153,7 +6177,7 @@ loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned c
if (!new_buff)
{
free (read_buff);
read_buff = (unsigned char *)_TIFFmalloc(buffsize+3);
read_buff = (unsigned char *)limitMalloc(buffsize+3);
}
else
read_buff = new_buff;
@ -7336,7 +7360,7 @@ createImageSection(uint32 sectsize, unsigned char **sect_buff_ptr)
if (!sect_buff)
{
sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
sect_buff = (unsigned char *)limitMalloc(sectsize);
*sect_buff_ptr = sect_buff;
_TIFFmemset(sect_buff, 0, sectsize);
}
@ -7347,8 +7371,8 @@ createImageSection(uint32 sectsize, unsigned char **sect_buff_ptr)
new_buff = _TIFFrealloc(sect_buff, sectsize);
if (!new_buff)
{
free (sect_buff);
sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
_TIFFfree (sect_buff);
sect_buff = (unsigned char *)limitMalloc(sectsize);
}
else
sect_buff = new_buff;
@ -7389,7 +7413,7 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
cropsize = crop->bufftotal;
crop_buff = seg_buffs[0].buffer;
if (!crop_buff)
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
else
{
prev_cropsize = seg_buffs[0].size;
@ -7399,7 +7423,7 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
if (! next_buff)
{
_TIFFfree (crop_buff);
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
}
else
crop_buff = next_buff;
@ -7491,7 +7515,7 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
cropsize = crop->bufftotal;
crop_buff = seg_buffs[i].buffer;
if (!crop_buff)
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
else
{
prev_cropsize = seg_buffs[0].size;
@ -7501,7 +7525,7 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
if (! next_buff)
{
_TIFFfree (crop_buff);
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
}
else
crop_buff = next_buff;
@ -7627,7 +7651,7 @@ createCroppedImage(struct image_data *image, struct crop_mask *crop,
crop_buff = *crop_buff_ptr;
if (!crop_buff)
{
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
*crop_buff_ptr = crop_buff;
_TIFFmemset(crop_buff, 0, cropsize);
prev_cropsize = cropsize;
@ -7640,7 +7664,7 @@ createCroppedImage(struct image_data *image, struct crop_mask *crop,
if (!new_buff)
{
free (crop_buff);
crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
crop_buff = (unsigned char *)limitMalloc(cropsize);
}
else
crop_buff = new_buff;
@ -8413,7 +8437,7 @@ rotateImage(uint16 rotation, struct image_data *image, uint32 *img_width,
return (-1);
}
if (!(rbuff = (unsigned char *)_TIFFmalloc(buffsize)))
if (!(rbuff = (unsigned char *)limitMalloc(buffsize)))
{
TIFFError("rotateImage", "Unable to allocate rotation buffer of %1u bytes", buffsize);
return (-1);
@ -9043,7 +9067,7 @@ mirrorImage(uint16 spp, uint16 bps, uint16 mirror, uint32 width, uint32 length,
{
case MIRROR_BOTH:
case MIRROR_VERT:
line_buff = (unsigned char *)_TIFFmalloc(rowsize);
line_buff = (unsigned char *)limitMalloc(rowsize);
if (line_buff == NULL)
{
TIFFError ("mirrorImage", "Unable to allocate mirror line buffer of %1u bytes", rowsize);
@ -9080,7 +9104,7 @@ mirrorImage(uint16 spp, uint16 bps, uint16 mirror, uint32 width, uint32 length,
}
else
{ /* non 8 bit per sample data */
if (!(line_buff = (unsigned char *)_TIFFmalloc(rowsize + 1)))
if (!(line_buff = (unsigned char *)limitMalloc(rowsize + 1)))
{
TIFFError("mirrorImage", "Unable to allocate mirror line buffer");
return (-1);