cjpeg: Fix buf overrun caused by bad bin PPM input
This extends the fix in 6709e4a0cfa44d4f54ee8ad05753d4aa9260cb91 to
include binary PPM/PGM files, thus preventing a malformed binary
PPM/PGM input file from triggering an overrun of the rescale array and
potentially crashing cjpeg.
Note that this issue affected only cjpeg and not the underlying
libjpeg-turbo libraries, and thus it did not represent a security
threat.
Thanks to @hughdavenport for the discovery.
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 7593239..4de0955 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -31,6 +31,13 @@
easy to examine an application binary and determine which version of the
library the application was linked against.
+[6] Fixed a couple of issues in the PPM reader that would cause buffer overruns
+in cjpeg if one of the values in a binary PPM/PGM input file exceeded the
+maximum value defined in the file's header. libjpeg-turbo 1.4.2 already
+included a similar fix for ASCII PPM/PGM files. Note that these issues were
+not security bugs, since they were confined to the cjpeg program and did not
+affect any of the libjpeg-turbo libraries.
+
1.4.2
=====
diff --git a/rdppm.c b/rdppm.c
index ebe82ac..5b52f0e 100644
--- a/rdppm.c
+++ b/rdppm.c
@@ -4,8 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 2009 by Bill Allombert, Guido Vollbeding.
- * 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 file.
*
* This file contains routines to read input images in PPM/PGM format.
@@ -243,6 +243,7 @@
register U_CHAR * bufferptr;
register JSAMPLE *rescale = source->rescale;
JDIMENSION col;
+ unsigned int maxval = source->maxval;
if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
ERREXIT(cinfo, JERR_INPUT_EOF);
@@ -252,6 +253,8 @@
register int temp;
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
+ if (temp > maxval)
+ ERREXIT(cinfo, JERR_PPM_TOOLARGE);
*ptr++ = rescale[temp];
}
return 1;
@@ -267,6 +270,7 @@
register U_CHAR * bufferptr;
register JSAMPLE *rescale = source->rescale;
JDIMENSION col;
+ unsigned int maxval = source->maxval;
if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
ERREXIT(cinfo, JERR_INPUT_EOF);
@@ -276,12 +280,18 @@
register int temp;
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
+ if (temp > maxval)
+ ERREXIT(cinfo, JERR_PPM_TOOLARGE);
*ptr++ = rescale[temp];
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
+ if (temp > maxval)
+ ERREXIT(cinfo, JERR_PPM_TOOLARGE);
*ptr++ = rescale[temp];
temp = UCH(*bufferptr++) << 8;
temp |= UCH(*bufferptr++);
+ if (temp > maxval)
+ ERREXIT(cinfo, JERR_PPM_TOOLARGE);
*ptr++ = rescale[temp];
}
return 1;