From 205591753126802da850ada6511a0ff8411aa287 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Thu, 14 Feb 2019 10:20:03 -0800
Subject: [PATCH] Fix bug 700585: Restrict superexec and remove it from
 internals and gs_cet.ps

Also while changing things, restructure the CETMODE so that it will
work with -dSAFER. The gs_cet.ps is now run when we are still at save
level 0 with systemdict writeable. Allows us to undefine .makeoperator
and .setCPSImode internal operators after CETMODE is handled.

Change previous uses of superexec to using .forceput (with the usual
.bind executeonly to hide it).
---
 Resource/Init/gs_cet.ps   | 37 ++++++++++++++-----------------------
 Resource/Init/gs_dps1.ps  |  2 +-
 Resource/Init/gs_fonts.ps |  8 ++++----
 Resource/Init/gs_init.ps  | 38 +++++++++++++++++++++++++++-----------
 Resource/Init/gs_ttf.ps   |  8 ++++----
 Resource/Init/gs_type1.ps |  6 +++---
 6 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/Resource/Init/gs_cet.ps b/Resource/Init/gs_cet.ps
index d47febf..54f17c6 100644
--- a/Resource/Init/gs_cet.ps
+++ b/Resource/Init/gs_cet.ps
@@ -1,28 +1,23 @@
 %!PS
 % Set defaults for Ghostscript to match Adobe CPSI behaviour for CET
 
-% do this in the server level so it is persistent across jobs
-//true 0 startjob not {
-  (*** Warning: CET startup is not in server default) = flush
-} if
+% Note: this must be run at save level 0 and when systemdict is writeable
+currentglobal //true setglobal
+systemdict dup dup dup
+/version (3017.102) readonly .forceput         % match CPSI 3017.102
+/product (PhotoPRINT SE 5.0v2) readonly .forceput      % match CPSI 3017.102
+/revision 0 put                        % match CPSI 3017.103 Tek shows revision 5
+/serialnumber dup {233640} readonly .makeoperator .forceput % match CPSI 3017.102 Tek shows serialnumber 1401788461
+
+systemdict /.odef {           % <name> <proc> odef -
+  1 index exch //.makeoperator def
+} .bind .forceput          % this will be undefined at the end
 
 300 .sethiresscreen	% needed for language switch build since it
                         % processes gs_init.ps BEFORE setting the resolution
 
 0 array 0 setdash % CET 09-08 wants local setdash
 
-currentglobal //true setglobal
-
-{
-  systemdict dup dup dup
-  /version (3017.102) readonly put		% match CPSI 3017.102
-  /product (PhotoPRINT SE 5.0v2) readonly put	% match CPSI 3017.102
-  /revision 0 put			% match CPSI 3017.103 Tek shows revision 5
-  /serialnumber dup {233640} readonly .makeoperator put % match CPSI 3017.102 Tek shows serialnumber 1401788461
-  systemdict /deviceinfo undef                  % for CET 20-23-1
-%  /UNROLLFORMS true put                 % CET files do unreasonable things inside forms
-} 1183615869 internaldict /superexec get exec
-
 /UNROLLFORMS true def
 
 { } bind dup
@@ -106,6 +101,7 @@
   } ifelse
   ofnfa
 } bind def
-% end of slightly nasty hack to give consistent cluster results
 
-//false 0 startjob pop		% re-enter encapsulated mode
+systemdict /.odef .undef
+
+% end of slightly nasty hack to give consistent cluster results
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index 0b0dff3..7cf29b4 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -89,7 +89,7 @@ level2dict begin
                 % definition, copy it into the local directory.
       //systemdict /SharedFontDirectory .knownget
        { 1 index .knownget
-          { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+          { //.FontDirectory 2 index 3 -1 roll .forceput } % readonly
          if
        }
       if
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 541b20c..0ec95eb 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -521,11 +521,11 @@ buildfontdict 3 /.buildfont3 cvx put
                 % the font in LocalFontDirectory.
    .currentglobal
     { //systemdict /LocalFontDirectory .knownget
-       { 2 index 2 index { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse }	% readonly
+       { 2 index 2 index .forceput }	% readonly
       if
     }
    if
-   dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse	% readonly
+   dup //.FontDirectory 4 -2 roll .forceput % readonly
                 % If the font originated as a resource, register it.
    currentfile .currentresourcefile eq { dup .registerfont } if
    readonly
@@ -1193,13 +1193,13 @@ $error /SubstituteFont { } put
           //.FontDirectory 1 index known not {
             2 dict dup /FontName 3 index put
             dup /FontType 1 put
-            //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
+            //.FontDirectory 3 1 roll //.forceput exec % readonly
           } {
             pop
           } ifelse
         } forall
       } forall
-    }
+    } executeonly	% hide .forceput
 FAKEFONTS { exch } if pop def   % don't bind, .current/setglobal get redefined
 
 % Install initial fonts from Fontmap.
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index dce6ed4..bfda301 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2204,9 +2204,6 @@ SAFER { .setsafeglobal } if
   /.endtransparencygroup     % transparency-example.ps
   /.setdotlength             % Bug687720.ps
   /.sort /.setdebug /.mementolistnewblocks /getenv
-
-  /.makeoperator /.setCPSImode              % gs_cet.ps, this won't work on cluster with -dSAFER
-
   /unread
   ]
   {systemdict exch .forceundef} forall
@@ -2296,7 +2293,6 @@ SAFER { .setsafeglobal } if
 
   % Used by our own test suite files
   %/.fileposition %image-qa.ps
-  %/.makeoperator /.setCPSImode % gs_cet.ps
 
   % Either our code uses these in ways which mean they can't be undefined, or they are used directly by
   % test files/utilities, or engineers expressed a desire to keep them visible.
@@ -2476,6 +2472,16 @@ end
 /vmreclaim where
  { pop NOGC not { 2 .vmreclaim 0 vmreclaim } if
  } if
+
+% Do this before systemdict is locked (see below for additional CETMODE setup using gs_cet.ps)
+systemdict /CETMODE .knownget {
+  {
+    (gs_cet.ps) runlibfile
+  } if
+} if
+systemdict /.makeoperator .undef	% must be after gs_cet.ps
+systemdict /.setCPSImode .undef		% must be after gs_cet.ps
+
 DELAYBIND not {
   systemdict /.bindnow .undef       % We only need this for DELAYBIND
   systemdict /.forcecopynew .undef	% remove temptation
@@ -2483,16 +2489,29 @@ DELAYBIND not {
   systemdict /.forceundef .undef	% ditto
 } if
 
-% Move superexec to internaldict if superexec is defined.
-systemdict /superexec .knownget {
-  1183615869 internaldict /superexec 3 -1 roll put
-  systemdict /superexec .undef
+% 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
 } if
+
 WRITESYSTEMDICT {
    SAFER {
        (\n *** WARNING - you have selected SAFER, indicating you want Ghostscript\n) print
diff --git a/Resource/Init/gs_ttf.ps b/Resource/Init/gs_ttf.ps
index 95b5cca..135ce93 100644
--- a/Resource/Init/gs_ttf.ps
+++ b/Resource/Init/gs_ttf.ps
@@ -1301,7 +1301,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef
           TTFDEBUG { (\n1 setting alias: ) print dup ==only
                 ( to be the same as  ) print 2 index //== exec } if
 
-          7 index 2 index 3 -1 roll exch //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+          7 index 2 index 3 -1 roll exch .forceput
         } forall
         pop pop pop
       }
@@ -1319,7 +1319,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef
           exch pop
           TTFDEBUG { (\n2 setting alias: ) print 1 index ==only
                      ( to use glyph index: ) print dup //== exec } if
-          5 index 3 1 roll //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+          5 index 3 1 roll .forceput
           //false
         }
         {
@@ -1336,7 +1336,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef
         {                            %  CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) gindex(integer)
           TTFDEBUG { (\3 nsetting alias: ) print 1 index ==only
                 ( to be index: ) print dup //== exec } if
-          exch pop 5 index 3 1 roll //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+          exch pop 5 index 3 1 roll .forceput
         }
         {
           pop pop
@@ -1486,7 +1486,7 @@
       } ifelse
     ]
   TTFDEBUG { (Encoding: ) print dup === flush } if
-} bind def
+} .bind executeonly odef               % hides .forceput
 
 % to be removed 9.09......
 currentdict /postalias undef
diff --git a/Resource/Init/gs_type1.ps b/Resource/Init/gs_type1.ps
index a680ac1..a03d48e 100644
--- a/Resource/Init/gs_type1.ps
+++ b/Resource/Init/gs_type1.ps
@@ -116,7 +116,7 @@
                  {                                               % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname aglname
                    CFFDEBUG { (\nsetting alias: ) print dup ==only
                          ( to be the same as glyph: ) print 1 index //== exec } if
-                   3 index exch 3 index //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+                   3 index exch 3 index .forceput
                                                                  % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname
                  }
                  {pop} ifelse
@@ -135,7 +135,7 @@
          3 1 roll pop pop
      } if
      pop
-     dup /.AGLprocessed~GS //true //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+     dup /.AGLprocessed~GS //true .forceput
    } if
 
    %% We need to excute the C .buildfont1 in a stopped context so that, if there
@@ -148,7 +148,7 @@
    {//.buildfont1} stopped
    4 3 roll .setglobal
    {//.buildfont1 $error /errorname get signalerror} if
- } bind def
+ } .bind executeonly def	% hide .forceput
 
  % container for CloseSource flag (default //true to prevent buildup of file handles)
  /closesourcedict mark
-- 
2.9.1

