From 5845e667dda3c945ee793fbe6af021533cb4fbec Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Sun, 24 Feb 2019 22:01:04 -0800
Subject: [PATCH] Bug 700585: Obliterate "superexec". We don't need it, nor
 do any known apps.

We were under the impression that the Windows driver 'PScript5.dll' used
superexec, but after testing with our extensive suite of PostScript file,
and analysis of the PScript5 "Adobe CoolType ProcSet, it does not appear
that this operator is needed anymore. Get rid of superexec and all of the
references to it, since it is a potential security hole.

CVE: CVE-2019-3835
Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git]

Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
---
 Resource/Init/gs_init.ps | 18 ------------------
 psi/icontext.c           |  1 -
 psi/icstate.h            |  1 -
 psi/zcontrol.c           | 30 ------------------------------
 psi/zdict.c              |  6 ++----
 psi/zgeneric.c           |  3 +--
 6 files changed, 3 insertions(+), 56 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 0d5c4f7..c5ac82a 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2470,24 +2470,6 @@ DELAYBIND not {
   systemdict /.forceundef .undef	% ditto
 } if
 
-% Move superexec to internaldict if superexec is defined. (Level 2 or later)
-systemdict /superexec known {
-  % restrict superexec to single known use by PScript5.dll
-  % We could do this only for SAFER mode, but internaldict and superexec are
-  % not very well documented, and we don't want them to be used.
-  1183615869 internaldict /superexec {
-    2 index /Private eq		% first check for typical use in PScript5.dll
-    1 index length 1 eq and	% expected usage is: dict /Private <value> {put} superexec
-    1 index 0 get systemdict /put get eq and
-    {
-      //superexec exec		% the only usage we allow
-    } {
-      /superexec load /invalidaccess signalerror
-    } ifelse
-  } bind cvx executeonly put
-  systemdict /superexec .undef	% get rid of the dangerous (unrestricted) operator
-} if
-
 % Can't remove this one until the last minute :-)
 DELAYBIND not {
 systemdict /.undef .undef
diff --git a/psi/icontext.c b/psi/icontext.c
index 1fbe486..7462ea3 100644
--- a/psi/icontext.c
+++ b/psi/icontext.c
@@ -151,7 +151,6 @@ context_state_alloc(gs_context_state_t ** ppcst,
     pcst->rand_state = rand_state_initial;
     pcst->usertime_total = 0;
     pcst->keep_usertime = false;
-    pcst->in_superexec = 0;
     pcst->plugin_list = 0;
     make_t(&pcst->error_object, t__invalid);
     {	/*
diff --git a/psi/icstate.h b/psi/icstate.h
index 4c6a14d..1009d85 100644
--- a/psi/icstate.h
+++ b/psi/icstate.h
@@ -54,7 +54,6 @@ struct gs_context_state_s {
     long usertime_total;	/* total accumulated usertime, */
                                 /* not counting current time if running */
     bool keep_usertime;		/* true if context ever executed usertime */
-    int in_superexec;		/* # of levels of superexec */
     /* View clipping is handled in the graphics state. */
     ref error_object;		/* t__invalid or error object from operator */
     ref userparams;		/* t_dictionary */
diff --git a/psi/zcontrol.c b/psi/zcontrol.c
index 0362cf4..dc813e8 100644
--- a/psi/zcontrol.c
+++ b/psi/zcontrol.c
@@ -158,34 +158,6 @@ zexecn(i_ctx_t *i_ctx_p)
     return o_push_estack;
 }
 
-/* <obj> superexec - */
-static int end_superexec(i_ctx_t *);
-static int
-zsuperexec(i_ctx_t *i_ctx_p)
-{
-    os_ptr op = osp;
-    es_ptr ep;
-
-    check_op(1);
-    if (!r_has_attr(op, a_executable))
-        return 0;		/* literal object just gets pushed back */
-    check_estack(2);
-    ep = esp += 3;
-    make_mark_estack(ep - 2, es_other, end_superexec); /* error case */
-    make_op_estack(ep - 1,  end_superexec); /* normal case */
-    ref_assign(ep, op);
-    esfile_check_cache();
-    pop(1);
-    i_ctx_p->in_superexec++;
-    return o_push_estack;
-}
-static int
-end_superexec(i_ctx_t *i_ctx_p)
-{
-    i_ctx_p->in_superexec--;
-    return 0;
-}
-
 /* <array> <executable> .runandhide <obj>				*/
 /* 	before executing  <executable>, <array> is been removed from	*/
 /*	the operand stack and placed on the execstack with attributes	*/
@@ -971,8 +943,6 @@ const op_def zcontrol3_op_defs[] = {
     {"0%loop_continue", loop_continue},
     {"0%repeat_continue", repeat_continue},
     {"0%stopped_push", stopped_push},
-    {"1superexec", zsuperexec},
-    {"0%end_superexec", end_superexec},
     {"2.runandhide", zrunandhide},
     {"0%end_runandhide", end_runandhide},
     op_def_end(0)
diff --git a/psi/zdict.c b/psi/zdict.c
index b0deaaa..e2e525d 100644
--- a/psi/zdict.c
+++ b/psi/zdict.c
@@ -212,8 +212,7 @@ zundef(i_ctx_t *i_ctx_p)
     int code;
 
     check_type(*op1, t_dictionary);
-    if (i_ctx_p->in_superexec == 0)
-        check_dict_write(*op1);
+    check_dict_write(*op1);
     code = idict_undef(op1, op);
     if (code < 0 && code != gs_error_undefined) /* ignore undefined error */
         return code;
@@ -504,8 +503,7 @@ zsetmaxlength(i_ctx_t *i_ctx_p)
     int code;
 
     check_type(*op1, t_dictionary);
-    if (i_ctx_p->in_superexec == 0)
-        check_dict_write(*op1);
+    check_dict_write(*op1);
     check_type(*op, t_integer);
     if (op->value.intval < 0)
         return_error(gs_error_rangecheck);
diff --git a/psi/zgeneric.c b/psi/zgeneric.c
index 8048e28..d4edddb 100644
--- a/psi/zgeneric.c
+++ b/psi/zgeneric.c
@@ -204,8 +204,7 @@ zput(i_ctx_t *i_ctx_p)
 
     switch (r_type(op2)) {
         case t_dictionary:
-            if (i_ctx_p->in_superexec == 0)
-                check_dict_write(*op2);
+            check_dict_write(*op2);
             {
                 int code = idict_put(op2, op1, op);
 
-- 
2.18.1

