diff --git a/ChangeLog.txt b/ChangeLog.txt index 16b264d4..505f7664 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -91,6 +91,15 @@ improve performance on CPUs with in-order pipelines. This speeds up the decompression of full-color JPEGs by nearly 2x on average on a Cavium ThunderX processor and by about 15% on average on a Cortex-A53 core. +[17] Fixed an issue in the accelerated Huffman decoder that could have caused +the decoder to read past the end of the input buffer when a malformed, +specially-crafted JPEG image was being decompressed. In prior versions of +libjpeg-turbo, the accelerated Huffman decoder was invoked (in most cases) only +if there were > 128 bytes of data in the input buffer. However, it is possible +to construct a JPEG image in which a single Huffman block is over 430 bytes +long, so this version of libjpeg-turbo activates the accelerated Huffman +decoder only if there are > 512 bytes of data in the input buffer. + 1.4.2 ===== diff --git a/jdhuff.c b/jdhuff.c index e3a3f0aa..e0495ab8 100644 --- a/jdhuff.c +++ b/jdhuff.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2015, D. R. Commander. + * Copyright (C) 2009-2011, 2016, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -750,7 +750,7 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) * this module, since we'll just re-assign them on the next call.) */ -#define BUFSIZE (DCTSIZE2 * 2) +#define BUFSIZE (DCTSIZE2 * 8) METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) diff --git a/jmemmgr.c b/jmemmgr.c index 4ddf33ff..73e770f6 100644 --- a/jmemmgr.c +++ b/jmemmgr.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2016, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -70,9 +70,9 @@ round_up_pow2 (size_t a, size_t b) * There isn't any really portable way to determine the worst-case alignment * requirement. This module assumes that the alignment requirement is * multiples of ALIGN_SIZE. - * By default, we define ALIGN_SIZE as sizeof(double). This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, + * By default, we define ALIGN_SIZE as sizeof(double). This is necessary on + * some workstations (where doubles really do need 8-byte alignment) and will + * work fine on nearly everything. If your machine has lesser alignment needs, * you can save a few bytes by making ALIGN_SIZE smaller. * The only place I know of where this will NOT work is certain Macintosh * 680x0 compilers that define double as a 10-byte IEEE extended float. @@ -276,10 +276,16 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) * and so that algorithms can straddle outside the proper area up * to the next alignment. */ + if (sizeofobject > MAX_ALLOC_CHUNK) { + /* This prevents overflow/wrap-around in round_up_pow2() if sizeofobject + is close to SIZE_MAX. */ + out_of_memory(cinfo, 7); + } sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE); /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if ((sizeof(small_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK) + if ((sizeof(small_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > + MAX_ALLOC_CHUNK) out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ /* See if space is available in any existing pool */ @@ -364,10 +370,16 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) * algorithms can straddle outside the proper area up to the next * alignment. */ + if (sizeofobject > MAX_ALLOC_CHUNK) { + /* This prevents overflow/wrap-around in round_up_pow2() if sizeofobject + is close to SIZE_MAX. */ + out_of_memory(cinfo, 8); + } sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE); /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if ((sizeof(large_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK) + if ((sizeof(large_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > + MAX_ALLOC_CHUNK) out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ /* Always make a new pool */ @@ -379,7 +391,8 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) ALIGN_SIZE - 1); if (hdr_ptr == NULL) out_of_memory(cinfo, 4); /* jpeg_get_large failed */ - mem->total_space_allocated += sizeofobject + sizeof(large_pool_hdr) + ALIGN_SIZE - 1; + mem->total_space_allocated += sizeofobject + sizeof(large_pool_hdr) + + ALIGN_SIZE - 1; /* Success, initialize the new pool header and add to list */ hdr_ptr->next = mem->large_list[pool_id]; @@ -429,7 +442,14 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, /* Make sure each row is properly aligned */ if ((ALIGN_SIZE % sizeof(JSAMPLE)) != 0) out_of_memory(cinfo, 5); /* safety check */ - samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / sizeof(JSAMPLE)); + + if (samplesperrow > MAX_ALLOC_CHUNK) { + /* This prevents overflow/wrap-around in round_up_pow2() if sizeofobject + is close to SIZE_MAX. */ + out_of_memory(cinfo, 9); + } + samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / + sizeof(JSAMPLE)); /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) / diff --git a/rdppm.c b/rdppm.c index bf8ded01..f496ab36 100644 --- a/rdppm.c +++ b/rdppm.c @@ -93,7 +93,7 @@ pbm_getc (FILE * infile) LOCAL(unsigned int) -read_pbm_integer (j_compress_ptr cinfo, FILE * infile, int maxval) +read_pbm_integer (j_compress_ptr cinfo, FILE * infile, unsigned int maxval) /* Read an unsigned decimal integer from the PPM file */ /* Swallows one trailing character after the integer */ /* Note that on a 16-bit-int machine, only values up to 64k can be read. */ @@ -144,7 +144,7 @@ get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) register JSAMPROW ptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; - int maxval = source->maxval; + unsigned int maxval = source->maxval; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { @@ -163,7 +163,7 @@ get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) register JSAMPROW ptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; - int maxval = source->maxval; + unsigned int maxval = source->maxval; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { @@ -386,7 +386,7 @@ start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */ if (need_iobuffer) { source->buffer_width = (size_t) w * cinfo->input_components * - ((maxval<=255) ? sizeof(U_CHAR) : (2*sizeof(U_CHAR))); + ((maxval <= 255) ? sizeof(U_CHAR) : (2 * sizeof(U_CHAR))); source->iobuffer = (U_CHAR *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, source->buffer_width); @@ -414,11 +414,13 @@ start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* On 16-bit-int machines we have to be careful of maxval = 65535 */ source->rescale = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) (((long) maxval + 1L) * sizeof(JSAMPLE))); + (size_t) (((long) maxval + 1L) * + sizeof(JSAMPLE))); half_maxval = maxval / 2; for (val = 0; val <= (long) maxval; val++) { /* The multiplication here must be done in 32 bits to avoid overflow */ - source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval); + source->rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / + maxval); } } } diff --git a/turbojpeg.c b/turbojpeg.c index 5754cb17..f51df789 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2015 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2016 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -557,7 +557,8 @@ DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes) static tjhandle _tjInitCompress(tjinstance *this) { - unsigned char buffer[1], *buf=buffer; unsigned long size=1; + static unsigned char buffer[1]; + unsigned char *buf=buffer; unsigned long size=1; /* This is also straight out of example.c */ this->cinfo.err=jpeg_std_error(&this->jerr.pub); @@ -1218,7 +1219,7 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, static tjhandle _tjInitDecompress(tjinstance *this) { - unsigned char buffer[1]; + static unsigned char buffer[1]; /* This is also straight out of example.c */ this->dinfo.err=jpeg_std_error(&this->jerr.pub);