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