Skip to content

Commit f35fd27

Browse files
committed
tjLoadImage: Fix issues w/loading 16-bit PPMs/PGMs
- The PPM reader now throws an error rather than segfaulting (due to a buffer overrun) if an application attempts to load a 16-bit PPM file into a grayscale uncompressed image buffer. No known applications allowed that (not even the test applications in libjpeg-turbo), because that mode of operation was never expected to work and did not work under any circumstances. (In fact, it was necessary to modify TJBench in order to reproduce the issue outside of a fuzzing environment.) This was purely a matter of making the library bow out gracefully rather than crash if an application tries to do something really stupid. - The PPM reader now throws an error rather than generating incorrect pixels if an application attempts to load a 16-bit PGM file into an RGB uncompressed image buffer. - The PPM reader now correctly loads 16-bit PPM files into extended RGB uncompressed image buffers. (Previously it generated incorrect pixels unless the input colorspace was JCS_RGB or JCS_EXT_RGB.) The only way that users could have potentially encountered these issues was through the tjLoadImage() function. cjpeg and TJBench were unaffected.
1 parent df17d39 commit f35fd27

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

Diff for: ChangeLog.md

+10
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ applications that use the TurboJPEG API to guard against an exploit of the
3535
progressive JPEG format described in the report
3636
["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf).
3737

38+
7. The PPM reader now throws an error, rather than segfaulting (due to a buffer
39+
overrun) or generating incorrect pixels, if an application attempts to use the
40+
`tjLoadImage()` function to load a 16-bit binary PPM file (a binary PPM file
41+
with a maximum value greater than 255) into a grayscale image buffer or to load
42+
a 16-bit binary PGM file into an RGB image buffer.
43+
44+
8. Fixed an issue in the PPM reader that caused incorrect pixels to be
45+
generated when using the `tjLoadImage()` function to load a 16-bit binary PPM
46+
file into an extended RGB image buffer.
47+
3848

3949
2.0.90 (2.1 beta1)
4050
==================

Diff for: rdppm.c

+20-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Copyright (C) 1991-1997, Thomas G. Lane.
66
* Modified 2009 by Bill Allombert, Guido Vollbeding.
77
* libjpeg-turbo Modifications:
8-
* Copyright (C) 2015-2017, 2020, D. R. Commander.
8+
* Copyright (C) 2015-2017, 2020-2021, D. R. Commander.
99
* For conditions of distribution and use, see the accompanying README.ijg
1010
* file.
1111
*
@@ -516,6 +516,11 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
516516
register JSAMPLE *rescale = source->rescale;
517517
JDIMENSION col;
518518
unsigned int maxval = source->maxval;
519+
register int rindex = rgb_red[cinfo->in_color_space];
520+
register int gindex = rgb_green[cinfo->in_color_space];
521+
register int bindex = rgb_blue[cinfo->in_color_space];
522+
register int aindex = alpha_index[cinfo->in_color_space];
523+
register int ps = rgb_pixelsize[cinfo->in_color_space];
519524

520525
if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
521526
ERREXIT(cinfo, JERR_INPUT_EOF);
@@ -527,17 +532,20 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
527532
temp |= UCH(*bufferptr++);
528533
if (temp > maxval)
529534
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
530-
*ptr++ = rescale[temp];
535+
ptr[rindex] = rescale[temp];
531536
temp = UCH(*bufferptr++) << 8;
532537
temp |= UCH(*bufferptr++);
533538
if (temp > maxval)
534539
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
535-
*ptr++ = rescale[temp];
540+
ptr[gindex] = rescale[temp];
536541
temp = UCH(*bufferptr++) << 8;
537542
temp |= UCH(*bufferptr++);
538543
if (temp > maxval)
539544
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
540-
*ptr++ = rescale[temp];
545+
ptr[bindex] = rescale[temp];
546+
if (aindex >= 0)
547+
ptr[aindex] = 0xFF;
548+
ptr += ps;
541549
}
542550
return 1;
543551
}
@@ -624,7 +632,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
624632
cinfo->in_color_space = JCS_GRAYSCALE;
625633
TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
626634
if (maxval > 255) {
627-
source->pub.get_pixel_rows = get_word_gray_row;
635+
if (cinfo->in_color_space == JCS_GRAYSCALE)
636+
source->pub.get_pixel_rows = get_word_gray_row;
637+
else
638+
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
628639
} else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
629640
cinfo->in_color_space == JCS_GRAYSCALE) {
630641
source->pub.get_pixel_rows = get_raw_row;
@@ -647,7 +658,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
647658
cinfo->in_color_space = JCS_EXT_RGB;
648659
TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
649660
if (maxval > 255) {
650-
source->pub.get_pixel_rows = get_word_rgb_row;
661+
if (IsExtRGB(cinfo->in_color_space))
662+
source->pub.get_pixel_rows = get_word_rgb_row;
663+
else
664+
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
651665
} else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
652666
#if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3
653667
(cinfo->in_color_space == JCS_EXT_RGB ||

0 commit comments

Comments
 (0)