Blame SOURCES/ghostscript-cve-2019-6116.patch

5e8686
From 30cd347f37bfb293ffdc407397d1023628400b81 Mon Sep 17 00:00:00 2001
5e8686
From: Ken Sharp <ken.sharp@artifex.com>
5e8686
Date: Mon, 15 Oct 2018 13:35:15 +0100
5e8686
Subject: [PATCH 1/6] font parsing - prevent SEGV in .cffparse
5e8686
5e8686
Bug #699961 "currentcolortransfer procs crash .parsecff"
5e8686
5e8686
zparsecff checked the operand for being an array (and not a packed
5e8686
array) but the returned procedures from the default currentcolortransfer
5e8686
are arrays, not packed arrays. This led to the code trying to
5e8686
dereference a NULL pointer.
5e8686
5e8686
Add a specific check for the 'refs' pointer being NULL before we try
5e8686
to use it.
5e8686
5e8686
Additionally, make the StartData procedure in the CFF Font Resource
5e8686
executeonly to prevent pulling the hidden .parsecff operator out and
5e8686
using it. Finally, extend this to other resource types.
5e8686
---
5e8686
 Resource/Init/gs_cff.ps   |  4 +--
5e8686
 Resource/Init/gs_cidcm.ps |  6 ++--
5e8686
 Resource/Init/gs_ciddc.ps |  4 +--
5e8686
 Resource/Init/gs_cmap.ps  |  2 +-
5e8686
 Resource/Init/gs_res.ps   | 60 +++++++++++++++++++--------------------
5e8686
 psi/zfont2.c              |  4 +++
5e8686
 6 files changed, 42 insertions(+), 38 deletions(-)
5e8686
5e8686
diff --git a/Resource/Init/gs_cff.ps b/Resource/Init/gs_cff.ps
5e8686
index 20c35a5..b60e374 100644
5e8686
--- a/Resource/Init/gs_cff.ps
5e8686
+++ b/Resource/Init/gs_cff.ps
5e8686
@@ -199,7 +199,7 @@ def
5e8686
 % ordinary CFF font.
5e8686
 /StartData {          % <resname> <nbytes> StartData -
5e8686
   currentfile exch subfilefilter //false //false ReadData pop
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 /ReadData {           % <resname> <file> <forceresname> <forcecid> ReadData <fontset>
5e8686
         % Initialize.
5e8686
 
5e8686
@@ -234,7 +234,7 @@ def
5e8686
   end		% FontSetInit ProcSet
5e8686
   /FontSet defineresource
5e8686
 
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 
5e8686
 % ---------------- Resource category definition ---------------- %
5e8686
 
5e8686
diff --git a/Resource/Init/gs_cidcm.ps b/Resource/Init/gs_cidcm.ps
5e8686
index 0201ea8..60b0fdb 100644
5e8686
--- a/Resource/Init/gs_cidcm.ps
5e8686
+++ b/Resource/Init/gs_cidcm.ps
5e8686
@@ -327,7 +327,7 @@ currentdict end def
5e8686
       //FindResource exec
5e8686
     } ifelse
5e8686
   } ifelse
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 
5e8686
 /ResourceStatus {  % <InstName> ResourceStatus <nStatus> <nSize> true
5e8686
                    % <InstName> ResourceStatus false
5e8686
@@ -359,7 +359,7 @@ currentdict end def
5e8686
       //false
5e8686
     } ifelse
5e8686
   } ifelse
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 
5e8686
 /ResourceForAll { % <template> <proc> <scratch> ResourceForAll -
5e8686
 
5e8686
@@ -440,7 +440,7 @@ currentdict end def
5e8686
 
5e8686
   % Make the enumerator and apply it :
5e8686
   /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 
5e8686
 currentdict end /Font exch /Category defineresource pop
5e8686
 end
5e8686
diff --git a/Resource/Init/gs_ciddc.ps b/Resource/Init/gs_ciddc.ps
5e8686
index 54c6876..f83e960 100644
5e8686
--- a/Resource/Init/gs_ciddc.ps
5e8686
+++ b/Resource/Init/gs_ciddc.ps
5e8686
@@ -204,7 +204,7 @@ begin
5e8686
     exch pop begin                                   %
5e8686
     .GetCIDDecoding
5e8686
     end
5e8686
-  } bind def
5e8686
+  } bind executeonly def
5e8686
 
5e8686
   /FindResource      % <name> FindResource <dict>
5e8686
   { currentglobal exch                               % bGlobal /InstName
5e8686
@@ -212,7 +212,7 @@ begin
5e8686
     dup //.MakeInstance exec                         % bGlobal /InstName <Inst>
5e8686
     DefineResource                                   % bGlobal <Inst>
5e8686
     exch setglobal                                   % <Inst>
5e8686
-  } bind def
5e8686
+  } bind executeonly def
5e8686
 
5e8686
 currentdict end
5e8686
 /CIDDecoding exch /Category defineresource pop
5e8686
diff --git a/Resource/Init/gs_cmap.ps b/Resource/Init/gs_cmap.ps
5e8686
index 63c023b..a01afc2 100644
5e8686
--- a/Resource/Init/gs_cmap.ps
5e8686
+++ b/Resource/Init/gs_cmap.ps
5e8686
@@ -536,7 +536,7 @@ dup /DefineResource {
5e8686
   } if
5e8686
   dup /CodeMap .knownget { //null eq { .buildcmap } if } if
5e8686
   /Generic /Category findresource /DefineResource get exec
5e8686
-} bind put
5e8686
+} bind executeonly put
5e8686
 /Category defineresource pop
5e8686
         % We might have loaded CID font support already.
5e8686
 /CIDInit /ProcSet 2 copy { findresource } .internalstopped
5e8686
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
5e8686
index d1e10c9..9bdb8ff 100644
5e8686
--- a/Resource/Init/gs_res.ps
5e8686
+++ b/Resource/Init/gs_res.ps
5e8686
@@ -155,10 +155,10 @@ setglobal
5e8686
         } {
5e8686
           /defineresource cvx /typecheck signaloperror
5e8686
         } ifelse
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 /FindResource		% (redefined below)
5e8686
         { .Instances exch get 0 get
5e8686
-        } bind def
5e8686
+        } bind executeonly def
5e8686
 
5e8686
                 % Additional entries
5e8686
 
5e8686
@@ -210,7 +210,7 @@ def
5e8686
       /findresource .systemvar /typecheck signalerror
5e8686
     } if
5e8686
     /findresource cvx //.findresource .errorexec
5e8686
-} odef
5e8686
+} bind executeonly odef
5e8686
 
5e8686
 /defineresource {	% <key> <instance> <category> defineresource <instance>
5e8686
     2 .argindex 2 index 2 index	% catch stackunderflow
5e8686
@@ -226,7 +226,7 @@ def
5e8686
         /DefineResource .resourceexec
5e8686
         4 1 roll pop pop pop
5e8686
     } .errorexec
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 % We must prevent resourceforall from automatically restoring the stacks,
5e8686
 % because we don't want the stacks restored if proc causes an error or
5e8686
 % executes a 'stop'. On the other hand, resourceforall is defined in the
5e8686
@@ -240,10 +240,10 @@ def
5e8686
         % Stack: <template> <proc> <scratch> <category> proc
5e8686
         exch pop		% pop the category
5e8686
         exec end
5e8686
-} bind def
5e8686
+} bind executeonly def
5e8686
 /resourceforall {	% <template> <proc> <scratch> <category> resourceforall1 -
5e8686
         //resourceforall1 exec		% see above
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 /resourcestatus {	% <key> <category> resourcestatus <status> <size> true
5e8686
                         % <key> <category> resourcestatus false
5e8686
   {
5e8686
@@ -259,7 +259,7 @@ def
5e8686
     % for error reporting. CET 23-26
5e8686
     /resourcestatus cvx $error /errorname get signalerror
5e8686
   } if
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 /undefineresource {	% <key> <category> undefineresource -
5e8686
   0 .argindex type /nametype ne {
5e8686
     /undefinedresource cvx /typecheck signaloperror
5e8686
@@ -272,7 +272,7 @@ def
5e8686
     % here but uses operator for the errors above. CET 23-33
5e8686
     /undefineresource cvx $error /errorname get signalerror
5e8686
   } if
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 
5e8686
 % Define the system parameters used for the Generic implementation of
5e8686
 % ResourceFileName.
5e8686
@@ -457,7 +457,7 @@ status {
5e8686
            { 2 copy .Instances exch exec
5e8686
            }
5e8686
           if .LocalInstances exch exec
5e8686
-        } bind
5e8686
+        } bind executeonly
5e8686
 % Because of some badly designed code in Adobe's CID font downloader that
5e8686
 % makes findresource and resourcestatus deliberately inconsistent with each
5e8686
 % other, the default FindResource must not call ResourceStatus if there is
5e8686
@@ -483,7 +483,7 @@ status {
5e8686
            /findresource cvx .undefinedresource
5e8686
           } ifelse
5e8686
         } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 % Because of some badly designed code in Adobe's CID font downloader, the
5e8686
 % definition of ResourceStatus for Generic and Font must be the same (!).
5e8686
 % We patch around this by using an intermediate .ResourceFileStatus procedure.
5e8686
@@ -493,10 +493,10 @@ status {
5e8686
         } {
5e8686
           .ResourceFileStatus
5e8686
         } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 /.ResourceFileStatus {
5e8686
         .ResourceFile { closefile 2 -1 //true } { pop //false } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 /ResourceForAll {
5e8686
                 % Construct a new procedure to hold the arguments.
5e8686
                 % All objects constructed here must be in local VM to avoid
5e8686
@@ -554,7 +554,7 @@ status {
5e8686
         3 2 roll pop % args
5e8686
         { forall } 0 get
5e8686
         currentdict end 2 .execn begin
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 
5e8686
 /ResourceFileName  {                          % /in (scr) --> (p/c/n)
5e8686
   exch //.rfnstring cvs                       % (scr) (n)
5e8686
@@ -586,7 +586,7 @@ status {
5e8686
     ifelse
5e8686
   } ifelse
5e8686
   exch copy                                   % (p/c/n)
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 
5e8686
                 % Additional entries
5e8686
 
5e8686
@@ -752,17 +752,17 @@ counttomark 2 idiv
5e8686
              ifelse
5e8686
            }
5e8686
           ifelse
5e8686
-        } bind
5e8686
+        } bind executeonly
5e8686
    /UndefineResource
5e8686
-        { /undefineresource cvx /invalidaccess signaloperror } bind
5e8686
+        { /undefineresource cvx /invalidaccess signaloperror } bind executeonly
5e8686
    /FindResource
5e8686
         { .Instances 1 index .knownget
5e8686
            { exch pop }
5e8686
            { /findresource cvx .undefinedresource }
5e8686
           ifelse
5e8686
-        } bind
5e8686
+        } bind executeonly
5e8686
    /ResourceStatus
5e8686
-        { .Instances exch known { 0 0 //true } { //false } ifelse } bind
5e8686
+        { .Instances exch known { 0 0 //true } { //false } ifelse } bind executeonly
5e8686
    /ResourceForAll
5e8686
         /Generic .findcategory /ResourceForAll load end
5e8686
 
5e8686
@@ -865,7 +865,7 @@ userdict /.localcsdefaults //false put
5e8686
     1 index .definedefaultcs
5e8686
     currentglobal not { .userdict /.localcsdefaults //true put } if
5e8686
   } if
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 
5e8686
 /UndefineResource {
5e8686
   dup /Generic /Category findresource /UndefineResource get exec
5e8686
@@ -888,7 +888,7 @@ userdict /.localcsdefaults //false put
5e8686
   } {
5e8686
     pop
5e8686
   } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 
5e8686
 .definecategory			% ColorSpace
5e8686
 
5e8686
@@ -918,7 +918,7 @@ userdict /.localcsdefaults //false put
5e8686
     { exch copy exch pop }
5e8686
     { /Generic /Category findresource /ResourceFileName get exec }
5e8686
    ifelse
5e8686
- } bind
5e8686
+ } bind executeonly
5e8686
 
5e8686
 .definecategory			% Encoding
5e8686
 
5e8686
@@ -991,11 +991,11 @@ currentdict /.fontstatusaux .undef
5e8686
 /DefineResource
5e8686
         { 2 copy //definefont exch pop
5e8686
           /Generic /Category findresource /DefineResource get exec
5e8686
-        } bind
5e8686
+        } bind executeonly
5e8686
 /UndefineResource
5e8686
         { dup //undefinefont
5e8686
           /Generic /Category findresource /UndefineResource get exec
5e8686
-        } bind
5e8686
+        } bind executeonly
5e8686
 /FindResource {
5e8686
         dup .getvminstance {
5e8686
           exch pop 0 get
5e8686
@@ -1006,14 +1006,14 @@ currentdict /.fontstatusaux .undef
5e8686
             .loadfontresource
5e8686
           } ifelse
5e8686
         } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 /ResourceForAll {
5e8686
         { .scannextfontdir not { exit } if } loop
5e8686
         /Generic /Category findresource /ResourceForAll get exec
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 /.ResourceFileStatus {
5e8686
         .fontstatus { pop 2 -1 //true } { pop //false } ifelse
5e8686
-} bind
5e8686
+} bind executeonly
5e8686
 
5e8686
 /.loadfontresource {
5e8686
         dup .vmused exch
5e8686
@@ -1063,20 +1063,20 @@ end
5e8686
   { /Font defineresource } stopped {
5e8686
       /definefont cvx $error /errorname get signalerror
5e8686
   } if
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 /undefinefont {
5e8686
   /Font undefineresource
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 % The Red Book requires that findfont be a procedure, not an operator,
5e8686
 % but it still needs to restore the stacks reliably if it fails.
5e8686
 /.findfontop {
5e8686
   { /Font findresource } stopped {
5e8686
     pop /findfont $error /errorname get signalerror
5e8686
   } if
5e8686
-} bind odef
5e8686
+} bind executeonly odef
5e8686
 /findfont {
5e8686
   .findfontop
5e8686
-} bind def	% Must be a procedure, not an operator
5e8686
+} bind executeonly def	% Must be a procedure, not an operator
5e8686
 
5e8686
 % Remove initialization utilities.
5e8686
 currentdict /.definecategory .undef
5e8686
diff --git a/psi/zfont2.c b/psi/zfont2.c
5e8686
index bed6c81..3123f19 100644
5e8686
--- a/psi/zfont2.c
5e8686
+++ b/psi/zfont2.c
5e8686
@@ -2745,9 +2745,13 @@ zparsecff(i_ctx_t *i_ctx_p)
5e8686
     ref blk_wrap[1];
5e8686
 
5e8686
     check_read(*op);
5e8686
+
5e8686
     if (r_has_type(op, t_array)) {  /* no packedarrays */
5e8686
         int i, blk_sz, blk_cnt;
5e8686
 
5e8686
+        if (op->value.refs == NULL)
5e8686
+            return_error(gs_error_typecheck);
5e8686
+
5e8686
         data.blk_ref = op->value.refs;
5e8686
         blk_cnt  = r_size(op);
5e8686
         blk_sz = r_size(data.blk_ref);
5e8686
-- 
5e8686
2.17.2
5e8686
5e8686
5e8686
From 8e18fcdaa2e2247363c4cc8f851f3096cc5756fa Mon Sep 17 00:00:00 2001
5e8686
From: Chris Liddell <chris.liddell@artifex.com>
5e8686
Date: Fri, 19 Oct 2018 13:14:24 +0100
5e8686
Subject: [PATCH 2/6] "Hide" a final use of a .force* operator
5e8686
5e8686
There was one use of .forceput remaining that was in a regular procedure
5e8686
rather than being "hidden" behind an operator.
5e8686
5e8686
In this case, it's buried in the resource machinery, and hard to access (I
5e8686
would not be confident in claiming it was impossible). This ensures it's
5e8686
not accessible.
5e8686
---
5e8686
 Resource/Init/gs_res.ps | 6 +++---
5e8686
 1 file changed, 3 insertions(+), 3 deletions(-)
5e8686
5e8686
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
5e8686
index 9bdb8ff..8eb8bb0 100644
5e8686
--- a/Resource/Init/gs_res.ps
5e8686
+++ b/Resource/Init/gs_res.ps
5e8686
@@ -155,7 +155,7 @@ setglobal
5e8686
         } {
5e8686
           /defineresource cvx /typecheck signaloperror
5e8686
         } ifelse
5e8686
-} bind executeonly def
5e8686
+} bind executeonly odef
5e8686
 /FindResource		% (redefined below)
5e8686
         { .Instances exch get 0 get
5e8686
         } bind executeonly def
5e8686
@@ -412,7 +412,7 @@ status {
5e8686
   } ifelse
5e8686
 } bind def
5e8686
 
5e8686
-/DefineResource {
5e8686
+/DefineResource dup {
5e8686
         .CheckResource
5e8686
            { dup [ exch 0 -1 ]
5e8686
                         % Stack: key value instance
5e8686
@@ -441,7 +441,7 @@ status {
5e8686
            { /defineresource cvx /typecheck signaloperror
5e8686
            }
5e8686
         ifelse
5e8686
-} .bind executeonly		% executeonly to prevent access to .forcedef
5e8686
+} .bind executeonly .makeoperator		% executeonly to prevent access to .forcedef
5e8686
 /UndefineResource
5e8686
         {  { dup 2 index .knownget
5e8686
               { dup 1 get 1 ge
5e8686
-- 
5e8686
2.17.2
5e8686
5e8686
5e8686
From 13b0a36f8181db66a91bcc8cea139998b53a8996 Mon Sep 17 00:00:00 2001
5e8686
From: Chris Liddell <chris.liddell@artifex.com>
5e8686
Date: Wed, 5 Dec 2018 12:22:13 +0000
5e8686
Subject: [PATCH 3/6] Sanitize op stack for error conditions
5e8686
5e8686
We save the stacks to an array and store the array for the error handler to
5e8686
access.
5e8686
5e8686
For SAFER, we traverse the array, and deep copy any op arrays (procedures). As
5e8686
we make these copies, we check for operators that do *not* exist in systemdict,
5e8686
when we find one, we replace the operator with a name object (of the form
5e8686
"/--opname--").
5e8686
---
5e8686
 psi/int.mak  |  3 +-
5e8686
 psi/interp.c |  8 ++++++
5e8686
 psi/istack.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
5e8686
 psi/istack.h |  3 ++
5e8686
 4 files changed, 91 insertions(+), 1 deletion(-)
5e8686
5e8686
diff --git a/psi/int.mak b/psi/int.mak
5e8686
index 6ab5bf0..6b349cb 100644
5e8686
--- a/psi/int.mak
5e8686
+++ b/psi/int.mak
5e8686
@@ -204,7 +204,8 @@ $(PSOBJ)iparam.$(OBJ) : $(PSSRC)iparam.c $(GH)\
5e8686
 $(PSOBJ)istack.$(OBJ) : $(PSSRC)istack.c $(GH) $(memory__h)\
5e8686
  $(ierrors_h) $(gsstruct_h) $(gsutil_h)\
5e8686
  $(ialloc_h) $(istack_h) $(istkparm_h) $(istruct_h) $(iutil_h) $(ivmspace_h)\
5e8686
- $(store_h) $(INT_MAK) $(MAKEDIRS)
5e8686
+ $(store_h) $(icstate_h) $(iname_h) $(dstack_h) $(idict_h) \
5e8686
+ $(INT_MAK) $(MAKEDIRS)
5e8686
 	$(PSCC) $(PSO_)istack.$(OBJ) $(C_) $(PSSRC)istack.c
5e8686
 
5e8686
 $(PSOBJ)iutil.$(OBJ) : $(PSSRC)iutil.c $(GH) $(math__h) $(memory__h) $(string__h)\
5e8686
diff --git a/psi/interp.c b/psi/interp.c
5e8686
index 6dc0dda..aa5779c 100644
5e8686
--- a/psi/interp.c
5e8686
+++ b/psi/interp.c
5e8686
@@ -761,6 +761,7 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
5e8686
     uint size = ref_stack_count(pstack) - skip;
5e8686
     uint save_space = ialloc_space(idmemory);
5e8686
     int code, i;
5e8686
+    ref *safety, *safe;
5e8686
 
5e8686
     if (size > 65535)
5e8686
         size = 65535;
5e8686
@@ -778,6 +779,13 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
5e8686
                 make_null(&arr->value.refs[i]);
5e8686
         }
5e8686
     }
5e8686
+    if (pstack == &o_stack && dict_find_string(systemdict, "SAFETY", &safety) > 0 &&
5e8686
+        dict_find_string(safety, "safe", &safe) > 0 && r_has_type(safe, t_boolean) &&
5e8686
+        safe->value.boolval == true) {
5e8686
+        code = ref_stack_array_sanitize(i_ctx_p, arr, arr);
5e8686
+        if (code < 0)
5e8686
+            return code;
5e8686
+    }
5e8686
     ialloc_set_space(idmemory, save_space);
5e8686
     return code;
5e8686
 }
5e8686
diff --git a/psi/istack.c b/psi/istack.c
5e8686
index 8fe151f..f1a3e51 100644
5e8686
--- a/psi/istack.c
5e8686
+++ b/psi/istack.c
5e8686
@@ -27,6 +27,10 @@
5e8686
 #include "iutil.h"
5e8686
 #include "ivmspace.h"		/* for local/global test */
5e8686
 #include "store.h"
5e8686
+#include "icstate.h"
5e8686
+#include "iname.h"
5e8686
+#include "dstack.h"
5e8686
+#include "idict.h"
5e8686
 
5e8686
 /* Forward references */
5e8686
 static void init_block(ref_stack_t *pstack, const ref *pblock_array,
5e8686
@@ -294,6 +298,80 @@ ref_stack_store_check(const ref_stack_t *pstack, ref *parray, uint count,
5e8686
     return 0;
5e8686
 }
5e8686
 
5e8686
+int
5e8686
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr)
5e8686
+{
5e8686
+    int i, code;
5e8686
+    ref obj, arr2;
5e8686
+    ref *pobj2;
5e8686
+    gs_memory_t *mem = (gs_memory_t *)idmemory->current;
5e8686
+
5e8686
+    if (!r_is_array(sarr) || !r_has_type(darr, t_array))
5e8686
+        return_error(gs_error_typecheck);
5e8686
+
5e8686
+    for (i = 0; i < r_size(sarr); i++) {
5e8686
+        code = array_get(mem, sarr, i, &obj);
5e8686
+        if (code < 0)
5e8686
+            make_null(&obj);
5e8686
+        switch(r_type(&obj)) {
5e8686
+          case t_operator:
5e8686
+          {
5e8686
+            int index = op_index(&obj);
5e8686
+
5e8686
+            if (index > 0 && index < op_def_count) {
5e8686
+                const byte *data = (const byte *)(op_index_def(index)->oname + 1);
5e8686
+                if (dict_find_string(systemdict, (const char *)data, &pobj2) <= 0) {
5e8686
+                    byte *s = gs_alloc_bytes(mem, strlen((char *)data) + 5, "ref_stack_array_sanitize");
5e8686
+                    if (s) {
5e8686
+                        s[0] =  '\0';
5e8686
+                        strcpy((char *)s, "--");
5e8686
+                        strcpy((char *)s + 2, (char *)data);
5e8686
+                        strcpy((char *)s + strlen((char *)data) + 2, "--");
5e8686
+                    }
5e8686
+                    else {
5e8686
+                        s = (byte *)data;
5e8686
+                    }
5e8686
+                    code = name_ref(imemory, s, strlen((char *)s), &obj, 1);
5e8686
+                    if (code < 0) make_null(&obj);
5e8686
+                    if (s != data)
5e8686
+                        gs_free_object(mem, s, "ref_stack_array_sanitize");
5e8686
+                }
5e8686
+            }
5e8686
+            else {
5e8686
+                make_null(&obj);
5e8686
+            }
5e8686
+            ref_assign(darr->value.refs + i, &obj);
5e8686
+            break;
5e8686
+          }
5e8686
+          case t_array:
5e8686
+          case t_shortarray:
5e8686
+          case t_mixedarray:
5e8686
+          {
5e8686
+            int attrs = r_type_attrs(&obj) & (a_write | a_read | a_execute | a_executable);
5e8686
+            /* We only want to copy executable arrays */
5e8686
+            if (attrs & (a_execute | a_executable)) {
5e8686
+                code = ialloc_ref_array(&arr2, attrs, r_size(&obj), "ref_stack_array_sanitize");
5e8686
+                if (code < 0) {
5e8686
+                    make_null(&arr2);
5e8686
+                }
5e8686
+                else {
5e8686
+                    code = ref_stack_array_sanitize(i_ctx_p, &obj, &arr2);
5e8686
+                }
5e8686
+                ref_assign(darr->value.refs + i, &arr2);
5e8686
+            }
5e8686
+            else {
5e8686
+                ref_assign(darr->value.refs + i, &obj);
5e8686
+            }
5e8686
+            break;
5e8686
+          }
5e8686
+          default:
5e8686
+            ref_assign(darr->value.refs + i, &obj);
5e8686
+        }
5e8686
+    }
5e8686
+    return 0;
5e8686
+}
5e8686
+
5e8686
+
5e8686
 /*
5e8686
  * Store the top 'count' elements of a stack, starting 'skip' elements below
5e8686
  * the top, into an array, with or without store/undo checking.  age=-1 for
5e8686
diff --git a/psi/istack.h b/psi/istack.h
5e8686
index 051dcbe..54be405 100644
5e8686
--- a/psi/istack.h
5e8686
+++ b/psi/istack.h
5e8686
@@ -129,6 +129,9 @@ int ref_stack_store(const ref_stack_t *pstack, ref *parray, uint count,
5e8686
                     uint skip, int age, bool check,
5e8686
                     gs_dual_memory_t *idmem, client_name_t cname);
5e8686
 
5e8686
+int
5e8686
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr);
5e8686
+
5e8686
 /*
5e8686
  * Pop the top N elements off a stack.
5e8686
  * The number must not exceed the number of elements in use.
5e8686
-- 
5e8686
2.17.2
5e8686
5e8686
5e8686
From 2db98f9c66135601efb103d8db7d020a672308db Mon Sep 17 00:00:00 2001
5e8686
From: Chris Liddell <chris.liddell@artifex.com>
5e8686
Date: Thu, 13 Dec 2018 15:28:34 +0000
5e8686
Subject: [PATCH 4/6] Any transient procedures that call .force* operators
5e8686
5e8686
(i.e. for conditionals or loops) make them executeonly.
5e8686
---
5e8686
 Resource/Init/gs_diskn.ps |  2 +-
5e8686
 Resource/Init/gs_dps1.ps  |  4 ++--
5e8686
 Resource/Init/gs_fntem.ps |  4 ++--
5e8686
 Resource/Init/gs_fonts.ps | 12 ++++++------
5e8686
 Resource/Init/gs_init.ps  |  4 ++--
5e8686
 Resource/Init/gs_lev2.ps  | 11 ++++++-----
5e8686
 Resource/Init/gs_pdfwr.ps |  2 +-
5e8686
 Resource/Init/gs_res.ps   |  4 ++--
5e8686
 Resource/Init/gs_setpd.ps |  2 +-
5e8686
 Resource/Init/pdf_base.ps | 13 ++++++++-----
5e8686
 Resource/Init/pdf_draw.ps | 16 +++++++++-------
5e8686
 Resource/Init/pdf_font.ps |  6 +++---
5e8686
 Resource/Init/pdf_main.ps |  4 ++--
5e8686
 Resource/Init/pdf_ops.ps  |  7 ++++---
5e8686
 14 files changed, 49 insertions(+), 42 deletions(-)
5e8686
5e8686
diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps
5e8686
index fd694bc..8bf2054 100644
5e8686
--- a/Resource/Init/gs_diskn.ps
5e8686
+++ b/Resource/Init/gs_diskn.ps
5e8686
@@ -51,7 +51,7 @@ systemdict begin
5e8686
     mark 5 1 roll ] mark exch { { } forall } forall ]
5e8686
     //systemdict /.searchabledevs 2 index .forceput
5e8686
     exch .setglobal
5e8686
-  }
5e8686
+  } executeonly
5e8686
   if
5e8686
 } .bind executeonly odef % must be bound and hidden for .forceput
5e8686
 
5e8686
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
5e8686
index ec5db61..4fae283 100644
5e8686
--- a/Resource/Init/gs_dps1.ps
5e8686
+++ b/Resource/Init/gs_dps1.ps
5e8686
@@ -78,7 +78,7 @@ level2dict begin
5e8686
    .currentglobal
5e8686
     {		% Current mode is global; delete from local directory too.
5e8686
       //systemdict /LocalFontDirectory .knownget
5e8686
-       { 1 index .forceundef }		% LocalFontDirectory is readonly
5e8686
+       { 1 index .forceundef } executeonly		% LocalFontDirectory is readonly
5e8686
       if
5e8686
     }
5e8686
     {		% Current mode is local; if there was a shadowed global
5e8686
@@ -126,7 +126,7 @@ level2dict begin
5e8686
           }
5e8686
          ifelse
5e8686
        } forall
5e8686
-      pop counttomark 2 idiv { .forceundef } repeat pop		% readonly
5e8686
+      pop counttomark 2 idiv { .forceundef } executeonly repeat pop		% readonly
5e8686
     }
5e8686
    if
5e8686
    //SharedFontDirectory exch .forcecopynew pop
5e8686
diff --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps
5e8686
index c1f7651..6eb672a 100644
5e8686
--- a/Resource/Init/gs_fntem.ps
5e8686
+++ b/Resource/Init/gs_fntem.ps
5e8686
@@ -401,12 +401,12 @@ currentdict end def
5e8686
       .forceput % FontInfo can be read-only.
5e8686
       pop                                                        % bool <font>
5e8686
       exit
5e8686
-    } if
5e8686
+    } executeonly if
5e8686
     dup /FontInfo get                                            % bool <font> <FI>
5e8686
     /GlyphNames2Unicode /Unicode /Decoding findresource
5e8686
     .forceput % FontInfo can be read-only.
5e8686
     exit
5e8686
-  } loop
5e8686
+  } executeonly loop
5e8686
   exch setglobal
5e8686
 } .bind executeonly odef % must be bound and hidden for .forceput
5e8686
 
5e8686
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
5e8686
index 052a191..6d2c26b 100644
5e8686
--- a/Resource/Init/gs_fonts.ps
5e8686
+++ b/Resource/Init/gs_fonts.ps
5e8686
@@ -374,7 +374,7 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
5e8686
 /.setnativefontmapbuilt { % set whether we've been run
5e8686
   dup type /booleantype eq {
5e8686
       systemdict exch /.nativefontmapbuilt exch .forceput
5e8686
-  }
5e8686
+  } executeonly
5e8686
   {pop}
5e8686
   ifelse
5e8686
 } .bind executeonly odef
5e8686
@@ -1007,11 +1007,11 @@ $error /SubstituteFont { } put
5e8686
 { 2 index gcheck currentglobal
5e8686
   2 copy eq {
5e8686
     pop pop .forceput
5e8686
-  } {
5e8686
+  } executeonly {
5e8686
     5 1 roll setglobal
5e8686
     dup length string copy
5e8686
     .forceput setglobal
5e8686
-  } ifelse
5e8686
+  } executeonly ifelse
5e8686
 } .bind executeonly odef % must be bound and hidden for .forceput
5e8686
 
5e8686
 % Attempt to load a font from a file.
5e8686
@@ -1084,7 +1084,7 @@ $error /SubstituteFont { } put
5e8686
            .FontDirectory 3 index .forceundef		% readonly
5e8686
            1 index (r) file .loadfont .FontDirectory exch
5e8686
            /.setglobal .systemvar exec
5e8686
-         }
5e8686
+         } executeonly
5e8686
          { .loadfont .FontDirectory
5e8686
          }
5e8686
         ifelse
5e8686
@@ -1105,7 +1105,7 @@ $error /SubstituteFont { } put
5e8686
         dup 3 index .fontknownget
5e8686
          { dup /PathLoad 4 index //.putgstringcopy
5e8686
            4 1 roll pop pop pop //true exit
5e8686
-         } if
5e8686
+         } executeonly if
5e8686
 
5e8686
                 % Maybe the file had a different FontName.
5e8686
                 % See if we can get a FontName from the file, and if so,
5e8686
@@ -1134,7 +1134,7 @@ $error /SubstituteFont { } put
5e8686
               ifelse  % Stack: origfontname fontdict
5e8686
               exch pop //true exit
5e8686
                       % Stack: fontdict
5e8686
-            }
5e8686
+            } executeonly
5e8686
            if pop % Stack: origfontname fontdirectory path
5e8686
          }
5e8686
         if pop pop  % Stack: origfontname
5e8686
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
5e8686
index 0b900e6..9015f90 100644
5e8686
--- a/Resource/Init/gs_init.ps
5e8686
+++ b/Resource/Init/gs_init.ps
5e8686
@@ -2347,7 +2347,7 @@ SAFER { .setsafeglobal } if
5e8686
         % Update the copy of the user parameters.
5e8686
   mark .currentuserparams counttomark 2 idiv {
5e8686
     userparams 3 1 roll .forceput	% userparams is read-only
5e8686
-  } repeat pop
5e8686
+  } executeonly repeat pop
5e8686
         % Turn on idiom recognition, if available.
5e8686
   currentuserparams /IdiomRecognition known {
5e8686
     /IdiomRecognition //true .definepsuserparam
5e8686
@@ -2366,7 +2366,7 @@ SAFER { .setsafeglobal } if
5e8686
         % Remove real system params from pssystemparams.
5e8686
   mark .currentsystemparams counttomark 2 idiv {
5e8686
     pop pssystemparams exch .forceundef
5e8686
-  } repeat pop
5e8686
+  } executeonly repeat pop
5e8686
 } if
5e8686
 
5e8686
 % Set up AlignToPixels :
5e8686
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
5e8686
index a8ed892..b69303d 100644
5e8686
--- a/Resource/Init/gs_lev2.ps
5e8686
+++ b/Resource/Init/gs_lev2.ps
5e8686
@@ -154,7 +154,8 @@ end
5e8686
       % protect top level of parameters that we copied
5e8686
       dup type dup /arraytype eq exch /stringtype eq or { readonly } if
5e8686
       /userparams .systemvar 3 1 roll .forceput  % userparams is read-only
5e8686
-    } {
5e8686
+    } executeonly
5e8686
+    {
5e8686
       pop pop
5e8686
     } ifelse
5e8686
   } forall
5e8686
@@ -224,7 +225,7 @@ end
5e8686
          % protect top level parameters that we copied
5e8686
          dup type dup /arraytype eq exch /stringtype eq or { readonly } if
5e8686
          //pssystemparams 3 1 roll .forceput	% pssystemparams is read-only
5e8686
-       }
5e8686
+       } executeonly
5e8686
        { pop pop
5e8686
        }
5e8686
       ifelse
5e8686
@@ -920,7 +921,7 @@ mark
5e8686
   dup /PaintProc get
5e8686
   1 index /Implementation known not {
5e8686
     1 index dup /Implementation //null .forceput readonly pop
5e8686
-  } if
5e8686
+  } executeonly if
5e8686
   exec
5e8686
 }.bind odef
5e8686
 
5e8686
@@ -944,7 +945,7 @@ mark
5e8686
   dup /PaintProc get
5e8686
   1 index /Implementation known not {
5e8686
     1 index dup /Implementation //null .forceput readonly pop
5e8686
-  } if
5e8686
+  } executeonly if
5e8686
   /UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not
5e8686
   %% [CTM] <<Form>> PaintProc .beginform -
5e8686
   {
5e8686
@@ -991,7 +992,7 @@ mark
5e8686
         %% Form dictioanry using the /Implementation key).
5e8686
         1 dict dup /FormID 4 -1 roll put
5e8686
         1 index exch /Implementation exch .forceput readonly pop
5e8686
-      }
5e8686
+      } executeonly
5e8686
       ifelse
5e8686
     }
5e8686
     {
5e8686
diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
5e8686
index 58e75d3..b425103 100644
5e8686
--- a/Resource/Init/gs_pdfwr.ps
5e8686
+++ b/Resource/Init/gs_pdfwr.ps
5e8686
@@ -650,7 +650,7 @@ currentdict /.pdfmarkparams .undef
5e8686
             } ifelse
5e8686
           } bind .makeoperator .forceput
5e8686
           systemdict /.pdf_hooked_DSC_Creator //true .forceput
5e8686
-        } if
5e8686
+        } executeonly if
5e8686
         pop
5e8686
       } if
5e8686
     } {
5e8686
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
5e8686
index 8eb8bb0..d9b3459 100644
5e8686
--- a/Resource/Init/gs_res.ps
5e8686
+++ b/Resource/Init/gs_res.ps
5e8686
@@ -152,7 +152,7 @@ setglobal
5e8686
                 % use .forceput / .forcedef later to replace the dummy,
5e8686
                 % empty .Instances dictionary with the real one later.
5e8686
           readonly
5e8686
-        } {
5e8686
+        }{
5e8686
           /defineresource cvx /typecheck signaloperror
5e8686
         } ifelse
5e8686
 } bind executeonly odef
5e8686
@@ -424,7 +424,7 @@ status {
5e8686
                         % As noted above, Category dictionaries are read-only,
5e8686
                         % so we have to use .forcedef here.
5e8686
                   /.Instances 1 index .forcedef	% Category dict is read-only
5e8686
-                } if
5e8686
+                } executeonly if
5e8686
               }
5e8686
               { .LocalInstances dup //.emptydict eq
5e8686
                  { pop 3 dict localinstancedict Category 2 index put
5e8686
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
5e8686
index 71eb622..46e5810 100644
5e8686
--- a/Resource/Init/gs_setpd.ps
5e8686
+++ b/Resource/Init/gs_setpd.ps
5e8686
@@ -634,7 +634,7 @@ NOMEDIAATTRS {
5e8686
   SETPDDEBUG { (Rolling back.) = pstack flush } if
5e8686
   3 index 2 index 3 -1 roll .forceput
5e8686
   4 index 1 index .knownget
5e8686
-  { 4 index 3 1 roll .forceput }
5e8686
+  { 4 index 3 1 roll .forceput } executeonly
5e8686
   { 3 index exch .undef }
5e8686
   ifelse
5e8686
 } bind executeonly odef
5e8686
diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
5e8686
index 7ccd4cd..c62ac0e 100644
5e8686
--- a/Resource/Init/pdf_base.ps
5e8686
+++ b/Resource/Init/pdf_base.ps
5e8686
@@ -130,26 +130,29 @@ currentdict /num-chars-dict .undef
5e8686
 
5e8686
 /.pdfexectoken {		% <count> <opdict> <exectoken> .pdfexectoken ?
5e8686
   PDFDEBUG {
5e8686
-    pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if
5e8686
+    pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if
5e8686
     PDFSTEP {
5e8686
       pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
5e8686
       PDFSTEPcount 1 gt {
5e8686
         pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
5e8686
-      } {
5e8686
+      } executeonly
5e8686
+      {
5e8686
         dup ==only
5e8686
         (    step # ) print PDFtokencount =only
5e8686
         ( ? ) print flush 1 //false .outputpage
5e8686
         (%stdin) (r) file 255 string readline {
5e8686
           token {
5e8686
             exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput
5e8686
-          } {
5e8686
+          } executeonly
5e8686
+          {
5e8686
             pdfdict /PDFSTEPcount 1 .forceput
5e8686
-          } ifelse % token
5e8686
+          } executeonly ifelse % token
5e8686
         } {
5e8686
           pop /PDFSTEP //false def	 % EOF on stdin
5e8686
         } ifelse % readline
5e8686
       } ifelse % PDFSTEPcount > 1
5e8686
-    } {
5e8686
+    } executeonly
5e8686
+    {
5e8686
       dup ==only () = flush
5e8686
     } ifelse % PDFSTEP
5e8686
   } if % PDFDEBUG
5e8686
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
5e8686
index c239daf..d743ae1 100644
5e8686
--- a/Resource/Init/pdf_draw.ps
5e8686
+++ b/Resource/Init/pdf_draw.ps
5e8686
@@ -1118,14 +1118,14 @@ currentdict end readonly def
5e8686
           pdfdict /.Qqwarning_issued //true .forceput
5e8686
           .setglobal
5e8686
           pdfformaterror
5e8686
-        } ifelse
5e8686
+        } executeonly ifelse
5e8686
       }
5e8686
       {
5e8686
         currentglobal pdfdict gcheck .setglobal
5e8686
         pdfdict /.Qqwarning_issued //true .forceput
5e8686
         .setglobal
5e8686
         pdfformaterror
5e8686
-      } ifelse
5e8686
+      } executeonly ifelse
5e8686
       end
5e8686
     } ifelse
5e8686
   } loop
5e8686
@@ -1141,14 +1141,14 @@ currentdict end readonly def
5e8686
         pdfdict /.Qqwarning_issued //true .forceput
5e8686
         .setglobal
5e8686
         pdfformaterror
5e8686
-      } ifelse
5e8686
+      } executeonly ifelse
5e8686
     }
5e8686
     {
5e8686
       currentglobal pdfdict gcheck .setglobal
5e8686
       pdfdict /.Qqwarning_issued //true .forceput
5e8686
       .setglobal
5e8686
       pdfformaterror
5e8686
-    } ifelse
5e8686
+    } executeonly ifelse
5e8686
   } if
5e8686
   pop
5e8686
 
5e8686
@@ -2350,9 +2350,10 @@ currentdict /last-ditch-bpc-csp undef
5e8686
 /IncrementAppearanceNumber {
5e8686
   pdfdict /AppearanceNumber .knownget {
5e8686
     1 add pdfdict /AppearanceNumber 3 -1 roll .forceput
5e8686
-  }{
5e8686
+  } executeonly
5e8686
+  {
5e8686
     pdfdict /AppearanceNumber 0 .forceput
5e8686
-  } ifelse
5e8686
+  } executeonly ifelse
5e8686
 }bind executeonly odef
5e8686
 
5e8686
 /MakeAppearanceName {
5e8686
@@ -2510,7 +2511,8 @@ currentdict /last-ditch-bpc-csp undef
5e8686
     %% want to preserve it.
5e8686
     pdfdict /.PreservePDFForm false .forceput
5e8686
     /q cvx /execform cvx 5 -2 roll
5e8686
-  }{
5e8686
+  } executeonly
5e8686
+  {
5e8686
     /q cvx /PDFexecform cvx 5 -2 roll
5e8686
   } ifelse
5e8686
 
5e8686
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
5e8686
index 535b14a..f1d1728 100644
5e8686
--- a/Resource/Init/pdf_font.ps
5e8686
+++ b/Resource/Init/pdf_font.ps
5e8686
@@ -714,7 +714,7 @@ currentdict end readonly def
5e8686
     pop pop pop
5e8686
     currentdict /.stackdepth .forceundef
5e8686
     currentdict /.dstackdepth .forceundef
5e8686
-  }
5e8686
+  } executeonly
5e8686
   {pop pop pop}
5e8686
   ifelse
5e8686
 
5e8686
@@ -1224,7 +1224,7 @@ currentdict /eexec_pdf_param_dict .undef
5e8686
                 (\n   **** Warning: Type 3 glyph has unbalanced q/Q operators \(too many q's\)\n               Output may be incorrect.\n)
5e8686
                 pdfformatwarning
5e8686
                 pdfdict /.Qqwarning_issued //true .forceput
5e8686
-              } if
5e8686
+              } executeonly if
5e8686
               Q
5e8686
             } repeat
5e8686
             Q
5e8686
@@ -1989,7 +1989,7 @@ currentdict /CMap_read_dict undef
5e8686
               /CIDFallBack /CIDFont findresource
5e8686
             } if
5e8686
             exit
5e8686
-          } if
5e8686
+          } executeonly if
5e8686
         } if
5e8686
       } if
5e8686
 
5e8686
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
5e8686
index c823e69..dd1480b 100644
5e8686
--- a/Resource/Init/pdf_main.ps
5e8686
+++ b/Resource/Init/pdf_main.ps
5e8686
@@ -2694,14 +2694,14 @@ currentdict /PDF2PS_matrix_key undef
5e8686
           pdfdict /.Qqwarning_issued //true .forceput
5e8686
           .setglobal
5e8686
           pdfformaterror
5e8686
-        } ifelse
5e8686
+        } executeonly ifelse
5e8686
       }
5e8686
       {
5e8686
         currentglobal pdfdict gcheck .setglobal
5e8686
         pdfdict /.Qqwarning_issued //true .forceput
5e8686
         .setglobal
5e8686
         pdfformaterror
5e8686
-      } ifelse
5e8686
+      } executeonly ifelse
5e8686
     } if
5e8686
   } if
5e8686
   pop
5e8686
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
5e8686
index 8672d61..aa09641 100644
5e8686
--- a/Resource/Init/pdf_ops.ps
5e8686
+++ b/Resource/Init/pdf_ops.ps
5e8686
@@ -184,14 +184,14 @@ currentdict /gput_always_allow .undef
5e8686
         pdfdict /.Qqwarning_issued //true .forceput
5e8686
         .setglobal
5e8686
         pdfformaterror
5e8686
-      } ifelse
5e8686
+      } executeonly ifelse
5e8686
     }
5e8686
     {
5e8686
       currentglobal pdfdict gcheck .setglobal
5e8686
       pdfdict /.Qqwarning_issued //true .forceput
5e8686
       .setglobal
5e8686
       pdfformaterror
5e8686
-    } ifelse
5e8686
+    } executeonly ifelse
5e8686
   } if
5e8686
 } bind executeonly odef
5e8686
 
5e8686
@@ -439,7 +439,8 @@ currentdict /gput_always_allow .undef
5e8686
   dup type /booleantype eq {
5e8686
     .currentSMask type /dicttype eq {
5e8686
       .currentSMask /Processed 2 index .forceput
5e8686
-    } {
5e8686
+  } executeonly
5e8686
+  {
5e8686
       .setSMask
5e8686
   }ifelse
5e8686
   }{
5e8686
-- 
5e8686
2.17.2
5e8686
5e8686
5e8686
From 99f13091a3f309bdc95d275ea9fec10bb9f42d9a Mon Sep 17 00:00:00 2001
5e8686
From: Chris Liddell <chris.liddell@artifex.com>
5e8686
Date: Sat, 15 Dec 2018 09:08:32 +0000
5e8686
Subject: [PATCH 5/6] Bug700317: Fix logic for an older change
5e8686
5e8686
Unlike almost every other function in gs, dict_find_string() returns 1 on
5e8686
success 0 or <0 on failure. The logic for this case was wrong.
5e8686
---
5e8686
 psi/interp.c | 2 +-
5e8686
 1 file changed, 1 insertion(+), 1 deletion(-)
5e8686
5e8686
diff --git a/psi/interp.c b/psi/interp.c
5e8686
index aa5779c..f6c45bb 100644
5e8686
--- a/psi/interp.c
5e8686
+++ b/psi/interp.c
5e8686
@@ -703,7 +703,7 @@ again:
5e8686
                  * i.e. it's an internal operator we have hidden
5e8686
                  */
5e8686
                 code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
5e8686
-                if (code < 0) {
5e8686
+                if (code <= 0) {
5e8686
                     buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
5e8686
                     rlen += 4;
5e8686
                     bufptr = buf;
5e8686
-- 
5e8686
2.17.2
5e8686
5e8686
5e8686
From 59d8f4deef90c1598ff50616519d5576756b4495 Mon Sep 17 00:00:00 2001
5e8686
From: Chris Liddell <chris.liddell@artifex.com>
5e8686
Date: Tue, 18 Dec 2018 10:42:10 +0000
5e8686
Subject: [PATCH 6/6] Harden some uses of .force* operators
5e8686
5e8686
by adding a few immediate evalutions
5e8686
---
5e8686
 Resource/Init/gs_dps1.ps  |  4 ++--
5e8686
 Resource/Init/gs_fonts.ps | 20 ++++++++++----------
5e8686
 Resource/Init/gs_init.ps  |  6 +++---
5e8686
 3 files changed, 15 insertions(+), 15 deletions(-)
5e8686
5e8686
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
5e8686
index 4fae283..b75ea14 100644
5e8686
--- a/Resource/Init/gs_dps1.ps
5e8686
+++ b/Resource/Init/gs_dps1.ps
5e8686
@@ -74,7 +74,7 @@ level2dict begin
5e8686
  } odef
5e8686
 % undefinefont has to take local/global VM into account.
5e8686
 /undefinefont		% <fontname> undefinefont -
5e8686
- { .FontDirectory 1 .argindex .forceundef	% FontDirectory is readonly
5e8686
+ { //.FontDirectory 1 .argindex .forceundef	% FontDirectory is readonly
5e8686
    .currentglobal
5e8686
     {		% Current mode is global; delete from local directory too.
5e8686
       //systemdict /LocalFontDirectory .knownget
5e8686
@@ -85,7 +85,7 @@ level2dict begin
5e8686
                 % definition, copy it into the local directory.
5e8686
       //systemdict /SharedFontDirectory .knownget
5e8686
        { 1 index .knownget
5e8686
-          { .FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
5e8686
+          { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
5e8686
          if
5e8686
        }
5e8686
       if
5e8686
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
5e8686
index 6d2c26b..4807f81 100644
5e8686
--- a/Resource/Init/gs_fonts.ps
5e8686
+++ b/Resource/Init/gs_fonts.ps
5e8686
@@ -516,7 +516,7 @@ buildfontdict 3 /.buildfont3 cvx put
5e8686
       if
5e8686
     }
5e8686
    if
5e8686
-   dup .FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse	% readonly
5e8686
+   dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse	% readonly
5e8686
                 % If the font originated as a resource, register it.
5e8686
    currentfile .currentresourcefile eq { dup .registerfont } if
5e8686
    readonly
5e8686
@@ -943,7 +943,7 @@ $error /SubstituteFont { } put
5e8686
 % Try to find a font using only the present contents of Fontmap.
5e8686
 /.tryfindfont {         % <fontname> .tryfindfont <font> true
5e8686
                         % <fontname> .tryfindfont false
5e8686
-  .FontDirectory 1 index .fontknownget
5e8686
+  //.FontDirectory 1 index .fontknownget
5e8686
     {                   % Already loaded
5e8686
       exch pop //true
5e8686
     }
5e8686
@@ -975,7 +975,7 @@ $error /SubstituteFont { } put
5e8686
                {                % Font with a procedural definition
5e8686
                  exec           % The procedure will load the font.
5e8686
                                 % Check to make sure this really happened.
5e8686
-                 .FontDirectory 1 index .knownget
5e8686
+                 //.FontDirectory 1 index .knownget
5e8686
                   { exch pop //true exit }
5e8686
                  if
5e8686
                }
5e8686
@@ -1081,11 +1081,11 @@ $error /SubstituteFont { } put
5e8686
                 % because it's different depending on language level.
5e8686
            .currentglobal exch /.setglobal .systemvar exec
5e8686
                 % Remove the fake definition, if any.
5e8686
-           .FontDirectory 3 index .forceundef		% readonly
5e8686
-           1 index (r) file .loadfont .FontDirectory exch
5e8686
+           //.FontDirectory 3 index .forceundef		% readonly
5e8686
+           1 index (r) file .loadfont //.FontDirectory exch
5e8686
            /.setglobal .systemvar exec
5e8686
          } executeonly
5e8686
-         { .loadfont .FontDirectory
5e8686
+         { .loadfont //.FontDirectory
5e8686
          }
5e8686
         ifelse
5e8686
                 % Stack: fontname fontfilename fontdirectory
5e8686
@@ -1119,8 +1119,8 @@ $error /SubstituteFont { } put
5e8686
                       % Stack: origfontname fontdirectory filefontname fontdict
5e8686
               3 -1 roll pop
5e8686
                       % Stack: origfontname filefontname fontdict
5e8686
-              dup /FontName get dup FontDirectory exch .forceundef
5e8686
-              GlobalFontDirectory exch .forceundef
5e8686
+              dup /FontName get dup //.FontDirectory exch .forceundef
5e8686
+              /GlobalFontDirectory .systemvar exch .forceundef
5e8686
               dup length dict .copydict dup 3 index /FontName exch put
5e8686
               2 index exch definefont
5e8686
               exch
5e8686
@@ -1175,10 +1175,10 @@ currentdict /.putgstringcopy .forceundef
5e8686
       {
5e8686
         {
5e8686
           pop dup type /stringtype eq { cvn } if
5e8686
-          .FontDirectory 1 index known not {
5e8686
+          //.FontDirectory 1 index known not {
5e8686
             2 dict dup /FontName 3 index put
5e8686
             dup /FontType 1 put
5e8686
-            .FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
5e8686
+            //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
5e8686
           } {
5e8686
             pop
5e8686
           } ifelse
5e8686
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
5e8686
index 9015f90..48bb96d 100644
5e8686
--- a/Resource/Init/gs_init.ps
5e8686
+++ b/Resource/Init/gs_init.ps
5e8686
@@ -1158,8 +1158,8 @@ errordict /unknownerror .undef
5e8686
   //.SAFERERRORLIST
5e8686
   {dup errordict exch get 2 index 3 1 roll put} forall
5e8686
   noaccess pop
5e8686
-  systemdict /.setsafeerrors .forceundef
5e8686
-  systemdict /.SAFERERRORLIST .forceundef
5e8686
+  //systemdict /.setsafeerrors .forceundef
5e8686
+  //systemdict /.SAFERERRORLIST .forceundef
5e8686
 } bind executeonly odef
5e8686
 
5e8686
 SAFERERRORS {.setsafererrors} if
5e8686
@@ -2104,7 +2104,7 @@ currentdict /tempfilepaths undef
5e8686
 
5e8686
 /.locksafe {
5e8686
   .locksafe_userparams
5e8686
-  systemdict /getenv {pop //false} .forceput
5e8686
+  //systemdict /getenv {pop //false} .forceput
5e8686
   % setpagedevice has the side effect of clearing the page, but
5e8686
   % we will just document that. Using setpagedevice keeps the device
5e8686
   % properties and pagedevice .LockSafetyParams in agreement even
5e8686
-- 
5e8686
2.17.2
5e8686