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

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