a8dbb9
From f35fd27ec641c42d6b115bfa595e483ec58188d2 Mon Sep 17 00:00:00 2001
a8dbb9
From: DRC <information@libjpeg-turbo.org>
a8dbb9
Date: Tue, 6 Apr 2021 12:51:03 -0500
a8dbb9
Subject: [PATCH] tjLoadImage: Fix issues w/loading 16-bit PPMs/PGMs
a8dbb9
a8dbb9
- The PPM reader now throws an error rather than segfaulting (due to a
a8dbb9
  buffer overrun) if an application attempts to load a 16-bit PPM file
a8dbb9
  into a grayscale uncompressed image buffer.  No known applications
a8dbb9
  allowed that (not even the test applications in libjpeg-turbo),
a8dbb9
  because that mode of operation was never expected to work and did not
a8dbb9
  work under any circumstances.  (In fact, it was necessary to modify
a8dbb9
  TJBench in order to reproduce the issue outside of a fuzzing
a8dbb9
  environment.)  This was purely a matter of making the library bow out
a8dbb9
  gracefully rather than crash if an application tries to do something
a8dbb9
  really stupid.
a8dbb9
a8dbb9
- The PPM reader now throws an error rather than generating incorrect
a8dbb9
  pixels if an application attempts to load a 16-bit PGM file into an
a8dbb9
  RGB uncompressed image buffer.
a8dbb9
a8dbb9
- The PPM reader now correctly loads 16-bit PPM files into extended
a8dbb9
  RGB uncompressed image buffers.  (Previously it generated incorrect
a8dbb9
  pixels unless the input colorspace was JCS_RGB or JCS_EXT_RGB.)
a8dbb9
a8dbb9
The only way that users could have potentially encountered these issues
a8dbb9
was through the tjLoadImage() function.  cjpeg and TJBench were
a8dbb9
unaffected.
a8dbb9
---
a8dbb9
 ChangeLog.md | 10 ++++++++++
a8dbb9
 rdppm.c      | 26 ++++++++++++++++++++------
a8dbb9
 2 files changed, 30 insertions(+), 6 deletions(-)
a8dbb9
a8dbb9
diff --git a/rdppm.c b/rdppm.c
a8dbb9
index c4c937e8..6ac8fdbf 100644
a8dbb9
--- a/rdppm.c
a8dbb9
+++ b/rdppm.c
a8dbb9
@@ -5,7 +5,7 @@
a8dbb9
  * Copyright (C) 1991-1997, Thomas G. Lane.
a8dbb9
  * Modified 2009 by Bill Allombert, Guido Vollbeding.
a8dbb9
  * libjpeg-turbo Modifications:
a8dbb9
- * Copyright (C) 2015-2017, 2020, D. R. Commander.
a8dbb9
+ * Copyright (C) 2015-2017, 2020-2021, D. R. Commander.
a8dbb9
  * For conditions of distribution and use, see the accompanying README.ijg
a8dbb9
  * file.
a8dbb9
  *
a8dbb9
@@ -516,6 +516,11 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
a8dbb9
   register JSAMPLE *rescale = source->rescale;
a8dbb9
   JDIMENSION col;
a8dbb9
   unsigned int maxval = source->maxval;
a8dbb9
+  register int rindex = rgb_red[cinfo->in_color_space];
a8dbb9
+  register int gindex = rgb_green[cinfo->in_color_space];
a8dbb9
+  register int bindex = rgb_blue[cinfo->in_color_space];
a8dbb9
+  register int aindex = alpha_index[cinfo->in_color_space];
a8dbb9
+  register int ps = rgb_pixelsize[cinfo->in_color_space];
a8dbb9
 
a8dbb9
   if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
a8dbb9
     ERREXIT(cinfo, JERR_INPUT_EOF);
a8dbb9
@@ -527,17 +532,20 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
a8dbb9
     temp |= UCH(*bufferptr++);
a8dbb9
     if (temp > maxval)
a8dbb9
       ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
a8dbb9
-    *ptr++ = rescale[temp];
a8dbb9
+    ptr[rindex] = rescale[temp];
a8dbb9
     temp  = UCH(*bufferptr++) << 8;
a8dbb9
     temp |= UCH(*bufferptr++);
a8dbb9
     if (temp > maxval)
a8dbb9
       ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
a8dbb9
-    *ptr++ = rescale[temp];
a8dbb9
+    ptr[gindex] = rescale[temp];
a8dbb9
     temp  = UCH(*bufferptr++) << 8;
a8dbb9
     temp |= UCH(*bufferptr++);
a8dbb9
     if (temp > maxval)
a8dbb9
       ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
a8dbb9
-    *ptr++ = rescale[temp];
a8dbb9
+    ptr[bindex] = rescale[temp];
a8dbb9
+    if (aindex >= 0)
a8dbb9
+      ptr[aindex] = 0xFF;
a8dbb9
+    ptr += ps;
a8dbb9
   }
a8dbb9
   return 1;
a8dbb9
 }
a8dbb9
@@ -624,7 +632,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
a8dbb9
       cinfo->in_color_space = JCS_GRAYSCALE;
a8dbb9
     TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
a8dbb9
     if (maxval > 255) {
a8dbb9
-      source->pub.get_pixel_rows = get_word_gray_row;
a8dbb9
+      if (cinfo->in_color_space == JCS_GRAYSCALE)
a8dbb9
+        source->pub.get_pixel_rows = get_word_gray_row;
a8dbb9
+      else
a8dbb9
+        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
a8dbb9
     } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
a8dbb9
                cinfo->in_color_space == JCS_GRAYSCALE) {
a8dbb9
       source->pub.get_pixel_rows = get_raw_row;
a8dbb9
@@ -647,7 +658,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
a8dbb9
       cinfo->in_color_space = JCS_EXT_RGB;
a8dbb9
     TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
a8dbb9
     if (maxval > 255) {
a8dbb9
-      source->pub.get_pixel_rows = get_word_rgb_row;
a8dbb9
+      if (IsExtRGB(cinfo->in_color_space))
a8dbb9
+        source->pub.get_pixel_rows = get_word_rgb_row;
a8dbb9
+      else
a8dbb9
+        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
a8dbb9
     } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
a8dbb9
 #if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3
a8dbb9
                (cinfo->in_color_space == JCS_EXT_RGB ||
a8dbb9
-- 
a8dbb9
2.34.1
a8dbb9