6bfa55
From b0222e5e39712999f22084996a6b85a120b9389e Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Thu, 20 Sep 2018 16:35:28 +0100
6bfa55
Subject: [PATCH 1/6] Bug 699795: add operand checking to
6bfa55
 .setnativefontmapbuilt
6bfa55
6bfa55
.setnativefontmapbuilt .forceputs a value into systemdict - it is intended
6bfa55
to be a boolean, but in this case was being called with a compound object
6bfa55
(a dictionary). Such an object, in local VM, being forced into systemdict
6bfa55
would then confuse the garbager, since it could be restored away with the
6bfa55
reference remaining.
6bfa55
6bfa55
This adds operand checking, so .setnativefontmapbuilt will simply ignore
6bfa55
anything other than a boolean value, and also removes the definition of
6bfa55
.setnativefontmapbuilt after use, since it is only used in two, closely
6bfa55
related places.
6bfa55
---
6bfa55
 Resource/Init/gs_fonts.ps | 11 ++++++++---
6bfa55
 1 file changed, 8 insertions(+), 3 deletions(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
6bfa55
index 38f0f6c..45b6613 100644
6bfa55
--- a/Resource/Init/gs_fonts.ps
6bfa55
+++ b/Resource/Init/gs_fonts.ps
6bfa55
@@ -372,9 +372,13 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
6bfa55
 % of strings: what the system thinks is the ps name,
6bfa55
 % and the access path.
6bfa55
 /.setnativefontmapbuilt { % set whether we've been run
6bfa55
-  systemdict exch /.nativefontmapbuilt exch .forceput
6bfa55
+  dup type /booleantype eq {
6bfa55
+      systemdict exch /.nativefontmapbuilt exch .forceput
6bfa55
+  }
6bfa55
+  {pop}
6bfa55
+  ifelse
6bfa55
 } .bind executeonly def
6bfa55
-systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
6bfa55
+systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec
6bfa55
 /.buildnativefontmap {   % - .buildnativefontmap <bool>
6bfa55
   systemdict /.nativefontmapbuilt .knownget not
6bfa55
   { //false} if
6bfa55
@@ -415,9 +419,10 @@ systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
6bfa55
       } forall
6bfa55
     } if
6bfa55
     % record that we've been run
6bfa55
-    //true .setnativefontmapbuilt
6bfa55
+    //true //.setnativefontmapbuilt exec
6bfa55
   } ifelse
6bfa55
 } bind def
6bfa55
+currentdict /.setnativefontmapbuilt .forceundef
6bfa55
 
6bfa55
 % Create the dictionary that registers the .buildfont procedure
6bfa55
 % (called by definefont) for each FontType.
6bfa55
-- 
6bfa55
2.17.2
6bfa55
6bfa55
6bfa55
From a54c9e61e7d02bbc620bcba9b1c208462a876afb Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Sat, 29 Sep 2018 15:34:55 +0100
6bfa55
Subject: [PATCH 2/6] Bug 699816: Improve hiding of security critical custom
6bfa55
 operators
6bfa55
6bfa55
Make procedures that use .forceput/.forcedef/.forceundef into operators.
6bfa55
6bfa55
The result of this is that errors get reported against the "top" operator,
6bfa55
rather than the "called" operator within the procedure.
6bfa55
6bfa55
For example:
6bfa55
/myproc
6bfa55
{
6bfa55
  myop
6bfa55
} bind def
6bfa55
6bfa55
If 'myop' throws an error, the error handler will be passed the 'myop'
6bfa55
operator. Promoting 'myproc' to a operator means the error handler will be
6bfa55
passed 'myproc'.
6bfa55
---
6bfa55
 Resource/Init/gs_diskn.ps |  2 +-
6bfa55
 Resource/Init/gs_dps.ps   |  2 +-
6bfa55
 Resource/Init/gs_fntem.ps |  2 +-
6bfa55
 Resource/Init/gs_fonts.ps | 10 +++++-----
6bfa55
 Resource/Init/gs_lev2.ps  | 13 +++++++++----
6bfa55
 Resource/Init/gs_pdfwr.ps |  2 +-
6bfa55
 Resource/Init/gs_setpd.ps | 25 +++++++++++++++++--------
6bfa55
 Resource/Init/gs_typ32.ps | 14 +++++++++-----
6bfa55
 Resource/Init/gs_type1.ps |  2 +-
6bfa55
 Resource/Init/pdf_base.ps |  2 +-
6bfa55
 Resource/Init/pdf_draw.ps | 10 +++++-----
6bfa55
 Resource/Init/pdf_font.ps |  8 ++++----
6bfa55
 Resource/Init/pdf_main.ps |  4 ++--
6bfa55
 Resource/Init/pdf_ops.ps  |  8 ++++----
6bfa55
 14 files changed, 61 insertions(+), 43 deletions(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps
6bfa55
index 5540715..26ec0b5 100644
6bfa55
--- a/Resource/Init/gs_diskn.ps
6bfa55
+++ b/Resource/Init/gs_diskn.ps
6bfa55
@@ -53,7 +53,7 @@ systemdict begin
6bfa55
     exch .setglobal
6bfa55
   }
6bfa55
   if
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef % must be bound and hidden for .forceput
6bfa55
 
6bfa55
 % Modify .putdevparams to force regeneration of .searchabledevs list
6bfa55
 /.putdevparams {
6bfa55
diff --git a/Resource/Init/gs_dps.ps b/Resource/Init/gs_dps.ps
6bfa55
index cad7056..daf7b0f 100644
6bfa55
--- a/Resource/Init/gs_dps.ps
6bfa55
+++ b/Resource/Init/gs_dps.ps
6bfa55
@@ -70,7 +70,7 @@
6bfa55
                 % Save a copy of the initial gstate.
6bfa55
   //systemdict /savedinitialgstate gstate readonly .forceput
6bfa55
   .setglobal
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef % must be bound and hidden for .forceput
6bfa55
 
6bfa55
 % Initialize local dictionaries and gstate when creating a new context.
6bfa55
 % Note that until this completes, we are in the anomalous situation of
6bfa55
diff --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps
6bfa55
index 3ceee18..c1f7651 100644
6bfa55
--- a/Resource/Init/gs_fntem.ps
6bfa55
+++ b/Resource/Init/gs_fntem.ps
6bfa55
@@ -408,7 +408,7 @@ currentdict end def
6bfa55
     exit
6bfa55
   } loop
6bfa55
   exch setglobal
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef % must be bound and hidden for .forceput
6bfa55
 
6bfa55
 currentdict end /ProcSet defineresource pop
6bfa55
 
6bfa55
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
6bfa55
index 45b6613..89c3ab7 100644
6bfa55
--- a/Resource/Init/gs_fonts.ps
6bfa55
+++ b/Resource/Init/gs_fonts.ps
6bfa55
@@ -377,8 +377,8 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
6bfa55
   }
6bfa55
   {pop}
6bfa55
   ifelse
6bfa55
-} .bind executeonly def
6bfa55
-systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec
6bfa55
+} .bind executeonly odef
6bfa55
+systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
6bfa55
 /.buildnativefontmap {   % - .buildnativefontmap <bool>
6bfa55
   systemdict /.nativefontmapbuilt .knownget not
6bfa55
   { //false} if
6bfa55
@@ -419,7 +419,7 @@ systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec
6bfa55
       } forall
6bfa55
     } if
6bfa55
     % record that we've been run
6bfa55
-    //true //.setnativefontmapbuilt exec
6bfa55
+    //true .setnativefontmapbuilt
6bfa55
   } ifelse
6bfa55
 } bind def
6bfa55
 currentdict /.setnativefontmapbuilt .forceundef
6bfa55
@@ -1103,7 +1103,7 @@ $error /SubstituteFont { } put
6bfa55
 
6bfa55
                 % Check to make sure the font was actually loaded.
6bfa55
         dup 3 index .fontknownget
6bfa55
-         { dup /PathLoad 4 index //.putgstringcopy exec
6bfa55
+         { dup /PathLoad 4 index .putgstringcopy
6bfa55
            4 1 roll pop pop pop //true exit
6bfa55
          } if
6bfa55
 
6bfa55
@@ -1115,7 +1115,7 @@ $error /SubstituteFont { } put
6bfa55
          {            % Stack: origfontname fontdirectory path filefontname
6bfa55
            2 index 1 index .fontknownget
6bfa55
             {   % Yes.  Stack: origfontname fontdirectory path filefontname fontdict
6bfa55
-              dup 4 -1 roll /PathLoad exch //.putgstringcopy exec
6bfa55
+              dup 4 -1 roll /PathLoad exch .putgstringcopy
6bfa55
                       % Stack: origfontname fontdirectory filefontname fontdict
6bfa55
               3 -1 roll pop
6bfa55
                       % Stack: origfontname filefontname fontdict
6bfa55
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
6bfa55
index eee0b9f..a8ed892 100644
6bfa55
--- a/Resource/Init/gs_lev2.ps
6bfa55
+++ b/Resource/Init/gs_lev2.ps
6bfa55
@@ -163,10 +163,11 @@ end
6bfa55
         % Set them again to the new values.  From here on, we are safe,
6bfa55
         % since a context switch will consult userparams.
6bfa55
   .setuserparams
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef % must be bound and hidden for .forceput
6bfa55
 
6bfa55
 /setuserparams {		% <dict> setuserparams -
6bfa55
-    .setuserparams2
6bfa55
+    {.setuserparams2} stopped
6bfa55
+    {/setuserparams load $error /errorname get signalerror} if
6bfa55
 } .bind odef
6bfa55
 % Initialize user parameters managed here.
6bfa55
 /JobName () .definepsuserparam
6bfa55
@@ -415,7 +416,9 @@ psuserparams /ProcessDSCComment {.checkprocesscomment} put
6bfa55
 
6bfa55
 % VMReclaim and VMThreshold are user parameters.
6bfa55
 /setvmthreshold {		% <int> setvmthreshold -
6bfa55
-  mark /VMThreshold 2 .argindex .dicttomark .setuserparams2 pop
6bfa55
+  mark /VMThreshold 2 .argindex .dicttomark {.setuserparams2} stopped
6bfa55
+  {pop /setvmthreshold load $error /errorname get signalerror}
6bfa55
+  {pop} ifelse
6bfa55
 } odef
6bfa55
 /vmreclaim {			% <int> vmreclaim -
6bfa55
   dup 0 gt {
6bfa55
@@ -427,7 +430,9 @@ psuserparams /ProcessDSCComment {.checkprocesscomment} put
6bfa55
     ifelse
6bfa55
   } {
6bfa55
     % VMReclaim userparam controls enable/disable GC
6bfa55
-    mark /VMReclaim 2 index .dicttomark .setuserparams2 pop
6bfa55
+    mark /VMReclaim 2 index .dicttomark {.setuserparams2} stopped
6bfa55
+    {pop /vmreclaim load $error /errorname get signalerror}
6bfa55
+    {pop} ifelse
6bfa55
   } ifelse
6bfa55
 } odef
6bfa55
 -1 setvmthreshold
6bfa55
diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
6bfa55
index fb1c419..58e75d3 100644
6bfa55
--- a/Resource/Init/gs_pdfwr.ps
6bfa55
+++ b/Resource/Init/gs_pdfwr.ps
6bfa55
@@ -660,7 +660,7 @@ currentdict /.pdfmarkparams .undef
6bfa55
   {
6bfa55
     pop
6bfa55
   } ifelse
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef % must be bound and hidden for .forceput
6bfa55
 
6bfa55
 % Use the DSC processing hook to pass DSC comments to the driver.
6bfa55
 % We use a pseudo-parameter named DSC whose value is an array:
6bfa55
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
6bfa55
index 8fa7c51..afb4ffa 100644
6bfa55
--- a/Resource/Init/gs_setpd.ps
6bfa55
+++ b/Resource/Init/gs_setpd.ps
6bfa55
@@ -608,6 +608,20 @@ NOMEDIAATTRS {
6bfa55
 % in the <failed> dictionary with the policy value,
6bfa55
 % and we replace the key in the <merged> dictionary with its prior value
6bfa55
 % (or remove it if it had no prior value).
6bfa55
+
6bfa55
+% Making this an operator means we can properly hide
6bfa55
+% the contents - specifically .forceput
6bfa55
+/1Policy
6bfa55
+{
6bfa55
+  % Roll back the failed request to its previous status.
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
+   { 3 index exch .undef }
6bfa55
+  ifelse
6bfa55
+} bind executeonly odef
6bfa55
+
6bfa55
 /.policyprocs mark
6bfa55
 % These procedures are called with the following on the stack:
6bfa55
 %   <orig> <merged> <failed> <Policies> <key> <policy>
6bfa55
@@ -631,14 +645,7 @@ NOMEDIAATTRS {
6bfa55
         /setpagedevice .systemvar /configurationerror signalerror
6bfa55
       } ifelse
6bfa55
   } bind
6bfa55
-  1 {		% Roll back the failed request to its previous status.
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
-         { 3 index exch .undef }
6bfa55
-        ifelse
6bfa55
-  } .bind executeonly % must be bound and hidden for .forceput
6bfa55
+  1 /1Policy load
6bfa55
   7 {		% For PageSize only, just impose the request.
6bfa55
         1 index /PageSize eq
6bfa55
          { pop pop 1 index /PageSize 7 put }
6bfa55
@@ -646,6 +653,8 @@ SETPDDEBUG { (Rolling back.) = pstack flush } if
6bfa55
         ifelse
6bfa55
   } bind
6bfa55
 .dicttomark readonly def
6bfa55
+currentdict /1Policy undef
6bfa55
+
6bfa55
 /.applypolicies		% <orig> <merged> <failed> .applypolicies
6bfa55
                         %   <orig> <merged'> <failed'>
6bfa55
  { 1 index /Policies get 1 index
6bfa55
diff --git a/Resource/Init/gs_typ32.ps b/Resource/Init/gs_typ32.ps
6bfa55
index b6600b0..9150f71 100644
6bfa55
--- a/Resource/Init/gs_typ32.ps
6bfa55
+++ b/Resource/Init/gs_typ32.ps
6bfa55
@@ -79,15 +79,19 @@ systemdict /.removeglyphs .undef
6bfa55
 .dicttomark /ProcSet defineresource pop
6bfa55
 
6bfa55
 /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse
6bfa55
-.cidfonttypes begin
6bfa55
-
6bfa55
-4	% CIDFontType 4 = FontType 32
6bfa55
-{ dup /FontType 32 .forceput
6bfa55
+/CIDFontType4
6bfa55
+{
6bfa55
+  dup /FontType 32 .forceput
6bfa55
   dup /CharStrings 20 dict .forceput
6bfa55
   1 index exch .buildfont32 exch pop
6bfa55
-} .bind executeonly def % must be bound and hidden for .forceput
6bfa55
+} .bind executeonly odef
6bfa55
+.cidfonttypes begin
6bfa55
+
6bfa55
+
6bfa55
+4 /CIDFontType4 load def % CIDFontType 4 = FontType 32
6bfa55
 
6bfa55
 end		% .cidfonttypes
6bfa55
+currentdict /CIDFontType4 .forceundef
6bfa55
 
6bfa55
 % Define the BuildGlyph procedure.
6bfa55
 % Since Type 32 fonts are indexed by CID, there is no BuildChar procedure.
6bfa55
diff --git a/Resource/Init/gs_type1.ps b/Resource/Init/gs_type1.ps
6bfa55
index efdae48..2935d9c 100644
6bfa55
--- a/Resource/Init/gs_type1.ps
6bfa55
+++ b/Resource/Init/gs_type1.ps
6bfa55
@@ -283,7 +283,7 @@ currentdict /closesourcedict .undef
6bfa55
   } if
6bfa55
   2 copy /WeightVector exch .forceput
6bfa55
   .setweightvector
6bfa55
-} .bind executeonly def
6bfa55
+} .bind executeonly odef
6bfa55
 end
6bfa55
 
6bfa55
 % Register the font types for definefont.
6bfa55
diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
6bfa55
index a82a2a3..7ccd4cd 100644
6bfa55
--- a/Resource/Init/pdf_base.ps
6bfa55
+++ b/Resource/Init/pdf_base.ps
6bfa55
@@ -218,7 +218,7 @@ currentdict /num-chars-dict .undef
6bfa55
       } ifelse
6bfa55
     } ifelse
6bfa55
   } ifelse
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 /PDFScanRules_true << /PDFScanRules //true >> def
6bfa55
 /PDFScanRules_null << /PDFScanRules //null >> def
6bfa55
 /.pdfrun {			% <file> <opdict> .pdfrun -
6bfa55
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
6bfa55
index d1b6ac9..c239daf 100644
6bfa55
--- a/Resource/Init/pdf_draw.ps
6bfa55
+++ b/Resource/Init/pdf_draw.ps
6bfa55
@@ -1158,7 +1158,7 @@ currentdict end readonly def
6bfa55
   Q
6bfa55
   PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if
6bfa55
   PDFfile exch setfileposition
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /.pdfpaintproc {
6bfa55
     %% Get the /m from pdfopdict (must be present)
6bfa55
@@ -1189,7 +1189,7 @@ currentdict end readonly def
6bfa55
     {
6bfa55
       switch_to_text_marking_ops
6bfa55
     } if
6bfa55
-}bind executeonly def
6bfa55
+}bind executeonly odef
6bfa55
 
6bfa55
 /resolvepattern {	% <patternstreamdict> resolvepattern <patterndict>
6bfa55
                 % Don't do the resolvestream now: just capture the data
6bfa55
@@ -2353,7 +2353,7 @@ currentdict /last-ditch-bpc-csp undef
6bfa55
   }{
6bfa55
     pdfdict /AppearanceNumber 0 .forceput
6bfa55
   } ifelse
6bfa55
-}bind executeonly def
6bfa55
+}bind executeonly odef
6bfa55
 
6bfa55
 /MakeAppearanceName {
6bfa55
   pdfdict /AppearanceNumber get
6bfa55
@@ -2382,7 +2382,7 @@ currentdict /last-ditch-bpc-csp undef
6bfa55
   DoForm
6bfa55
   pdfdict /.PreservePDFForm 3 -1 roll .forceput
6bfa55
   grestore
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /DoForm {
6bfa55
   %% save the current value, if its true we will set it to false later, in order
6bfa55
@@ -2541,7 +2541,7 @@ currentdict /last-ditch-bpc-csp undef
6bfa55
     end
6bfa55
   } if
6bfa55
   pdfdict /.PreservePDFForm 3 -1 roll .forceput
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /_dops_save 1 array def
6bfa55
 
6bfa55
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
6bfa55
index feaf0d0..535b14a 100644
6bfa55
--- a/Resource/Init/pdf_font.ps
6bfa55
+++ b/Resource/Init/pdf_font.ps
6bfa55
@@ -718,7 +718,7 @@ currentdict end readonly def
6bfa55
   {pop pop pop}
6bfa55
   ifelse
6bfa55
 
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 currentdict /.DoToUnicode? .forceundef
6bfa55
 
6bfa55
@@ -1241,7 +1241,7 @@ currentdict /eexec_pdf_param_dict .undef
6bfa55
     } bdef
6bfa55
     dup currentdict Encoding .processToUnicode
6bfa55
     currentdict end .completefont exch pop
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 /.adjustcharwidth {	% <wx> <wy> .adjustcharwidth <wx'> <wy'>
6bfa55
   % Enforce the metrics, in glyph space, to the values found in the PDF Font object
6bfa55
   % - force wy == 0 (assumed, and not stored in the PDF font)
6bfa55
@@ -2026,7 +2026,7 @@ currentdict /CMap_read_dict undef
6bfa55
     } if
6bfa55
     /findresource cvx /undefined signalerror
6bfa55
   } loop
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /buildCIDType0 {	% <CIDFontType0-font-resource> buildCIDType0 <font>
6bfa55
   dup /BaseFont get findCIDFont exch pop
6bfa55
@@ -2211,7 +2211,7 @@ currentdict /CMap_read_dict undef
6bfa55
   /Type0 //buildType0
6bfa55
   /Type1 //buildType1
6bfa55
   /MMType1 //buildType1
6bfa55
-  /Type3 //buildType3
6bfa55
+  /Type3 /buildType3 load
6bfa55
   /TrueType //buildTrueType
6bfa55
   /CIDFontType0 //buildCIDType0
6bfa55
   /CIDFontType2 //buildCIDType2
6bfa55
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
6bfa55
index 09f8735..c823e69 100644
6bfa55
--- a/Resource/Init/pdf_main.ps
6bfa55
+++ b/Resource/Init/pdf_main.ps
6bfa55
@@ -660,7 +660,7 @@ currentdict /runpdfstring .undef
6bfa55
     } forall
6bfa55
     pop
6bfa55
   } ifelse
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 currentdict /pdf_collection_files .undef
6bfa55
 
6bfa55
@@ -2715,7 +2715,7 @@ currentdict /PDF2PS_matrix_key undef
6bfa55
   .setglobal
6bfa55
   /RepairedAnError exch def
6bfa55
   /Repaired exch def
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 % Display the contents of a page (including annotations).
6bfa55
 /showpagecontents {	% <pagedict> showpagecontents -
6bfa55
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
6bfa55
index c45fc51..8672d61 100644
6bfa55
--- a/Resource/Init/pdf_ops.ps
6bfa55
+++ b/Resource/Init/pdf_ops.ps
6bfa55
@@ -193,7 +193,7 @@ currentdict /gput_always_allow .undef
6bfa55
       pdfformaterror
6bfa55
     } ifelse
6bfa55
   } if
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 % Save PDF gstate
6bfa55
 /qstate {       % - qstate <qstate>
6bfa55
@@ -451,7 +451,7 @@ currentdict /gput_always_allow .undef
6bfa55
   %% a gsave, so we haven't copied it to /self, if we don't do that here
6bfa55
   %% then transparent annotations cause an invalid access error.
6bfa55
   currentdict //nodict eq {/self dup load end 5 dict begin def} if
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 /AIS { .setalphaisshape } bind executeonly def
6bfa55
 /BM {
6bfa55
   /.setblendmode where {
6bfa55
@@ -1077,7 +1077,7 @@ end readonly def
6bfa55
     pdfopdict /v {inside_text_v} bind .forceput
6bfa55
     pdfopdict /y {inside_text_y} bind .forceput
6bfa55
     pdfopdict /re {inside_text_re} bind .forceput
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /switch_to_normal_marking_ops {
6bfa55
     pdfopdict /m {normal_m} bind .forceput
6bfa55
@@ -1086,7 +1086,7 @@ end readonly def
6bfa55
     pdfopdict /v {normal_v} bind .forceput
6bfa55
     pdfopdict /y {normal_y} bind .forceput
6bfa55
     pdfopdict /re {normal_re} bind .forceput
6bfa55
-} bind executeonly def
6bfa55
+} bind executeonly odef
6bfa55
 
6bfa55
 /BT {
6bfa55
   currentdict /TextSaveMatrix known {
6bfa55
-- 
6bfa55
2.17.2
6bfa55
6bfa55
6bfa55
From 1778db6bc10a8d60dfe986b22d2300326733ddd6 Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Thu, 4 Oct 2018 10:42:13 +0100
6bfa55
Subject: [PATCH 3/6] Bug 699832: add control over hiding error handlers.
6bfa55
6bfa55
With a previous commit changing error handling in SAFER so the handler gets
6bfa55
passed a name object (rather than executable object), it is less critical to
6bfa55
hide the error handlers.
6bfa55
6bfa55
This introduces a -dSAFERERRORS option to force only use of the default error
6bfa55
handlers.
6bfa55
6bfa55
It also adds a .setsafererrors Postscript call, meaning a caller, without
6bfa55
-dSAFERERRORS, can create their own default error handlers (in errordict, as
6bfa55
normal), and then call .setsafererrors meaning their own handlers are always
6bfa55
called.
6bfa55
6bfa55
With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is
6bfa55
removed.
6bfa55
---
6bfa55
 Resource/Init/gs_init.ps | 42 ++++++++++++++++++++++++----------
6bfa55
 psi/interp.c             | 49 ++++++++++++++++++++++++----------------
6bfa55
 2 files changed, 59 insertions(+), 32 deletions(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
6bfa55
index b94f873..a627eec 100644
6bfa55
--- a/Resource/Init/gs_init.ps
6bfa55
+++ b/Resource/Init/gs_init.ps
6bfa55
@@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if
6bfa55
   currentdict /PARANOIDSAFER known or	% PARANOIDSAFER is equivalent
6bfa55
 }
6bfa55
 ifelse def
6bfa55
+
6bfa55
+/SAFERERRORS
6bfa55
+currentdict /NOSAFERERRORS known
6bfa55
+{
6bfa55
+  //false
6bfa55
+}
6bfa55
+{
6bfa55
+  currentdict /SAFERERRORS known
6bfa55
+} ifelse def
6bfa55
+
6bfa55
 currentdict /SHORTERRORS known   /SHORTERRORS exch def
6bfa55
 currentdict /TTYPAUSE known   /TTYPAUSE exch def
6bfa55
 currentdict /WRITESYSTEMDICT known   /WRITESYSTEMDICT exch def
6bfa55
@@ -1137,12 +1147,23 @@ errordict begin
6bfa55
  } bind def
6bfa55
 end		% errordict
6bfa55
 
6bfa55
-% Put all the default handlers in gserrordict
6bfa55
-gserrordict
6bfa55
-errordict {2 index 3 1 roll put} forall
6bfa55
-noaccess pop
6bfa55
-% remove the non-standard errors from errordict
6bfa55
+gserrordict /unknownerror errordict /unknownerror get put
6bfa55
 errordict /unknownerror .undef
6bfa55
+
6bfa55
+/.SAFERERRORLIST ErrorNames def
6bfa55
+/.setsafererrors
6bfa55
+{
6bfa55
+% Put all the requested handlers in gserrordict
6bfa55
+  gserrordict
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
+} bind executeonly odef
6bfa55
+
6bfa55
+SAFERERRORS {.setsafererrors} if
6bfa55
+
6bfa55
 % Define a stable private copy of handleerror that we will always use under
6bfa55
 % JOBSERVER mode.
6bfa55
 /.GShandleerror errordict /handleerror get def
6bfa55
@@ -1774,18 +1795,15 @@ currentdict /.runlibfile .undef
6bfa55
 
6bfa55
 % Bind all the operators defined as procedures.
6bfa55
 /.bindoperators		% binds operators in currentdict
6bfa55
- { % Temporarily disable the typecheck error.
6bfa55
-   errordict /typecheck 2 copy get
6bfa55
-   errordict /typecheck { pop } put	% pop the command
6bfa55
+ {
6bfa55
    currentdict
6bfa55
     { dup type /operatortype eq
6bfa55
-       { % This might be a real operator, so bind might cause a typecheck,
6bfa55
-         % but we've made the error a no-op temporarily.
6bfa55
-         .bind
6bfa55
+       {
6bfa55
+         % This might be a real operator, so bind might cause a typecheck
6bfa55
+         {.bind} .internalstopped pop
6bfa55
        }
6bfa55
       if pop pop
6bfa55
     } forall
6bfa55
-   put
6bfa55
  } def
6bfa55
 DELAYBIND not { .bindoperators } if
6bfa55
 
6bfa55
diff --git a/psi/interp.c b/psi/interp.c
6bfa55
index 1dec9b6..d60c733 100644
6bfa55
--- a/psi/interp.c
6bfa55
+++ b/psi/interp.c
6bfa55
@@ -661,27 +661,18 @@ again:
6bfa55
     if (gs_errorname(i_ctx_p, code, &error_name) < 0)
6bfa55
         return code;            /* out-of-range error code! */
6bfa55
 
6bfa55
-    /*  If LockFilePermissions is true, we only refer to gserrordict, which
6bfa55
-     *  is not accessible to Postcript jobs
6bfa55
+    /*  We refer to gserrordict first, which is not accessible to Postcript jobs
6bfa55
+     *  If we're running with SAFERERRORS all the handlers are copied to gserrordict
6bfa55
+     *  so we'll always find the default one. If not SAFERERRORS, only gs specific
6bfa55
+     *  errors are in gserrordict.
6bfa55
      */
6bfa55
-    if (i_ctx_p->LockFilePermissions) {
6bfa55
-        if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
6bfa55
-              dict_find(perrordict, &error_name, &epref) <= 0))
6bfa55
-            )
6bfa55
-            return code;            /* error name not in errordict??? */
6bfa55
-    }
6bfa55
-    else {
6bfa55
-        /*
6bfa55
-         * For greater Adobe compatibility, only the standard PostScript errors
6bfa55
-         * are defined in errordict; the rest are in gserrordict.
6bfa55
-         */
6bfa55
-        if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
6bfa55
-            (dict_find(perrordict, &error_name, &epref) <= 0 &&
6bfa55
-             (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
6bfa55
-              dict_find(perrordict, &error_name, &epref) <= 0))
6bfa55
-            )
6bfa55
-            return code;            /* error name not in errordict??? */
6bfa55
-    }
6bfa55
+    if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
6bfa55
+        (dict_find(perrordict, &error_name, &epref) <= 0 &&
6bfa55
+         (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
6bfa55
+          dict_find(perrordict, &error_name, &epref) <= 0))
6bfa55
+        )
6bfa55
+        return code;            /* error name not in errordict??? */
6bfa55
+
6bfa55
     doref = *epref;
6bfa55
     epref = &doref;
6bfa55
     /* Push the error object on the operand stack if appropriate. */
6bfa55
@@ -694,6 +685,24 @@ again:
6bfa55
         }
6bfa55
         *osp = *perror_object;
6bfa55
         errorexec_find(i_ctx_p, osp);
6bfa55
+        /* If using SAFER, hand a name object to the error handler, rather than the executable
6bfa55
+         * object/operator itself.
6bfa55
+         */
6bfa55
+        if (i_ctx_p->LockFilePermissions) {
6bfa55
+            code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
6bfa55
+            if (code < 0) {
6bfa55
+                const char *unknownstr = "--unknown--";
6bfa55
+                rlen = strlen(unknownstr);
6bfa55
+                memcpy(buf, unknownstr, rlen);
6bfa55
+            }
6bfa55
+            else {
6bfa55
+                buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
6bfa55
+                rlen += 4;
6bfa55
+            }
6bfa55
+            code = name_ref(imemory, buf, rlen, osp, 1);
6bfa55
+            if (code < 0)
6bfa55
+                make_null(osp);
6bfa55
+        }
6bfa55
     }
6bfa55
     goto again;
6bfa55
 }
6bfa55
-- 
6bfa55
2.17.2
6bfa55
6bfa55
6bfa55
From a6807394bd94b708be24758287b606154daaaed9 Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Tue, 2 Oct 2018 16:02:58 +0100
6bfa55
Subject: [PATCH 4/6] For hidden operators, pass a name object to error
6bfa55
 handler.
6bfa55
6bfa55
In normal operation, Postscript error handlers are passed the object which
6bfa55
triggered the error: this is invariably an operator object.
6bfa55
6bfa55
The issue arises when an error is triggered by an operator which is for internal
6bfa55
use only, and that operator is then passed to the error handler, meaning it
6bfa55
becomes visible to the error handler code.
6bfa55
6bfa55
By converting to a name object, the error message is still valid, but we no
6bfa55
longer expose internal use only operators.
6bfa55
6bfa55
The change in gs_dps1.ps is related to the above: previously an error in
6bfa55
scheck would throw an error against .gcheck, but as .gcheck is now a hidden
6bfa55
operator, it resulted in a name object being passed to the error handler. As
6bfa55
scheck is a 'real' operator, it's better to use the real operator, rather than
6bfa55
the name of an internal, hidden one.
6bfa55
---
6bfa55
 Resource/Init/gs_dps1.ps |  2 +-
6bfa55
 psi/interp.c             | 33 ++++++++++++++++++++++++---------
6bfa55
 2 files changed, 25 insertions(+), 10 deletions(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
6bfa55
index 1182f53..ec5db61 100644
6bfa55
--- a/Resource/Init/gs_dps1.ps
6bfa55
+++ b/Resource/Init/gs_dps1.ps
6bfa55
@@ -21,7 +21,7 @@ level2dict begin
6bfa55
 % ------ Virtual memory ------ %
6bfa55
 
6bfa55
 /currentshared /.currentglobal load def
6bfa55
-/scheck /.gcheck load def
6bfa55
+/scheck {.gcheck} bind odef
6bfa55
 %****** FOLLOWING IS WRONG ******
6bfa55
 /shareddict currentdict /globaldict .knownget not { 20 dict } if def
6bfa55
 
6bfa55
diff --git a/psi/interp.c b/psi/interp.c
6bfa55
index d60c733..6dc0dda 100644
6bfa55
--- a/psi/interp.c
6bfa55
+++ b/psi/interp.c
6bfa55
@@ -677,6 +677,8 @@ again:
6bfa55
     epref = &doref;
6bfa55
     /* Push the error object on the operand stack if appropriate. */
6bfa55
     if (!GS_ERROR_IS_INTERRUPT(code)) {
6bfa55
+        byte buf[260], *bufptr;
6bfa55
+        uint rlen;
6bfa55
         /* Replace the error object if within an oparray or .errorexec. */
6bfa55
         osp++;
6bfa55
         if (osp >= ostop) {
6bfa55
@@ -685,23 +687,36 @@ again:
6bfa55
         }
6bfa55
         *osp = *perror_object;
6bfa55
         errorexec_find(i_ctx_p, osp);
6bfa55
-        /* If using SAFER, hand a name object to the error handler, rather than the executable
6bfa55
-         * object/operator itself.
6bfa55
-         */
6bfa55
-        if (i_ctx_p->LockFilePermissions) {
6bfa55
+
6bfa55
+        if (!r_has_type(osp, t_string) && !r_has_type(osp, t_name)) {
6bfa55
             code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
6bfa55
             if (code < 0) {
6bfa55
                 const char *unknownstr = "--unknown--";
6bfa55
                 rlen = strlen(unknownstr);
6bfa55
                 memcpy(buf, unknownstr, rlen);
6bfa55
+                bufptr = buf;
6bfa55
             }
6bfa55
             else {
6bfa55
-                buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
6bfa55
-                rlen += 4;
6bfa55
+                ref *tobj;
6bfa55
+                bufptr[rlen] = '\0';
6bfa55
+                /* Only pass a name object if the operator doesn't exist in systemdict
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
+                    buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
6bfa55
+                    rlen += 4;
6bfa55
+                    bufptr = buf;
6bfa55
+                }
6bfa55
+                else {
6bfa55
+                    bufptr = NULL;
6bfa55
+                }
6bfa55
+            }
6bfa55
+            if (bufptr) {
6bfa55
+                code = name_ref(imemory, buf, rlen, osp, 1);
6bfa55
+                if (code < 0)
6bfa55
+                    make_null(osp);
6bfa55
             }
6bfa55
-            code = name_ref(imemory, buf, rlen, osp, 1);
6bfa55
-            if (code < 0)
6bfa55
-                make_null(osp);
6bfa55
         }
6bfa55
     }
6bfa55
     goto again;
6bfa55
-- 
6bfa55
2.17.2
6bfa55
6bfa55
6bfa55
From a5a9bf8c6a63aa4ac6874234fe8cd63e72077291 Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Wed, 10 Oct 2018 23:25:51 +0100
6bfa55
Subject: [PATCH 5/6] Bug 699938: .loadfontloop must be an operator
6bfa55
6bfa55
In the fix for Bug 699816, I omitted to make .loadfontloop into an operator, to
6bfa55
better hide .forceundef and .putgstringcopy.
6bfa55
---
6bfa55
 Resource/Init/gs_fonts.ps | 2 +-
6bfa55
 1 file changed, 1 insertion(+), 1 deletion(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
6bfa55
index 89c3ab7..72feff2 100644
6bfa55
--- a/Resource/Init/gs_fonts.ps
6bfa55
+++ b/Resource/Init/gs_fonts.ps
6bfa55
@@ -1148,7 +1148,7 @@ $error /SubstituteFont { } put
6bfa55
 
6bfa55
     } loop              % end of loop
6bfa55
 
6bfa55
- } bind executeonly def % must be bound and hidden for .putgstringcopy
6bfa55
+ } bind executeonly odef % must be bound and hidden for .putgstringcopy
6bfa55
 
6bfa55
 currentdict /.putgstringcopy .undef
6bfa55
 
6bfa55
-- 
6bfa55
2.17.2
6bfa55
6bfa55
6bfa55
From 2756f0efae1d3966989b15a6526c5d80848b5015 Mon Sep 17 00:00:00 2001
6bfa55
From: Chris Liddell <chris.liddell@artifex.com>
6bfa55
Date: Wed, 28 Nov 2018 17:12:08 +0000
6bfa55
Subject: [PATCH 6/6] Bug 700290: Fix problems with DELAYBIND and font
6bfa55
 substitution
6bfa55
6bfa55
Judicious use of immediate evaluation for .setnativefontmapbuilt and
6bfa55
.putgstringcopy to avoid problems with DELAYBIND
6bfa55
---
6bfa55
 Resource/Init/gs_fonts.ps | 9 ++++-----
6bfa55
 1 file changed, 4 insertions(+), 5 deletions(-)
6bfa55
6bfa55
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
6bfa55
index 72feff2..7a57366 100644
6bfa55
--- a/Resource/Init/gs_fonts.ps
6bfa55
+++ b/Resource/Init/gs_fonts.ps
6bfa55
@@ -419,7 +419,7 @@ systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
6bfa55
       } forall
6bfa55
     } if
6bfa55
     % record that we've been run
6bfa55
-    //true .setnativefontmapbuilt
6bfa55
+    //true //.setnativefontmapbuilt
6bfa55
   } ifelse
6bfa55
 } bind def
6bfa55
 currentdict /.setnativefontmapbuilt .forceundef
6bfa55
@@ -1103,7 +1103,7 @@ $error /SubstituteFont { } put
6bfa55
 
6bfa55
                 % Check to make sure the font was actually loaded.
6bfa55
         dup 3 index .fontknownget
6bfa55
-         { dup /PathLoad 4 index .putgstringcopy
6bfa55
+         { dup /PathLoad 4 index //.putgstringcopy
6bfa55
            4 1 roll pop pop pop //true exit
6bfa55
          } if
6bfa55
 
6bfa55
@@ -1115,7 +1115,7 @@ $error /SubstituteFont { } put
6bfa55
          {            % Stack: origfontname fontdirectory path filefontname
6bfa55
            2 index 1 index .fontknownget
6bfa55
             {   % Yes.  Stack: origfontname fontdirectory path filefontname fontdict
6bfa55
-              dup 4 -1 roll /PathLoad exch .putgstringcopy
6bfa55
+              dup 4 -1 roll /PathLoad exch //.putgstringcopy
6bfa55
                       % Stack: origfontname fontdirectory filefontname fontdict
6bfa55
               3 -1 roll pop
6bfa55
                       % Stack: origfontname filefontname fontdict
6bfa55
@@ -1149,8 +1149,7 @@ $error /SubstituteFont { } put
6bfa55
     } loop              % end of loop
6bfa55
 
6bfa55
  } bind executeonly odef % must be bound and hidden for .putgstringcopy
6bfa55
-
6bfa55
-currentdict /.putgstringcopy .undef
6bfa55
+currentdict /.putgstringcopy .forceundef
6bfa55
 
6bfa55
 % Define a procedure to load all known fonts.
6bfa55
 % This isn't likely to be very useful.
6bfa55
-- 
6bfa55
2.17.2
6bfa55