From 360153f3aa63c8fef0d507eccde75f46342c5264 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 31 Jan 2024 14:08:18 +0000
Subject: [PATCH 2/2] Bug 707510(5)2: The original fix was overly aggressive

The way the default OCRLanguage value was set was for the relevant get_params
methods to check if the value had been set, and if not return a default value.
This could result in the first time the put_params seeing that value being after
path control has been enabled, meaning it would throw an invalidaccess error.

This changes how we set the default: they now uses an init_device method, so
the string is populated from the device's creation. This works correctly for
both the default value, and for values set on the command line.

CVE: CVE-2024-29511

Upstream-Status: Backport [https://git.ghostscript.com/?p=ghostpdl.git;a=patch;h=638159c43dbb48425a187d244ec288d252d0ecf4]

Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
---
 devices/gdevocr.c         | 17 ++++++++++++++++-
 devices/gdevpdfocr.c      | 28 ++++++++++++++++++++++------
 devices/vector/gdevpdf.c  | 15 +++++++++++++++
 devices/vector/gdevpdfp.c |  3 ++-
 4 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/devices/gdevocr.c b/devices/gdevocr.c
index 287b74b..a616ef4 100644
--- a/devices/gdevocr.c
+++ b/devices/gdevocr.c
@@ -30,6 +30,7 @@
 #define X_DPI 72
 #define Y_DPI 72

+static dev_proc_initialize_device(ocr_initialize_device);
 static dev_proc_print_page(ocr_print_page);
 static dev_proc_print_page(hocr_print_page);
 static dev_proc_get_params(ocr_get_params);
@@ -55,6 +56,7 @@ ocr_initialize_device_procs(gx_device *dev)
 {
     gdev_prn_initialize_device_procs_gray_bg(dev);

+    set_dev_proc(dev, initialize_device, ocr_initialize_device);
     set_dev_proc(dev, open_device, ocr_open);
     set_dev_proc(dev, close_device, ocr_close);
     set_dev_proc(dev, get_params, ocr_get_params);
@@ -79,6 +81,7 @@ hocr_initialize_device_procs(gx_device *dev)
 {
     gdev_prn_initialize_device_procs_gray_bg(dev);

+    set_dev_proc(dev, initialize_device, ocr_initialize_device);
     set_dev_proc(dev, open_device, ocr_open);
     set_dev_proc(dev, close_device, hocr_close);
     set_dev_proc(dev, get_params, ocr_get_params);
@@ -102,6 +105,17 @@ const gx_device_ocr gs_hocr_device =
 #define HOCR_HEADER "<html>\n <body>\n"
 #define HOCR_TRAILER " </body>\n</html>\n"

+static int
+ocr_initialize_device(gx_device *dev)
+{
+    gx_device_ocr *odev = (gx_device_ocr *)dev;
+    const char *default_ocr_lang = "eng";
+
+    odev->language[0] = '\0';
+    strcpy(odev->language, default_ocr_lang);
+    return 0;
+}
+
 static int
 ocr_open(gx_device *pdev)
 {
@@ -187,7 +201,8 @@ ocr_put_params(gx_device *dev, gs_param_list *plist)

     switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
         case 0:
-            if (pdev->memory->gs_lib_ctx->core->path_control_active) {
+                if (pdev->memory->gs_lib_ctx->core->path_control_active
+                && (strlen(pdev->language) != langstr.size || memcmp(pdev->language, langstr.data, langstr.size) != 0)) {
                 return_error(gs_error_invalidaccess);
             }
             else {
diff --git a/devices/gdevpdfocr.c b/devices/gdevpdfocr.c
index 4c694e3..e4f9862 100644
--- a/devices/gdevpdfocr.c
+++ b/devices/gdevpdfocr.c
@@ -33,9 +33,9 @@
 #include "gdevpdfimg.h"
 #include "tessocr.h"

-int pdf_ocr_open(gx_device *pdev);
-int pdf_ocr_close(gx_device *pdev);
-
+static dev_proc_initialize_device(pdf_ocr_initialize_device);
+static dev_proc_open_device(pdf_ocr_open);
+static dev_proc_close_device(pdf_ocr_close);

 static int
 pdfocr_put_some_params(gx_device * dev, gs_param_list * plist)
@@ -50,7 +50,8 @@ pdfocr_put_some_params(gx_device * dev, gs_param_list * plist)

     switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
         case 0:
-            if (pdf_dev->memory->gs_lib_ctx->core->path_control_active) {
+                if (pdf_dev->memory->gs_lib_ctx->core->path_control_active
+                && (strlen(pdf_dev->ocr.language) != langstr.size || memcmp(pdf_dev->ocr.language, langstr.data, langstr.size) != 0)) {
                 return_error(gs_error_invalidaccess);
             }
             else {
@@ -152,6 +153,8 @@ pdfocr8_initialize_device_procs(gx_device *dev)
 {
     gdev_prn_initialize_device_procs_gray(dev);

+    set_dev_proc(dev, initialize_device, pdf_ocr_initialize_device);
+    set_dev_proc(dev, initialize_device, pdf_ocr_initialize_device);
     set_dev_proc(dev, open_device, pdf_ocr_open);
     set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
     set_dev_proc(dev, close_device, pdf_ocr_close);
@@ -185,6 +188,7 @@ pdfocr24_initialize_device_procs(gx_device *dev)
 {
     gdev_prn_initialize_device_procs_rgb(dev);

+    set_dev_proc(dev, initialize_device, pdf_ocr_initialize_device);
     set_dev_proc(dev, open_device, pdf_ocr_open);
     set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
     set_dev_proc(dev, close_device, pdf_ocr_close);
@@ -216,6 +220,7 @@ pdfocr32_initialize_device_procs(gx_device *dev)
 {
     gdev_prn_initialize_device_procs_cmyk8(dev);

+    set_dev_proc(dev, initialize_device, pdf_ocr_initialize_device);
     set_dev_proc(dev, open_device, pdf_ocr_open);
     set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
     set_dev_proc(dev, close_device, pdf_ocr_close);
@@ -703,7 +708,18 @@ ocr_end_page(gx_device_pdf_image *dev)
     return 0;
 }

-int
+static int
+pdf_ocr_initialize_device(gx_device *dev)
+{
+    gx_device_pdf_image *ppdev = (gx_device_pdf_image *)dev;
+    const char *default_ocr_lang = "eng";
+
+    ppdev->ocr.language[0] = '\0';
+    strcpy(ppdev->ocr.language, default_ocr_lang);
+    return 0;
+}
+
+static int
 pdf_ocr_open(gx_device *pdev)
 {
     gx_device_pdf_image *ppdev;
@@ -726,7 +742,7 @@ pdf_ocr_open(gx_device *pdev)
     return 0;
 }

-int
+static int
 pdf_ocr_close(gx_device *pdev)
 {
     gx_device_pdf_image *pdf_dev;
diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c
index 9ab562c..5caabb8 100644
--- a/devices/vector/gdevpdf.c
+++ b/devices/vector/gdevpdf.c
@@ -206,6 +206,7 @@ device_pdfwrite_finalize(const gs_memory_t *cmem, void *vpdev)
 }

 /* Driver procedures */
+static dev_proc_initialize_device(pdfwrite_initialize_device);
 static dev_proc_open_device(pdf_open);
 static dev_proc_output_page(pdf_output_page);
 static dev_proc_close_device(pdf_close);
@@ -223,6 +224,7 @@ static dev_proc_close_device(pdf_close);
 static void
 pdfwrite_initialize_device_procs(gx_device *dev)
 {
+    set_dev_proc(dev, initialize_device, pdfwrite_initialize_device);
     set_dev_proc(dev, open_device, pdf_open);
     set_dev_proc(dev, get_initial_matrix, gx_upright_get_initial_matrix);
     set_dev_proc(dev, output_page, pdf_output_page);
@@ -766,6 +768,19 @@ pdf_reset_text(gx_device_pdf * pdev)
     pdf_reset_text_state(pdev->text);
 }

+static int
+pdfwrite_initialize_device(gx_device *dev)
+{
+#if OCR_VERSION > 0
+    gx_device_pdf *pdev = (gx_device_pdf *) dev;
+    const char *default_ocr_lang = "eng";
+    pdev->ocr_language[0] = '\0';
+    strcpy(pdev->ocr_language, default_ocr_lang);
+#endif
+    return 0;
+}
+
+
 /* Open the device. */
 static int
 pdf_open(gx_device * dev)
diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c
index 23e9bc8..42a1794 100644
--- a/devices/vector/gdevpdfp.c
+++ b/devices/vector/gdevpdfp.c
@@ -458,7 +458,8 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
         gs_param_string langstr;
         switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
             case 0:
-                if (pdev->memory->gs_lib_ctx->core->path_control_active) {
+                if (pdev->memory->gs_lib_ctx->core->path_control_active
+                && (strlen(pdev->ocr_language) != langstr.size || memcmp(pdev->ocr_language, langstr.data, langstr.size) != 0)) {
                     return_error(gs_error_invalidaccess);
                 }
                 else {
--
2.40.0
