From 20001d2bdf3cc60e76241a6ae72b1df01c5424c5 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 13 Dec 2018 15:28:34 +0000
Subject: [PATCH 2/7] Any transient procedures that call .force* operators

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

CVE: CVE-2019-6116
Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git]

Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
---
 Resource/Init/gs_diskn.ps |  2 +-
 Resource/Init/gs_dps1.ps  |  4 ++--
 Resource/Init/gs_fntem.ps |  4 ++--
 Resource/Init/gs_fonts.ps | 12 ++++++------
 Resource/Init/gs_init.ps  |  4 ++--
 Resource/Init/gs_lev2.ps  | 11 ++++++-----
 Resource/Init/gs_pdfwr.ps |  2 +-
 Resource/Init/gs_res.ps   |  4 ++--
 Resource/Init/gs_setpd.ps |  2 +-
 Resource/Init/pdf_base.ps | 13 ++++++++-----
 Resource/Init/pdf_draw.ps | 16 +++++++++-------
 Resource/Init/pdf_font.ps |  6 +++---
 Resource/Init/pdf_main.ps |  4 ++--
 Resource/Init/pdf_ops.ps  |  7 ++++---
 14 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps
index fd694bc..8bf2054 100644
--- a/Resource/Init/gs_diskn.ps
+++ b/Resource/Init/gs_diskn.ps
@@ -51,7 +51,7 @@ systemdict begin
     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 --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index ec5db61..4fae283 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -78,7 +78,7 @@ level2dict begin
    .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
@@ -126,7 +126,7 @@ level2dict begin
           }
          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 --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps
index c1f7651..6eb672a 100644
--- a/Resource/Init/gs_fntem.ps
+++ b/Resource/Init/gs_fntem.ps
@@ -401,12 +401,12 @@ currentdict end def
       .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 --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 803faca..290da0c 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -374,7 +374,7 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
 /.setnativefontmapbuilt { % set whether we've been run
   dup type /booleantype eq {
       systemdict exch /.nativefontmapbuilt exch .forceput
-  }
+  } executeonly
   {pop}
   ifelse
 } .bind executeonly odef
@@ -1007,11 +1007,11 @@ $error /SubstituteFont { } put
 { 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.
@@ -1084,7 +1084,7 @@ $error /SubstituteFont { } put
            .FontDirectory 3 index .forceundef		% readonly
            1 index (r) file .loadfont .FontDirectory exch
            /.setglobal .systemvar exec
-         }
+         } executeonly
          { .loadfont .FontDirectory
          }
         ifelse
@@ -1105,7 +1105,7 @@ $error /SubstituteFont { } put
         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,
@@ -1134,7 +1134,7 @@ $error /SubstituteFont { } put
               ifelse  % Stack: origfontname fontdict
               exch pop //true exit
                       % Stack: fontdict
-            }
+            } executeonly
            if pop % Stack: origfontname fontdirectory path
          }
         if pop pop  % Stack: origfontname
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index d733124..56c0bd2 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2357,7 +2357,7 @@ SAFER { .setsafeglobal } if
         % 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 @@ SAFER { .setsafeglobal } if
         % 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 --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 44fe619..0f0d573 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -154,7 +154,8 @@ end
       % 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 @@ end
          % 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 @@ mark
   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 @@ mark
   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 @@ mark
         %% 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 --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
index 58e75d3..b425103 100644
--- a/Resource/Init/gs_pdfwr.ps
+++ b/Resource/Init/gs_pdfwr.ps
@@ -650,7 +650,7 @@ currentdict /.pdfmarkparams .undef
             } ifelse
           } bind .makeoperator .forceput
           systemdict /.pdf_hooked_DSC_Creator //true .forceput
-        } if
+        } executeonly if
         pop
       } if
     } {
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
index 8eb8bb0..d9b3459 100644
--- a/Resource/Init/gs_res.ps
+++ b/Resource/Init/gs_res.ps
@@ -152,7 +152,7 @@ setglobal
                 % 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 @@ status {
                         % 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 --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
index e22597e..7875d1f 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -634,7 +634,7 @@ NOMEDIAATTRS {
   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 --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
index b45e980..7312729 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -130,26 +130,29 @@ currentdict /num-chars-dict .undef
 
 /.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 --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index 6b0ba93..40c6ac8 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -1118,14 +1118,14 @@ currentdict end readonly def
           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 @@ currentdict end readonly def
         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 @@ currentdict /last-ditch-bpc-csp undef
 /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 @@ currentdict /last-ditch-bpc-csp undef
     %% 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 --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index bea9ea9..4cd62b9 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -714,7 +714,7 @@ currentdict end readonly def
     pop pop pop
     currentdict /.stackdepth .forceundef
     currentdict /.dstackdepth .forceundef
-  }
+  } executeonly
   {pop pop pop}
   ifelse
 
@@ -1232,7 +1232,7 @@ currentdict /eexec_pdf_param_dict .undef
                 (\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 @@ currentdict /CMap_read_dict undef
               /CIDFallBack /CIDFont findresource
             } if
             exit
-          } if
+          } executeonly if
         } if
       } if
 
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 00da47a..37e69b3 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -2701,14 +2701,14 @@ currentdict /PDF2PS_matrix_key undef
           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 --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index 8672d61..aa09641 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -184,14 +184,14 @@ currentdict /gput_always_allow .undef
         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 @@ currentdict /gput_always_allow .undef
   dup type /booleantype eq {
     .currentSMask type /dicttype eq {
       .currentSMask /Processed 2 index .forceput
-    } {
+  } executeonly
+  {
       .setSMask
   }ifelse
   }{
-- 
2.18.1

