Blame SOURCES/ghostscript-cve-2018-17961.patch

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