From 779fbd23c0297aa571a7e0c99e48c58f7c766d56 Mon Sep 17 00:00:00 2001
From: Frank Bossen <frank@bossentech.com>
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