Skip to content

Commit

Permalink
cjpeg: Fix OOB read caused by malformed 8-bit BMP
Browse files Browse the repository at this point in the history
... in which one or more of the color indices is out of range for the
number of palette entries.

Fix partly borrowed from jpeg-9c.  This commit also adopts Guido's
JERR_PPM_OUTOFRANGE enum value in lieu of our project-specific
JERR_PPM_TOOLARGE enum value.

Fixes libjpeg-turbo#258
  • Loading branch information
dcommander committed Jul 21, 2018
1 parent 0fa7850 commit 9c78a04
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
5 changes: 5 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ a 4:2:2 or 4:2:0 JPEG image using the merged (non-fancy) upsampling algorithms
7. The new CMake-based build system will now disable the MIPS DSPr2 SIMD
extensions if it detects that the compiler does not support DSPr2 instructions.

8. Fixed out-of-bounds read in cjpeg that occurred when attempting to compress
a specially-crafted malformed color-index (8-bit-per-sample) BMP file in which
some of the samples (color indices) exceeded the bounds of the BMP file's color
table.


1.5.90 (2.0 beta1)
==================
Expand Down
5 changes: 3 additions & 2 deletions cderror.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* cderror.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 2009 by Guido Vollbeding.
* Modified 2009-2017 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
Expand Down Expand Up @@ -49,6 +49,7 @@ JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image")
JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
JMESSAGE(JERR_BMP_OUTOFRANGE, "Numeric value out of range in BMP file")
JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
Expand All @@ -75,8 +76,8 @@ JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
#ifdef PPM_SUPPORTED
JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
JMESSAGE(JERR_PPM_TOOLARGE, "Integer value too large in PPM file")
JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
JMESSAGE(JERR_PPM_OUTOFRANGE, "Numeric value out of range in PPM file")
JMESSAGE(JTRC_PGM, "%ux%u PGM image")
JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
JMESSAGE(JTRC_PPM, "%ux%u PPM image")
Expand Down
13 changes: 12 additions & 1 deletion rdbmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* Modified 2009-2010 by Guido Vollbeding.
* Modified 2009-2017 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Modified 2011 by Siarhei Siamashka.
* Copyright (C) 2015, 2017-2018, D. R. Commander.
Expand Down Expand Up @@ -72,6 +72,7 @@ typedef struct _bmp_source_struct {
JDIMENSION row_width; /* Physical width of scanlines in file */

int bits_per_pixel; /* remembers 8- or 24-bit format */
int cmap_length; /* colormap length */

boolean use_inversion_array; /* TRUE = preload the whole image, which is
stored in bottom-up order, and feed it to
Expand Down Expand Up @@ -155,6 +156,7 @@ get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
bmp_source_ptr source = (bmp_source_ptr)sinfo;
register JSAMPARRAY colormap = source->colormap;
int cmaplen = source->cmap_length;
JSAMPARRAY image_ptr;
register int t;
register JSAMPROW inptr, outptr;
Expand All @@ -178,11 +180,15 @@ get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
if (cinfo->in_color_space == JCS_GRAYSCALE) {
for (col = cinfo->image_width; col > 0; col--) {
t = GETJSAMPLE(*inptr++);
if (t >= cmaplen)
ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
*outptr++ = colormap[0][t];
}
} else if (cinfo->in_color_space == JCS_CMYK) {
for (col = cinfo->image_width; col > 0; col--) {
t = GETJSAMPLE(*inptr++);
if (t >= cmaplen)
ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
rgb_to_cmyk(colormap[0][t], colormap[1][t], colormap[2][t], outptr,
outptr + 1, outptr + 2, outptr + 3);
outptr += 4;
Expand All @@ -197,6 +203,8 @@ get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
if (aindex >= 0) {
for (col = cinfo->image_width; col > 0; col--) {
t = GETJSAMPLE(*inptr++);
if (t >= cmaplen)
ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
outptr[rindex] = colormap[0][t];
outptr[gindex] = colormap[1][t];
outptr[bindex] = colormap[2][t];
Expand All @@ -206,6 +214,8 @@ get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
} else {
for (col = cinfo->image_width; col > 0; col--) {
t = GETJSAMPLE(*inptr++);
if (t >= cmaplen)
ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
outptr[rindex] = colormap[0][t];
outptr[gindex] = colormap[1][t];
outptr[bindex] = colormap[2][t];
Expand Down Expand Up @@ -539,6 +549,7 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* Allocate space to store the colormap */
source->colormap = (*cinfo->mem->alloc_sarray)
((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)biClrUsed, (JDIMENSION)3);
source->cmap_length = (int)biClrUsed;
/* and read it from the file */
read_colormap(source, (int)biClrUsed, mapentrysize);
/* account for size of colormap */
Expand Down
12 changes: 6 additions & 6 deletions rdppm.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ typedef struct {
JSAMPROW pixrow; /* compressor input buffer */
size_t buffer_width; /* width of I/O buffer */
JSAMPLE *rescale; /* => maxval-remapping array, or NULL */
int maxval;
unsigned int maxval;
} ppm_source_struct;

typedef ppm_source_struct *ppm_source_ptr;
Expand Down Expand Up @@ -125,7 +125,7 @@ read_pbm_integer(j_compress_ptr cinfo, FILE *infile, unsigned int maxval)
}

if (val > maxval)
ERREXIT(cinfo, JERR_PPM_TOOLARGE);
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);

return val;
}
Expand Down Expand Up @@ -509,7 +509,7 @@ get_word_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
if (temp > maxval)
ERREXIT(cinfo, JERR_PPM_TOOLARGE);
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
*ptr++ = rescale[temp];
}
return 1;
Expand All @@ -536,17 +536,17 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
if (temp > maxval)
ERREXIT(cinfo, JERR_PPM_TOOLARGE);
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
*ptr++ = rescale[temp];
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
if (temp > maxval)
ERREXIT(cinfo, JERR_PPM_TOOLARGE);
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
*ptr++ = rescale[temp];
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
if (temp > maxval)
ERREXIT(cinfo, JERR_PPM_TOOLARGE);
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
*ptr++ = rescale[temp];
}
return 1;
Expand Down

0 comments on commit 9c78a04

Please sign in to comment.