From: Michael R Sweet <michael.r.sweet@gmail.com>
Date: Thu, 1 Apr 2021 09:37:58 -0400
Subject: CVE-2021-23158, CVE-2021-23191, CVE-2021-26252

Fix JPEG error handling (Issue #415)

Origin: upstream, https://github.com/michaelrsweet/htmldoc/commit/369b2ea1fd0d0537ba707f20a2f047b6afd2fbdc
Bug: https://github.com/michaelrsweet/htmldoc/issues/412
Bug: https://github.com/michaelrsweet/htmldoc/issues/414
Bug: https://github.com/michaelrsweet/htmldoc/issues/415
Bug-Debian: https://bugs.debian.org/989437
---
 htmldoc/file.c     |  9 ++++++++-
 htmldoc/image.cxx  | 38 +++++++++++++++++++++++++++++++-------
 htmldoc/ps-pdf.cxx |  5 +++++
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/htmldoc/file.c b/htmldoc/file.c
index 20229c1..9f017de 100644
--- a/htmldoc/file.c
+++ b/htmldoc/file.c
@@ -1000,8 +1000,15 @@ file_rlookup(const char *filename)	/* I - Filename */
 
 
   for (i = web_files, wc = web_cache; i > 0; i --, wc ++)
+  {
     if (!strcmp(wc->name, filename))
-      return (wc->url);
+    {
+      if (!strncmp(wc->url, "data:", 5))
+        return ("data URL");
+      else
+        return (wc->url);
+    }
+  }
 
   return (filename);
 }
diff --git a/htmldoc/image.cxx b/htmldoc/image.cxx
index 8f53050..74abfac 100644
--- a/htmldoc/image.cxx
+++ b/htmldoc/image.cxx
@@ -1336,6 +1336,15 @@ image_load_gif(image_t *img,	/* I - Image pointer */
 }
 
 
+typedef struct hd_jpeg_err_s	// JPEG error manager extension
+{
+  struct jpeg_error_mgr	jerr;	// JPEG error manager information
+  jmp_buf	retbuf;		// setjmp() return buffer
+  char		message[JMSG_LENGTH_MAX];
+				// Last error message
+} hd_jpeg_err_t;
+
+
 /*
  * 'image_load_jpeg()' - Load a JPEG image file.
  */
@@ -1347,14 +1356,21 @@ image_load_jpeg(image_t *img,	/* I - Image pointer */
                 int     load_data)/* I - 1 = load image data, 0 = just info */
 {
   struct jpeg_decompress_struct	cinfo;		/* Decompressor info */
-  struct jpeg_error_mgr		jerr;		/* Error handler info */
-  JSAMPROW			row;		/* Sample row pointer */
+  hd_jpeg_err_t			jerr;		// JPEG error handler
+JSAMPROW			row;		/* Sample row pointer */
 
 
-  jpeg_std_error(&jerr);
-  jerr.error_exit = jpeg_error_handler;
+  jpeg_std_error(&jerr.jerr);
+  jerr.jerr.error_exit = jpeg_error_handler;
 
-  cinfo.err = &jerr;
+  if (setjmp(jerr.retbuf))
+  {
+    progress_error(HD_ERROR_BAD_FORMAT, "%s (%s)", jerr.message,  file_rlookup(img->filename));
+    jpeg_destroy_decompress(&cinfo);
+    return (-1);
+  }
+
+  cinfo.err = (struct jpeg_error_mgr *)&jerr;
   jpeg_create_decompress(&cinfo);
   jpeg_stdio_src(&cinfo, fp);
   jpeg_read_header(&cinfo, (boolean)1);
@@ -1797,9 +1813,17 @@ image_unload(image_t *img)	// I - Image
  */
 
 static void
-jpeg_error_handler(j_common_ptr)
+jpeg_error_handler(j_common_ptr p)	// Common JPEG data
 {
-  return;
+  hd_jpeg_err_t	*jerr = (hd_jpeg_err_t *)p->err;
+					// JPEG error handler
+
+
+  // Save the error message in the string buffer...
+  (jerr->jerr.format_message)(p, jerr->message);
+
+  // Return to the point we called setjmp()...
+  longjmp(jerr->retbuf, 1);
 }
 
 
diff --git a/htmldoc/ps-pdf.cxx b/htmldoc/ps-pdf.cxx
index af1a55e..499f487 100644
--- a/htmldoc/ps-pdf.cxx
+++ b/htmldoc/ps-pdf.cxx
@@ -1404,6 +1404,8 @@ pspdf_prepare_page(int page)		/* I - Page number */
 
 
   DEBUG_printf(("pspdf_prepare_page(%d)\n", page));
+  if (page < 0 || page >= num_pages)
+    return;
 
  /*
   * Make a page number; use roman numerals for the table of contents
@@ -12258,6 +12260,9 @@ write_trailer(FILE  *out,		/* I - Output file */
 
       for (j = 1; j <= TocDocCount; j ++)
       {
+        if (chapter_starts[j] < 0)
+          continue;
+
         page  = pages + chapter_starts[j];
 	start = chapter_starts[j] - chapter_starts[1] + 1;
 	type  = 'D';
