Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates-src > by-pkgid > 09236aad26217818763c178cc3a83744 > files > 4

ghostscript-9.24-1.5.mga6.src.rpm

From 2b533271d8bd915593a2f8e1a1f446ee940c7d76 Mon Sep 17 00:00:00 2001
From: Robin Watts <robin.watts@artifex.com>
Date: Wed, 5 Sep 2018 18:07:40 +0100
Subject: [PATCH] Fix arg_copy leaks.

When handling -d or -s args, the code currently arg_copies the string
it gets back, then uses that copied block to make postscript names
from.

Here we change the code so that postscript names are made in a
slightly different way, so they copy the string content. This means
we can free the arg_copied block afterwards, solving the leaks.

While we are here, remove a layer of nasty variable hiding macros
that do nothing but confuse things.
---
 psi/iddict.h   |  2 ++
 psi/idict.c    | 17 +++++++++++++++++
 psi/idict.h    |  6 ++++++
 psi/iinit.c    | 42 ++++++++++++++++++++++++++++++------------
 psi/imain.c    |  6 +++---
 psi/imainarg.c | 34 +++++++++++++++++++---------------
 psi/interp.h   |  4 ----
 7 files changed, 77 insertions(+), 34 deletions(-)

diff --git a/psi/iddict.h b/psi/iddict.h
index 67e6b88..53d864b 100644
--- a/psi/iddict.h
+++ b/psi/iddict.h
@@ -29,6 +29,8 @@
   dict_put(pdref, key, pvalue, &idict_stack)
 #define idict_put_string(pdref, kstr, pvalue)\
   dict_put_string(pdref, kstr, pvalue, &idict_stack)
+#define idict_put_string_copy(pdref, kstr, pvalue)\
+  dict_put_string_copy(pdref, kstr, pvalue, &idict_stack)
 #define idict_undef(pdref, key)\
   dict_undef(pdref, key, &idict_stack)
 #define idict_copy(dfrom, dto)\
diff --git a/psi/idict.c b/psi/idict.c
index 978f73d..01d7837 100644
--- a/psi/idict.c
+++ b/psi/idict.c
@@ -555,6 +555,23 @@ dict_put_string(ref * pdref, const char *kstr, const ref * pvalue,
     return dict_put(pdref, &kname, pvalue, pds);
 }
 
+/*
+ * Enter a key-value pair where the key is a C string that must be copied.
+ */
+int
+dict_put_string_copy(ref * pdref, const char *kstr, const ref * pvalue,
+                     dict_stack_t *pds)
+{
+    int code;
+    ref kname;
+    dict *pdict = pdref->value.pdict;
+
+    if ((code = name_ref(dict_mem(pdict),
+                         (const byte *)kstr, strlen(kstr), &kname, 1)) < 0)
+        return code;
+    return dict_put(pdref, &kname, pvalue, pds);
+}
+
 /* Remove an element from a dictionary. */
 int
 dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
diff --git a/psi/idict.h b/psi/idict.h
index 31d3387..c18d4f1 100644
--- a/psi/idict.h
+++ b/psi/idict.h
@@ -125,6 +125,12 @@ int dict_put_string(ref * pdref, const char *kstr, const ref * pvalue,
                     dict_stack_t *pds);
 
 /*
+ * Enter a key-value pair where the key is a (transient) C string.
+ */
+int dict_put_string_copy(ref * pdref, const char *kstr, const ref * pvalue,
+                         dict_stack_t *pds);
+
+/*
  * Remove a key-value pair from a dictionary.
  * Return any of the same values as dict_put, except for 0 and gs_error_dictfull
  * which are converted to gs_error_undefined.
diff --git a/psi/iinit.c b/psi/iinit.c
index 3c4ccdc..1e2c46d 100644
--- a/psi/iinit.c
+++ b/psi/iinit.c
@@ -105,6 +105,24 @@ i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref)
     return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref);
 }
 
+/* Enter a name and value into a dictionary. */
+static int
+i_initial_enter_name_copy_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr,
+                             const ref * pref)
+{
+    int code = idict_put_string_copy(pdict, nstr, pref);
+
+    if (code < 0)
+        lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n",
+                 code, nstr, dict_length(pdict), dict_maxlength(pdict));
+    return code;
+}
+int
+i_initial_enter_name_copy(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref)
+{
+    return i_initial_enter_name_copy_in(i_ctx_p, systemdict, nstr, pref);
+}
+
 /* Remove a name from systemdict. */
 void
 i_initial_remove_name(i_ctx_t *i_ctx_p, const char *nstr)
@@ -297,7 +315,7 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
         }
 
         /* Enter names of referenced initial dictionaries into systemdict. */
-        initial_enter_name("systemdict", systemdict);
+        i_initial_enter_name(i_ctx_p, "systemdict", systemdict);
         for (i = 0; i < icount; i++) {
             ref *idict = &idicts[i];
 
@@ -314,8 +332,8 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
                 uint save_space = r_space(systemdict);
 
                 r_set_space(systemdict, avm_local);
-                code = initial_enter_name(initial_dictionaries[i].name,
-                                          idict);
+                code = i_initial_enter_name(i_ctx_p, initial_dictionaries[i].name,
+                                            idict);
                 r_set_space(systemdict, save_space);
                 if (code < 0)
                     return code;
@@ -336,9 +354,9 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
         make_null(&vnull);
         make_true(&vtrue);
         make_false(&vfalse);
-        if ((code = initial_enter_name("null", &vnull)) < 0 ||
-            (code = initial_enter_name("true", &vtrue)) < 0 ||
-            (code = initial_enter_name("false", &vfalse)) < 0
+        if ((code = i_initial_enter_name(i_ctx_p, "null", &vnull)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "true", &vtrue)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "false", &vfalse)) < 0
             )
             return code;
     }
@@ -356,7 +374,7 @@ obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
           if ((code = name_enter_string(imemory, (const char *)gs_error_names[i],
                                           era.value.refs + i)) < 0)
                 return code;
-        return initial_enter_name("ErrorNames", &era);
+        return i_initial_enter_name(i_ctx_p, "ErrorNames", &era);
     }
 }
 
@@ -398,11 +416,11 @@ zop_init(i_ctx_t *i_ctx_p)
                           (const byte *)gs_productfamily);
         make_int(&vre, gs_revision);
         make_int(&vrd, gs_revisiondate);
-        if ((code = initial_enter_name("copyright", &vcr)) < 0 ||
-            (code = initial_enter_name("product", &vpr)) < 0 ||
-            (code = initial_enter_name("productfamily", &vpf)) < 0 ||
-            (code = initial_enter_name("revision", &vre)) < 0 ||
-            (code = initial_enter_name("revisiondate", &vrd)) < 0)
+        if ((code = i_initial_enter_name(i_ctx_p, "copyright", &vcr)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "product", &vpr)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "productfamily", &vpf)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "revision", &vre)) < 0 ||
+            (code = i_initial_enter_name(i_ctx_p, "revisiondate", &vrd)) < 0)
             return code;
     }
 
diff --git a/psi/imain.c b/psi/imain.c
index 138bfc8..9fc72bb 100644
--- a/psi/imain.c
+++ b/psi/imain.c
@@ -264,18 +264,18 @@ int gs_main_init2aux(gs_main_instance * minst) {
 
         /* Set up the array of additional initialization files. */
         make_const_string(&ifa, a_readonly | avm_foreign, gs_init_files_sizeof - 2, gs_init_files);
-        code = initial_enter_name("INITFILES", &ifa);
+        code = i_initial_enter_name(i_ctx_p, "INITFILES", &ifa);
         if (code < 0)
             return code;
 
         /* Set up the array of emulator names. */
         make_const_string(&ifa, a_readonly | avm_foreign, gs_emulators_sizeof - 2, gs_emulators);
-        code = initial_enter_name("EMULATORS", &ifa);
+        code = i_initial_enter_name(i_ctx_p, "EMULATORS", &ifa);
         if (code < 0)
             return code;
 
         /* Pass the search path. */
-        code = initial_enter_name("LIBPATH", &minst->lib_path.list);
+        code = i_initial_enter_name(i_ctx_p, "LIBPATH", &minst->lib_path.list);
         if (code < 0)
             return code;
 
diff --git a/psi/imainarg.c b/psi/imainarg.c
index fb16f4b..9cd62c8 100644
--- a/psi/imainarg.c
+++ b/psi/imainarg.c
@@ -312,9 +312,6 @@ swproc(gs_main_instance * minst, const char *arg, arg_list * pal)
     char sw = arg[1];
     ref vtrue;
     int code = 0;
-#undef initial_enter_name
-#define initial_enter_name(nstr, pvalue)\
-  i_initial_enter_name(minst->i_ctx_p, nstr, pvalue)
 
     make_true(&vtrue);
     arg += 2;                   /* skip - and letter */
@@ -603,10 +600,10 @@ run_stdin:
                     return gs_error_Fatal;
                 }
                 make_int(&value, width);
-                initial_enter_name("DEVICEWIDTH", &value);
+                i_initial_enter_name(minst->i_ctx_p, "DEVICEWIDTH", &value);
                 make_int(&value, height);
-                initial_enter_name("DEVICEHEIGHT", &value);
-                initial_enter_name("FIXEDMEDIA", &vtrue);
+                i_initial_enter_name(minst->i_ctx_p, "DEVICEHEIGHT", &value);
+                i_initial_enter_name(minst->i_ctx_p, "FIXEDMEDIA", &vtrue);
                 break;
             }
         case 'h':               /* print help */
@@ -705,9 +702,9 @@ run_stdin:
                 memcpy(str, adef, len);
                 make_const_string(&value, a_readonly | avm_system, len, str);
                 ialloc_set_space(idmemory, space);
-                initial_enter_name("OutputFile", &value);
-                initial_enter_name("NOPAUSE", &vtrue);
-                initial_enter_name("BATCH", &vtrue);
+                i_initial_enter_name(minst->i_ctx_p, "OutputFile", &value);
+                i_initial_enter_name(minst->i_ctx_p, "NOPAUSE", &vtrue);
+                i_initial_enter_name(minst->i_ctx_p, "BATCH", &vtrue);
             }
             break;
         case 'P':               /* choose whether search '.' first */
@@ -723,7 +720,7 @@ run_stdin:
         case 'q':               /* quiet startup */
             if ((code = gs_main_init1(minst)) < 0)
                 return code;
-            initial_enter_name("QUIET", &vtrue);
+            i_initial_enter_name(minst->i_ctx_p, "QUIET", &vtrue);
             break;
         case 'r':               /* define device resolution */
             {
@@ -741,10 +738,10 @@ run_stdin:
                         /* fall through */
                     case 2:     /* -r<xres>x<yres> */
                         make_real(&value, xres);
-                        initial_enter_name("DEVICEXRESOLUTION", &value);
+                        i_initial_enter_name(minst->i_ctx_p, "DEVICEXRESOLUTION", &value);
                         make_real(&value, yres);
-                        initial_enter_name("DEVICEYRESOLUTION", &value);
-                        initial_enter_name("FIXEDRESOLUTION", &vtrue);
+                        i_initial_enter_name(minst->i_ctx_p, "DEVICEYRESOLUTION", &value);
+                        i_initial_enter_name(minst->i_ctx_p, "FIXEDRESOLUTION", &vtrue);
                 }
                 break;
             }
@@ -772,6 +769,7 @@ run_stdin:
                 }
                 if (eqp == adef) {
                     puts(minst->heap, "Usage: -dNAME, -dNAME=TOKEN, -sNAME=STRING");
+                    arg_free((char *)adef, minst->heap);
                     return gs_error_Fatal;
                 }
                 if (eqp == NULL) {
@@ -828,6 +826,7 @@ run_stdin:
                             code = gs_scan_token(minst->i_ctx_p, &value, &state);
                             if (code) {
                                 outprintf(minst->heap, "Invalid value for option -d%s, -dNAME= must be followed by a valid token\n", arg);
+                                arg_free((char *)adef, minst->heap);
                                 return gs_error_Fatal;
                             }
                             if (r_has_type_attrs(&value, t_name,
@@ -847,6 +846,7 @@ run_stdin:
                                     make_false(&value);
                                 else {
                                     outprintf(minst->heap, "Invalid value for option -d%s, use -sNAME= to define string constants\n", arg);
+                                    arg_free((char *)adef, minst->heap);
                                     return gs_error_Fatal;
                                 }
                             }
@@ -857,17 +857,21 @@ run_stdin:
 
                         if (body == NULL) {
                             lprintf("Out of memory!\n");
+                            arg_free((char *)adef, minst->heap);
                             return gs_error_Fatal;
                         }
                         memcpy(body, eqp, len);
                         make_const_string(&value, a_readonly | avm_system, len, body);
-                        if ((code = try_stdout_redirect(minst, adef, eqp)) < 0)
+                        if ((code = try_stdout_redirect(minst, adef, eqp)) < 0) {
+                            arg_free((char *)adef, minst->heap);
                             return code;
+                        }
                     }
                     ialloc_set_space(idmemory, space);
                 }
                 /* Enter the name in systemdict. */
-                initial_enter_name(adef, &value);
+                i_initial_enter_name_copy(minst->i_ctx_p, adef, &value);
+                arg_free((char *)adef, minst->heap);
                 break;
             }
         case 'u':               /* undefine name */
diff --git a/psi/interp.h b/psi/interp.h
index 10c037a..5e5ca58 100644
--- a/psi/interp.h
+++ b/psi/interp.h
@@ -23,13 +23,9 @@
 
 /* Enter a name and value into systemdict. */
 int i_initial_enter_name(i_ctx_t *, const char *, const ref *);
-#define initial_enter_name(nstr, pvalue)\
-  i_initial_enter_name(i_ctx_p, nstr, pvalue)
 
 /* Remove a name from systemdict. */
 void i_initial_remove_name(i_ctx_t *, const char *);
-#define initial_remove_name(nstr)\
-  i_initial_remove_name(i_ctx_p, nstr)
 
 /* ------ interp.c ------ */
 
-- 
2.9.1