From d683d1e6450d74619e6277efeebfc222d9a5cb91 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.
---
 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 4102d0d..1ca2775 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2563,24 +2563,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 c4110ca..a48d8d8 100644
--- a/psi/icontext.c
+++ b/psi/icontext.c
@@ -151,7 +151,6 @@
     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 ba207cf..b06ba3f 100644
--- a/psi/icstate.h
+++ b/psi/icstate.h
@@ -54,7 +54,6 @@
     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 e95d39b..8f7f6d0 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 33be181..48fcc00 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 43c4bc4..3a5e398 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.9.1

