From c57118965195d8d28923430f046c1c8a585da83f Mon Sep 17 00:00:00 2001 From: erouault Date: Sat, 24 Jun 2017 15:33:28 +0000 Subject: * libjpeg/tif_jpeg.c: error out at decoding time if anticipated libjpeg memory allocation is above 100 MB. libjpeg in case of multiple scans, which is allowed even in baseline JPEG, if components are spread over several scans and not interleavedin a single one, needs to allocate memory (or backing store) for the whole strip/tile. See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf This limitation may be overriden by setting the LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, or recompiling libtiff with a custom value of TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro. --- ChangeLog | 12 ++++++++++++ libtiff/tif_jpeg.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0059296a..bc5096e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2017-06-24 Even Rouault + + * libjpeg/tif_jpeg.c: error out at decoding time if anticipated libjpeg + memory allocation is above 100 MB. libjpeg in case of multiple scans, + which is allowed even in baseline JPEG, if components are spread over several + scans and not interleavedin a single one, needs to allocate memory (or + backing store) for the whole strip/tile. + See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf + This limitation may be overriden by setting the + LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, or recompiling + libtiff with a custom value of TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro. + 2017-06-24 Even Rouault * libtiff/tif_jpeg.c: add anti-denial of service measure to avoid excessive diff --git a/libtiff/tif_jpeg.c b/libtiff/tif_jpeg.c index afc11491..e28fd667 100644 --- a/libtiff/tif_jpeg.c +++ b/libtiff/tif_jpeg.c @@ -1,4 +1,4 @@ -/* $Id: tif_jpeg.c,v 1.129 2017-06-24 13:03:25 erouault Exp $ */ +/* $Id: tif_jpeg.c,v 1.130 2017-06-24 15:33:28 erouault Exp $ */ /* * Copyright (c) 1994-1997 Sam Leffler @@ -27,6 +27,8 @@ #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN +#include + #include "tiffiop.h" #ifdef JPEG_SUPPORT @@ -364,6 +366,12 @@ TIFFjpeg_read_header(JPEGState* sp, boolean require_image) return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); } +static int +TIFFjpeg_has_multiple_scans(JPEGState* sp) +{ + return CALLJPEG(sp, 0, jpeg_has_multiple_scans(&sp->cinfo.d)); +} + static int TIFFjpeg_start_decompress(JPEGState* sp) { @@ -1137,6 +1145,47 @@ JPEGPreDecode(TIFF* tif, uint16 s) return (0); } #endif + + /* In some cases, libjpeg needs to allocate a lot of memory */ + /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf */ + if( TIFFjpeg_has_multiple_scans(sp) ) + { + /* In this case libjpeg will need to allocate memory or backing */ + /* store for all coefficients */ + /* See call to jinit_d_coef_controller() from master_selection() */ + /* in libjpeg */ + toff_t nRequiredMemory = (toff_t)sp->cinfo.d.image_width * + sp->cinfo.d.image_height * + sp->cinfo.d.num_components * + ((td->td_bitspersample+7)/8); + /* BLOCK_SMOOTHING_SUPPORTED is generally defined, so we need */ + /* to replicate the logic of jinit_d_coef_controller() */ + if( sp->cinfo.d.progressive_mode ) + nRequiredMemory *= 3; + +#ifndef TIFF_LIBJPEG_LARGEST_MEM_ALLOC +#define TIFF_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024) +#endif + + if( nRequiredMemory > TIFF_LIBJPEG_LARGEST_MEM_ALLOC && + getenv("LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC") == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Reading this strip would require libjpeg to allocate " + "at least %u bytes. " + "This is disabled since above the %u threshold. " + "You may override this restriction by defining the " + "LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, " + "or recompile libtiff by defining the " + "TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater " + "than %u", + (unsigned)nRequiredMemory, + (unsigned)TIFF_LIBJPEG_LARGEST_MEM_ALLOC, + (unsigned)TIFF_LIBJPEG_LARGEST_MEM_ALLOC); + return (0); + } + } + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { /* Component 0 should have expected sampling factors */ if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || -- cgit v1.2.1