From: Zdenek Hutyra <zhutyra@centrum.cz>
Date: Mon, 27 May 2024 13:38:36 +0100
Subject: Bug 707793: Check for overflow validating format string
Origin: https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=294a3755e33f453dd92e2a7c4cfceb087ac09d6a
Bug: https://bugs.ghostscript.com/show_bug.cgi?id=707793
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2024-46953

for the output file name

CVE-2024-46953
---
 base/gsdevice.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/base/gsdevice.c b/base/gsdevice.c
index 90e699ab45a7..c1eaedd8517c 100644
--- a/base/gsdevice.c
+++ b/base/gsdevice.c
@@ -1070,7 +1070,7 @@ static int
 gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
 {
     bool have_format = false, field;
-    int width[2], int_width = sizeof(int) * 3, w = 0;
+    uint width[2], int_width = sizeof(int) * 3, w = 0;
     uint i;
 
     /* Scan the file name for a format string, and validate it if present. */
@@ -1099,6 +1099,8 @@ gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
                         default: /* width (field = 0) and precision (field = 1) */
                             if (strchr("0123456789", pfn->fname[i])) {
                                 width[field] = width[field] * 10 + pfn->fname[i] - '0';
+                                if (width[field] > max_int)
+	                                return_error(gs_error_undefinedfilename);
                                 continue;
                             } else if (0 == field && '.' == pfn->fname[i]) {
                                 field++;
@@ -1127,8 +1129,10 @@ gx_parse_output_format(gs_parsed_file_name_t *pfn, const char **pfmt)
         /* Calculate a conservative maximum width. */
         w = max(width[0], width[1]);
         w = max(w, int_width) + 5;
+        if (w > max_int)
+            return_error(gs_error_undefinedfilename);
     }
-    return w;
+    return (int)w;
 }
 
 /*
@@ -1181,10 +1185,15 @@ gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
     if (!pfn->fname)
         return 0;
     code = gx_parse_output_format(pfn, pfmt);
-    if (code < 0)
+    if (code < 0) {
         return code;
-    if (strlen(pfn->iodev->dname) + pfn->len + code >= gp_file_name_sizeof)
+    }
+
+    if (pfn->len >= gp_file_name_sizeof - strlen(pfn->iodev->dname) ||
+        code >= gp_file_name_sizeof - strlen(pfn->iodev->dname) - pfn->len) {
         return_error(gs_error_undefinedfilename);
+    }
+
     return 0;
 }
 
-- 
2.45.2

