From 779fbd23c0297aa571a7e0c99e48c58f7c766d56 Mon Sep 17 00:00:00 2001 From: Frank Bossen Date: Mon, 29 Dec 2014 19:42:20 +0100 Subject: [PATCH 2/3] Check range of integer values in PPM text file Add checks to ensure values are within the specified range. Fixes mozilla/mozjpeg#141, closes #8 --- cderror.h | 1 + rdppm.c | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cderror.h b/cderror.h index e19c475..d69b501 100644 --- a/cderror.h +++ b/cderror.h @@ -74,6 +74,7 @@ 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(JTRC_PGM, "%ux%u PGM image") JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") diff --git a/rdppm.c b/rdppm.c index a757022..5da1646 100644 --- a/rdppm.c +++ b/rdppm.c @@ -76,6 +76,7 @@ typedef struct { JSAMPROW pixrow; /* FAR pointer to same */ size_t buffer_width; /* width of I/O buffer */ JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ + int maxval; } ppm_source_struct; typedef ppm_source_struct * ppm_source_ptr; @@ -99,7 +100,7 @@ pbm_getc (FILE * infile) LOCAL(unsigned int) -read_pbm_integer (j_compress_ptr cinfo, FILE * infile) +read_pbm_integer (j_compress_ptr cinfo, FILE * infile, 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. */ @@ -123,6 +124,10 @@ read_pbm_integer (j_compress_ptr cinfo, FILE * infile) val *= 10; val += ch - '0'; } + + if (val > maxval) + ERREXIT(cinfo, JERR_PPM_TOOLARGE); + return val; } @@ -147,10 +152,11 @@ 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; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { - *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)]; } return 1; } @@ -165,12 +171,13 @@ 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; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { - *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; - *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; - *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)]; } return 1; } @@ -319,9 +326,9 @@ start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) } /* fetch the remaining header info */ - w = read_pbm_integer(cinfo, source->pub.input_file); - h = read_pbm_integer(cinfo, source->pub.input_file); - maxval = read_pbm_integer(cinfo, source->pub.input_file); + w = read_pbm_integer(cinfo, source->pub.input_file, 65535); + h = read_pbm_integer(cinfo, source->pub.input_file, 65535); + maxval = read_pbm_integer(cinfo, source->pub.input_file, 65535); if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ ERREXIT(cinfo, JERR_PPM_NOT); @@ -329,6 +336,7 @@ start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ cinfo->image_width = (JDIMENSION) w; cinfo->image_height = (JDIMENSION) h; + source->maxval = maxval; /* initialize flags to most common settings */ need_iobuffer = TRUE; /* do we need an I/O buffer? */ -- 2.17.2