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

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