CVE-2021-23158 (published 2022-03-16T15:15Z)

A flaw was found in htmldoc in v1.9.12. Double-free in function pspdf_export(),in ps-pdf.cxx may result in a write-what-where condition, allowing an attacker to execute arbitrary code and denial of service.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-415
cwe_name: Double Free
description: The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.
extended_description: When a program calls free() twice with the same argument, the program's memory management data structures become corrupted. This corruption can cause the program to crash or, in some circumstances, cause two later calls to malloc() to return the same pointer. If malloc() returns the same value twice and the program later gives the attacker control over the data that is written into this doubly-allocated memory, the program becomes vulnerable to a buffer overflow attack.
         

Fix information:
repo_url: https://github.com/michaelrsweet/htmldoc
commit_details: repo_url: https://github.com/michaelrsweet/htmldoc
author: Michael R Sweet
author_date: 2021-04-01 09:37:58-04:00
msg: Fix JPEG error handling (Issue #415)
repository: repo_url: https://github.com/michaelrsweet/htmldoc
repo_name: michaelrsweet/htmldoc
description: HTML Conversion Software
repo_language: C++
owner: michaelrsweet
file_changes: filename: CHANGES.md
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,7 @@
 # Changes in HTMLDOC v1.9.12
 
 - Fixed a crash bug with "data:" URIs and EPUB output (Issue #410)
+- Fixed JPEG error handling (Issue #415)
 - Fixed crash bugs with bogus table attributes (Issue #416, Issue #417)
 - Fixed a crash bug with malformed URIs (Issue #418)
 - Fixed a crash bug with malformed GIF files (Issue #423)

programming_language: Markdown
filename: file.c
change_type: ModificationType.MODIFY
diff: @@ -1010,8 +1010,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);
 }

programming_language: C
filename: image.cxx
change_type: ModificationType.MODIFY
diff: @@ -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);
 }
 
 

programming_language: C
filename: ps-pdf.cxx
change_type: ModificationType.MODIFY
diff: @@ -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
@@ -12285,6 +12287,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';

programming_language: C