Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
Date: 2019-01-31
Initial Package Version: 9.26
Upstream Status: Applied
Origin: Upstream, found via Arch
Description: A cure for a segfault, e.g .when specifying a page of a PDF,
https://bugs.archlinux.org/task/61513 and more critically a fix for
CVE-2019-6116 (Sandbox escape, access to filesystem).

From fae21f1668d2b44b18b84cf0923a1d5f3008a696 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Tue, 4 Dec 2018 21:31:31 +0000
Subject: [PATCH] subclassing devices - fix put_image method

The subclassing devices need to change the 'memory device' parameter to
be the child device, when its the same as the subclassing device.

Otherwise we end up trying to access the child device's memory pointers
in the subclassing device, which may not contain valid copies of
those pointers.
---

From d3537a54740d78c5895ec83694a07b3e4f616f61 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 5 Dec 2018 12:22:13 +0000
Subject: [PATCH] Bug700317: Address .force* operators exposure

Fix logic for an older change: unlike almost every other function in gs, dict_find_string() returns 1 on
success 0 or <0 on failure. The logic for this case was wrong.

Sanitize op stack for error conditions

We save the stacks to an array and store the array for the error handler to
access.

For SAFER, we traverse the array, and deep copy any op arrays (procedures). As
we make these copies, we check for operators that do *not* exist in systemdict,
when we find one, we replace the operator with a name object (of the form
"/--opname--").

Any transient procedures that call .force* operators

(i.e. for conditionals or loops) make them executeonly.

Harden some uses of .force* operators

by adding a few immediate evalutions

CVE-2019-6116
---
diff -Naur a/base/gdevsclass.c b/base/gdevsclass.c
--- a/base/gdevsclass.c	2018-11-20 10:08:19.000000000 +0000
+++ b/base/gdevsclass.c	2019-02-01 02:33:51.241121334 +0000
@@ -797,7 +797,10 @@
             int alpha_plane_index, int tag_plane_index)
 {
     if (dev->child)
-        return dev_proc(dev->child, put_image)(dev->child, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
+        if (dev == mdev)
+            return dev_proc(dev->child, put_image)(dev->child, dev->child, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
+        else
+            return dev_proc(dev->child, put_image)(dev->child, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
 
     return 0;
 }
diff -Naur a/psi/interp.c b/psi/interp.c
--- a/psi/interp.c	2018-11-20 10:08:19.000000000 +0000
+++ b/psi/interp.c	2019-02-01 02:34:28.393733960 +0000
@@ -703,7 +703,7 @@
                  * i.e. it's an internal operator we have hidden
                  */
                 code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
-                if (code < 0) {
+                if (code <= 0) {
                     buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
                     rlen += 4;
                     bufptr = buf;
@@ -761,6 +761,7 @@
     uint size = ref_stack_count(pstack) - skip;
     uint save_space = ialloc_space(idmemory);
     int code, i;
+    ref *safety, *safe;
 
     if (size > 65535)
         size = 65535;
@@ -778,6 +779,13 @@
                 make_null(&arr->value.refs[i]);
         }
     }
+    if (pstack == &o_stack && dict_find_string(systemdict, "SAFETY", &safety) > 0 &&
+        dict_find_string(safety, "safe", &safe) > 0 && r_has_type(safe, t_boolean) &&
+        safe->value.boolval == true) {
+        code = ref_stack_array_sanitize(i_ctx_p, arr, arr);
+        if (code < 0)
+            return code;
+    }
     ialloc_set_space(idmemory, save_space);
     return code;
 }
diff -Naur a/psi/int.mak b/psi/int.mak
--- a/psi/int.mak	2018-11-20 10:08:19.000000000 +0000
+++ b/psi/int.mak	2019-02-01 02:34:28.393733960 +0000
@@ -204,7 +204,8 @@
 $(PSOBJ)istack.$(OBJ) : $(PSSRC)istack.c $(GH) $(memory__h)\
  $(ierrors_h) $(gsstruct_h) $(gsutil_h)\
  $(ialloc_h) $(istack_h) $(istkparm_h) $(istruct_h) $(iutil_h) $(ivmspace_h)\
- $(store_h) $(INT_MAK) $(MAKEDIRS)
+ $(store_h) $(icstate_h) $(iname_h) $(dstack_h) $(idict_h) \
+ $(INT_MAK) $(MAKEDIRS)
 	$(PSCC) $(PSO_)istack.$(OBJ) $(C_) $(PSSRC)istack.c
 
 $(PSOBJ)iutil.$(OBJ) : $(PSSRC)iutil.c $(GH) $(math__h) $(memory__h) $(string__h)\
diff -Naur a/psi/istack.c b/psi/istack.c
--- a/psi/istack.c	2018-11-20 10:08:19.000000000 +0000
+++ b/psi/istack.c	2019-02-01 02:34:28.393733960 +0000
@@ -27,6 +27,10 @@
 #include "iutil.h"
 #include "ivmspace.h"		/* for local/global test */
 #include "store.h"
+#include "icstate.h"
+#include "iname.h"
+#include "dstack.h"
+#include "idict.h"
 
 /* Forward references */
 static void init_block(ref_stack_t *pstack, const ref *pblock_array,
@@ -294,6 +298,80 @@
     return 0;
 }
 
+int
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr)
+{
+    int i, code;
+    ref obj, arr2;
+    ref *pobj2;
+    gs_memory_t *mem = (gs_memory_t *)idmemory->current;
+
+    if (!r_is_array(sarr) || !r_has_type(darr, t_array))
+        return_error(gs_error_typecheck);
+
+    for (i = 0; i < r_size(sarr); i++) {
+        code = array_get(mem, sarr, i, &obj);
+        if (code < 0)
+            make_null(&obj);
+        switch(r_type(&obj)) {
+          case t_operator:
+          {
+            int index = op_index(&obj);
+
+            if (index > 0 && index < op_def_count) {
+                const byte *data = (const byte *)(op_index_def(index)->oname + 1);
+                if (dict_find_string(systemdict, (const char *)data, &pobj2) <= 0) {
+                    byte *s = gs_alloc_bytes(mem, strlen((char *)data) + 5, "ref_stack_array_sanitize");
+                    if (s) {
+                        s[0] =  '\0';
+                        strcpy((char *)s, "--");
+                        strcpy((char *)s + 2, (char *)data);
+                        strcpy((char *)s + strlen((char *)data) + 2, "--");
+                    }
+                    else {
+                        s = (byte *)data;
+                    }
+                    code = name_ref(imemory, s, strlen((char *)s), &obj, 1);
+                    if (code < 0) make_null(&obj);
+                    if (s != data)
+                        gs_free_object(mem, s, "ref_stack_array_sanitize");
+                }
+            }
+            else {
+                make_null(&obj);
+            }
+            ref_assign(darr->value.refs + i, &obj);
+            break;
+          }
+          case t_array:
+          case t_shortarray:
+          case t_mixedarray:
+          {
+            int attrs = r_type_attrs(&obj) & (a_write | a_read | a_execute | a_executable);
+            /* We only want to copy executable arrays */
+            if (attrs & (a_execute | a_executable)) {
+                code = ialloc_ref_array(&arr2, attrs, r_size(&obj), "ref_stack_array_sanitize");
+                if (code < 0) {
+                    make_null(&arr2);
+                }
+                else {
+                    code = ref_stack_array_sanitize(i_ctx_p, &obj, &arr2);
+                }
+                ref_assign(darr->value.refs + i, &arr2);
+            }
+            else {
+                ref_assign(darr->value.refs + i, &obj);
+            }
+            break;
+          }
+          default:
+            ref_assign(darr->value.refs + i, &obj);
+        }
+    }
+    return 0;
+}
+
+
 /*
  * Store the top 'count' elements of a stack, starting 'skip' elements below
  * the top, into an array, with or without store/undo checking.  age=-1 for
diff -Naur a/psi/istack.h b/psi/istack.h
--- a/psi/istack.h	2018-11-20 10:08:19.000000000 +0000
+++ b/psi/istack.h	2019-02-01 02:34:28.393733960 +0000
@@ -129,6 +129,9 @@
                     uint skip, int age, bool check,
                     gs_dual_memory_t *idmem, client_name_t cname);
 
+int
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr);
+
 /*
  * Pop the top N elements off a stack.
  * The number must not exceed the number of elements in use.
diff -Naur a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps
--- a/Resource/Init/gs_diskn.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_diskn.ps	2019-02-01 02:34:28.391733981 +0000
@@ -51,7 +51,7 @@
     mark 5 1 roll ] mark exch { { } forall } forall ]
     //systemdict /.searchabledevs 2 index .forceput
     exch .setglobal
-  }
+  } executeonly
   if
 } .bind executeonly odef % must be bound and hidden for .forceput
 
diff -Naur a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
--- a/Resource/Init/gs_dps1.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_dps1.ps	2019-02-01 02:34:28.391733981 +0000
@@ -74,18 +74,18 @@
  } odef
 % undefinefont has to take local/global VM into account.
 /undefinefont		% <fontname> undefinefont -
- { .FontDirectory 1 .argindex .forceundef	% FontDirectory is readonly
+ { //.FontDirectory 1 .argindex .forceundef	% FontDirectory is readonly
    .currentglobal
     {		% Current mode is global; delete from local directory too.
       //systemdict /LocalFontDirectory .knownget
-       { 1 index .forceundef }		% LocalFontDirectory is readonly
+       { 1 index .forceundef } executeonly		% LocalFontDirectory is readonly
       if
     }
     {		% Current mode is local; if there was a shadowed global
                 % definition, copy it into the local directory.
       //systemdict /SharedFontDirectory .knownget
        { 1 index .knownget
-          { .FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+          { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
          if
        }
       if
@@ -126,7 +126,7 @@
           }
          ifelse
        } forall
-      pop counttomark 2 idiv { .forceundef } repeat pop		% readonly
+      pop counttomark 2 idiv { .forceundef } executeonly repeat pop		% readonly
     }
    if
    //SharedFontDirectory exch .forcecopynew pop
diff -Naur a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps
--- a/Resource/Init/gs_fntem.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_fntem.ps	2019-02-01 02:34:28.391733981 +0000
@@ -401,12 +401,12 @@
       .forceput % FontInfo can be read-only.
       pop                                                        % bool <font>
       exit
-    } if
+    } executeonly if
     dup /FontInfo get                                            % bool <font> <FI>
     /GlyphNames2Unicode /Unicode /Decoding findresource
     .forceput % FontInfo can be read-only.
     exit
-  } loop
+  } executeonly loop
   exch setglobal
 } .bind executeonly odef % must be bound and hidden for .forceput
 
diff -Naur a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
--- a/Resource/Init/gs_fonts.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_fonts.ps	2019-02-01 02:34:28.391733981 +0000
@@ -374,7 +374,7 @@
 /.setnativefontmapbuilt { % set whether we've been run
   dup type /booleantype eq {
       systemdict exch /.nativefontmapbuilt exch .forceput
-  }
+  } executeonly
   {pop}
   ifelse
 } .bind executeonly odef
@@ -516,7 +516,7 @@
       if
     }
    if
-   dup .FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse	% readonly
+   dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse	% readonly
                 % If the font originated as a resource, register it.
    currentfile .currentresourcefile eq { dup .registerfont } if
    readonly
@@ -943,7 +943,7 @@
 % Try to find a font using only the present contents of Fontmap.
 /.tryfindfont {         % <fontname> .tryfindfont <font> true
                         % <fontname> .tryfindfont false
-  .FontDirectory 1 index .fontknownget
+  //.FontDirectory 1 index .fontknownget
     {                   % Already loaded
       exch pop //true
     }
@@ -975,7 +975,7 @@
                {                % Font with a procedural definition
                  exec           % The procedure will load the font.
                                 % Check to make sure this really happened.
-                 .FontDirectory 1 index .knownget
+                 //.FontDirectory 1 index .knownget
                   { exch pop //true exit }
                  if
                }
@@ -1007,11 +1007,11 @@
 { 2 index gcheck currentglobal
   2 copy eq {
     pop pop .forceput
-  } {
+  } executeonly {
     5 1 roll setglobal
     dup length string copy
     .forceput setglobal
-  } ifelse
+  } executeonly ifelse
 } .bind executeonly odef % must be bound and hidden for .forceput
 
 % Attempt to load a font from a file.
@@ -1081,11 +1081,11 @@
                 % because it's different depending on language level.
            .currentglobal exch /.setglobal .systemvar exec
                 % Remove the fake definition, if any.
-           .FontDirectory 3 index .forceundef		% readonly
-           1 index (r) file .loadfont .FontDirectory exch
+           //.FontDirectory 3 index .forceundef		% readonly
+           1 index (r) file .loadfont //.FontDirectory exch
            /.setglobal .systemvar exec
-         }
-         { .loadfont .FontDirectory
+         } executeonly
+         { .loadfont //.FontDirectory
          }
         ifelse
                 % Stack: fontname fontfilename fontdirectory
@@ -1105,7 +1105,7 @@
         dup 3 index .fontknownget
          { dup /PathLoad 4 index .putgstringcopy
            4 1 roll pop pop pop //true exit
-         } if
+         } executeonly if
 
                 % Maybe the file had a different FontName.
                 % See if we can get a FontName from the file, and if so,
@@ -1119,8 +1119,8 @@
                       % Stack: origfontname fontdirectory filefontname fontdict
               3 -1 roll pop
                       % Stack: origfontname filefontname fontdict
-              dup /FontName get dup FontDirectory exch .forceundef
-              GlobalFontDirectory exch .forceundef
+              dup /FontName get dup //.FontDirectory exch .forceundef
+              /GlobalFontDirectory .systemvar exch .forceundef
               dup length dict .copydict dup 3 index /FontName exch put
               2 index exch definefont
               exch
@@ -1134,9 +1134,9 @@
               ifelse  % Stack: origfontname fontdict
               exch pop //true exit
                       % Stack: fontdict
-            }
+            } executeonly
            if pop % Stack: origfontname fontdirectory path
-         }
+         } executeonly
         if pop pop  % Stack: origfontname
 
                 % The font definitely did not load correctly.
@@ -1176,10 +1176,10 @@
       {
         {
           pop dup type /stringtype eq { cvn } if
-          .FontDirectory 1 index known not {
+          //.FontDirectory 1 index known not {
             2 dict dup /FontName 3 index put
             dup /FontType 1 put
-            .FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
+            //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
           } {
             pop
           } ifelse
diff -Naur a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
--- a/Resource/Init/gs_init.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_init.ps	2019-02-01 02:34:28.392733971 +0000
@@ -1168,8 +1168,8 @@
     }ifelse
   }forall
   noaccess pop
-  systemdict /.setsafeerrors .forceundef
-  systemdict /.SAFERERRORLIST .forceundef
+  //systemdict /.setsafeerrors .forceundef
+  //systemdict /.SAFERERRORLIST .forceundef
 } bind executeonly odef
 
 SAFERERRORS {.setsafererrors} if
@@ -2114,7 +2114,7 @@
 
 /.locksafe {
   .locksafe_userparams
-  systemdict /getenv {pop //false} .forceput
+  //systemdict /getenv {pop //false} .forceput
   % setpagedevice has the side effect of clearing the page, but
   % we will just document that. Using setpagedevice keeps the device
   % properties and pagedevice .LockSafetyParams in agreement even
@@ -2357,7 +2357,7 @@
         % Update the copy of the user parameters.
   mark .currentuserparams counttomark 2 idiv {
     userparams 3 1 roll .forceput	% userparams is read-only
-  } repeat pop
+  } executeonly repeat pop
         % Turn on idiom recognition, if available.
   currentuserparams /IdiomRecognition known {
     /IdiomRecognition //true .definepsuserparam
@@ -2376,7 +2376,7 @@
         % Remove real system params from pssystemparams.
   mark .currentsystemparams counttomark 2 idiv {
     pop pssystemparams exch .forceundef
-  } repeat pop
+  } executeonly repeat pop
 } if
 
 % Set up AlignToPixels :
diff -Naur a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
--- a/Resource/Init/gs_lev2.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_lev2.ps	2019-02-01 02:34:28.392733971 +0000
@@ -154,7 +154,8 @@
       % protect top level of parameters that we copied
       dup type dup /arraytype eq exch /stringtype eq or { readonly } if
       /userparams .systemvar 3 1 roll .forceput  % userparams is read-only
-    } {
+    } executeonly
+    {
       pop pop
     } ifelse
   } forall
@@ -224,7 +225,7 @@
          % protect top level parameters that we copied
          dup type dup /arraytype eq exch /stringtype eq or { readonly } if
          //pssystemparams 3 1 roll .forceput	% pssystemparams is read-only
-       }
+       } executeonly
        { pop pop
        }
       ifelse
@@ -934,7 +935,7 @@
   dup /PaintProc get
   1 index /Implementation known not {
     1 index dup /Implementation //null .forceput readonly pop
-  } if
+  } executeonly if
   exec
 }.bind odef
 
@@ -958,7 +959,7 @@
   dup /PaintProc get
   1 index /Implementation known not {
     1 index dup /Implementation //null .forceput readonly pop
-  } if
+  } executeonly if
   /UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not
   %% [CTM] <<Form>> PaintProc .beginform -
   {
@@ -1005,7 +1006,7 @@
         %% Form dictioanry using the /Implementation key).
         1 dict dup /FormID 4 -1 roll put
         1 index exch /Implementation exch .forceput readonly pop
-      }
+      } executeonly
       ifelse
     }
     {
diff -Naur a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
--- a/Resource/Init/gs_pdfwr.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_pdfwr.ps	2019-02-01 02:34:28.392733971 +0000
@@ -650,7 +650,7 @@
             } ifelse
           } bind .makeoperator .forceput
           systemdict /.pdf_hooked_DSC_Creator //true .forceput
-        } if
+        } executeonly if
         pop
       } if
     } {
diff -Naur a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
--- a/Resource/Init/gs_res.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_res.ps	2019-02-01 02:34:28.392733971 +0000
@@ -152,7 +152,7 @@
                 % use .forceput / .forcedef later to replace the dummy,
                 % empty .Instances dictionary with the real one later.
           readonly
-        } {
+        }{
           /defineresource cvx /typecheck signaloperror
         } ifelse
 } bind executeonly odef
@@ -424,7 +424,7 @@
                         % As noted above, Category dictionaries are read-only,
                         % so we have to use .forcedef here.
                   /.Instances 1 index .forcedef	% Category dict is read-only
-                } if
+                } executeonly if
               }
               { .LocalInstances dup //.emptydict eq
                  { pop 3 dict localinstancedict Category 2 index put
diff -Naur a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
--- a/Resource/Init/gs_setpd.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/gs_setpd.ps	2019-02-01 02:34:28.392733971 +0000
@@ -634,7 +634,7 @@
   SETPDDEBUG { (Rolling back.) = pstack flush } if
   3 index 2 index 3 -1 roll .forceput
   4 index 1 index .knownget
-  { 4 index 3 1 roll .forceput }
+  { 4 index 3 1 roll .forceput } executeonly
   { 3 index exch .undef }
   ifelse
 } bind executeonly odef
diff -Naur a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
--- a/Resource/Init/pdf_base.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/pdf_base.ps	2019-02-01 02:34:28.392733971 +0000
@@ -130,26 +130,29 @@
 
 /.pdfexectoken {		% <count> <opdict> <exectoken> .pdfexectoken ?
   PDFDEBUG {
-    pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if
+    pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if
     PDFSTEP {
       pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
       PDFSTEPcount 1 gt {
         pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
-      } {
+      } executeonly
+      {
         dup ==only
         (    step # ) print PDFtokencount =only
         ( ? ) print flush 1 //false .outputpage
         (%stdin) (r) file 255 string readline {
           token {
             exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput
-          } {
+          } executeonly
+          {
             pdfdict /PDFSTEPcount 1 .forceput
-          } ifelse % token
+          } executeonly ifelse % token
         } {
           pop /PDFSTEP //false def	 % EOF on stdin
         } ifelse % readline
       } ifelse % PDFSTEPcount > 1
-    } {
+    } executeonly
+    {
       dup ==only () = flush
     } ifelse % PDFSTEP
   } if % PDFDEBUG
diff -Naur a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
--- a/Resource/Init/pdf_draw.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/pdf_draw.ps	2019-02-01 02:34:28.392733971 +0000
@@ -1118,14 +1118,14 @@
           pdfdict /.Qqwarning_issued //true .forceput
           .setglobal
           pdfformaterror
-        } ifelse
+        } executeonly ifelse
       }
       {
         currentglobal pdfdict gcheck .setglobal
         pdfdict /.Qqwarning_issued //true .forceput
         .setglobal
         pdfformaterror
-      } ifelse
+      } executeonly ifelse
       end
     } ifelse
   } loop
@@ -1141,14 +1141,14 @@
         pdfdict /.Qqwarning_issued //true .forceput
         .setglobal
         pdfformaterror
-      } ifelse
+      } executeonly ifelse
     }
     {
       currentglobal pdfdict gcheck .setglobal
       pdfdict /.Qqwarning_issued //true .forceput
       .setglobal
       pdfformaterror
-    } ifelse
+    } executeonly ifelse
   } if
   pop
 
@@ -2350,9 +2350,10 @@
 /IncrementAppearanceNumber {
   pdfdict /AppearanceNumber .knownget {
     1 add pdfdict /AppearanceNumber 3 -1 roll .forceput
-  }{
+  } executeonly
+  {
     pdfdict /AppearanceNumber 0 .forceput
-  } ifelse
+  } executeonly ifelse
 }bind executeonly odef
 
 /MakeAppearanceName {
@@ -2510,7 +2511,8 @@
     %% want to preserve it.
     pdfdict /.PreservePDFForm false .forceput
     /q cvx /execform cvx 5 -2 roll
-  }{
+  } executeonly
+  {
     /q cvx /PDFexecform cvx 5 -2 roll
   } ifelse
 
diff -Naur a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
--- a/Resource/Init/pdf_font.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/pdf_font.ps	2019-02-01 02:34:28.393733960 +0000
@@ -714,7 +714,7 @@
     pop pop pop
     currentdict /.stackdepth .forceundef
     currentdict /.dstackdepth .forceundef
-  }
+  } executeonly
   {pop pop pop}
   ifelse
 
@@ -1232,7 +1232,7 @@
                 (\n   **** Warning: Type 3 glyph has unbalanced q/Q operators \(too many q's\)\n               Output may be incorrect.\n)
                 pdfformatwarning
                 pdfdict /.Qqwarning_issued //true .forceput
-              } if
+              } executeonly if
               Q
             } repeat
             Q
@@ -2016,7 +2016,7 @@
               /CIDFallBack /CIDFont findresource
             } if
             exit
-          } if
+          } executeonly if
         } if
       } if
 
diff -Naur a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
--- a/Resource/Init/pdf_main.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/pdf_main.ps	2019-02-01 02:34:28.393733960 +0000
@@ -2701,14 +2701,14 @@
           pdfdict /.Qqwarning_issued //true .forceput
           .setglobal
           pdfformaterror
-        } ifelse
+        } executeonly ifelse
       }
       {
         currentglobal pdfdict gcheck .setglobal
         pdfdict /.Qqwarning_issued //true .forceput
         .setglobal
         pdfformaterror
-      } ifelse
+      } executeonly ifelse
     } if
   } if
   pop
diff -Naur a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
--- a/Resource/Init/pdf_ops.ps	2018-11-20 10:08:19.000000000 +0000
+++ b/Resource/Init/pdf_ops.ps	2019-02-01 02:34:28.393733960 +0000
@@ -184,14 +184,14 @@
         pdfdict /.Qqwarning_issued //true .forceput
         .setglobal
         pdfformaterror
-      } ifelse
+      } executeonly ifelse
     }
     {
       currentglobal pdfdict gcheck .setglobal
       pdfdict /.Qqwarning_issued //true .forceput
       .setglobal
       pdfformaterror
-    } ifelse
+    } executeonly ifelse
   } if
 } bind executeonly odef
 
@@ -439,7 +439,8 @@
   dup type /booleantype eq {
     .currentSMask type /dicttype eq {
       .currentSMask /Processed 2 index .forceput
-    } {
+  } executeonly
+  {
       .setSMask
   }ifelse
   }{
