| From 0661bf23a5be32973682e17afed4a2f23a8214ba Mon Sep 17 00:00:00 2001 |
| From: Chris Liddell <chris.liddell@artifex.com> |
| Date: Sat, 29 Sep 2018 15:34:55 +0100 |
| Subject: [PATCH 2/5] Bug 699816: Improve hiding of security critical custom |
| operators |
| |
| Make procedures that use .forceput/.forcedef/.forceundef into operators. |
| |
| The result of this is that errors get reported against the "top" operator, |
| rather than the "called" operator within the procedure. |
| |
| For example: |
| /myproc |
| { |
| myop |
| } bind def |
| |
| If 'myop' throws an error, the error handler will be passed the 'myop' |
| operator. Promoting 'myproc' to a operator means the error handler will be |
| passed 'myproc'. |
| |
| CVE: CVE-2018-17961 |
| Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| --- |
| Resource/Init/gs_diskn.ps | 2 +- |
| Resource/Init/gs_dps.ps | 2 +- |
| Resource/Init/gs_fntem.ps | 2 +- |
| Resource/Init/gs_fonts.ps | 10 +++++----- |
| Resource/Init/gs_lev2.ps | 13 +++++++++---- |
| Resource/Init/gs_pdfwr.ps | 2 +- |
| Resource/Init/gs_setpd.ps | 25 +++++++++++++++++-------- |
| Resource/Init/gs_typ32.ps | 14 +++++++++----- |
| Resource/Init/gs_type1.ps | 2 +- |
| Resource/Init/pdf_base.ps | 2 +- |
| Resource/Init/pdf_draw.ps | 10 +++++----- |
| Resource/Init/pdf_font.ps | 8 ++++---- |
| Resource/Init/pdf_main.ps | 4 ++-- |
| Resource/Init/pdf_ops.ps | 8 ++++---- |
| 14 files changed, 61 insertions(+), 43 deletions(-) |
| |
| diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps |
| index 5540715..26ec0b5 100644 |
| --- a/Resource/Init/gs_diskn.ps |
| +++ b/Resource/Init/gs_diskn.ps |
| @@ -53,7 +53,7 @@ systemdict begin |
| exch .setglobal |
| } |
| if |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| % Modify .putdevparams to force regeneration of .searchabledevs list |
| /.putdevparams { |
| diff --git a/Resource/Init/gs_dps.ps b/Resource/Init/gs_dps.ps |
| index cad7056..daf7b0f 100644 |
| --- a/Resource/Init/gs_dps.ps |
| +++ b/Resource/Init/gs_dps.ps |
| @@ -70,7 +70,7 @@ |
| % Save a copy of the initial gstate. |
| //systemdict /savedinitialgstate gstate readonly .forceput |
| .setglobal |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| % Initialize local dictionaries and gstate when creating a new context. |
| % Note that until this completes, we are in the anomalous situation of |
| diff --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps |
| index 3ceee18..c1f7651 100644 |
| --- a/Resource/Init/gs_fntem.ps |
| +++ b/Resource/Init/gs_fntem.ps |
| @@ -408,7 +408,7 @@ currentdict end def |
| exit |
| } loop |
| exch setglobal |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| currentdict end /ProcSet defineresource pop |
| |
| diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps |
| index 45b6613..89c3ab7 100644 |
| --- a/Resource/Init/gs_fonts.ps |
| +++ b/Resource/Init/gs_fonts.ps |
| @@ -377,8 +377,8 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if |
| } |
| {pop} |
| ifelse |
| -} .bind executeonly def |
| -systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec |
| +} .bind executeonly odef |
| +systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt |
| /.buildnativefontmap { % - .buildnativefontmap <bool> |
| systemdict /.nativefontmapbuilt .knownget not |
| { //false} if |
| @@ -419,7 +419,7 @@ systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec |
| } forall |
| } if |
| % record that we've been run |
| - //true //.setnativefontmapbuilt exec |
| + //true .setnativefontmapbuilt |
| } ifelse |
| } bind def |
| currentdict /.setnativefontmapbuilt .forceundef |
| @@ -1103,7 +1103,7 @@ $error /SubstituteFont { } put |
| |
| % Check to make sure the font was actually loaded. |
| dup 3 index .fontknownget |
| - { dup /PathLoad 4 index //.putgstringcopy exec |
| + { dup /PathLoad 4 index .putgstringcopy |
| 4 1 roll pop pop pop //true exit |
| } if |
| |
| @@ -1115,7 +1115,7 @@ $error /SubstituteFont { } put |
| { % Stack: origfontname fontdirectory path filefontname |
| 2 index 1 index .fontknownget |
| { % Yes. Stack: origfontname fontdirectory path filefontname fontdict |
| - dup 4 -1 roll /PathLoad exch //.putgstringcopy exec |
| + dup 4 -1 roll /PathLoad exch .putgstringcopy |
| % Stack: origfontname fontdirectory filefontname fontdict |
| 3 -1 roll pop |
| % Stack: origfontname filefontname fontdict |
| diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps |
| index eee0b9f..a8ed892 100644 |
| --- a/Resource/Init/gs_lev2.ps |
| +++ b/Resource/Init/gs_lev2.ps |
| @@ -163,10 +163,11 @@ end |
| % Set them again to the new values. From here on, we are safe, |
| % since a context switch will consult userparams. |
| .setuserparams |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| /setuserparams { % <dict> setuserparams - |
| - .setuserparams2 |
| + {.setuserparams2} stopped |
| + {/setuserparams load $error /errorname get signalerror} if |
| } .bind odef |
| % Initialize user parameters managed here. |
| /JobName () .definepsuserparam |
| @@ -415,7 +416,9 @@ psuserparams /ProcessDSCComment {.checkprocesscomment} put |
| |
| % VMReclaim and VMThreshold are user parameters. |
| /setvmthreshold { % <int> setvmthreshold - |
| - mark /VMThreshold 2 .argindex .dicttomark .setuserparams2 pop |
| + mark /VMThreshold 2 .argindex .dicttomark {.setuserparams2} stopped |
| + {pop /setvmthreshold load $error /errorname get signalerror} |
| + {pop} ifelse |
| } odef |
| /vmreclaim { % <int> vmreclaim - |
| dup 0 gt { |
| @@ -427,7 +430,9 @@ psuserparams /ProcessDSCComment {.checkprocesscomment} put |
| ifelse |
| } { |
| % VMReclaim userparam controls enable/disable GC |
| - mark /VMReclaim 2 index .dicttomark .setuserparams2 pop |
| + mark /VMReclaim 2 index .dicttomark {.setuserparams2} stopped |
| + {pop /vmreclaim load $error /errorname get signalerror} |
| + {pop} ifelse |
| } ifelse |
| } odef |
| -1 setvmthreshold |
| diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps |
| index fb1c419..58e75d3 100644 |
| --- a/Resource/Init/gs_pdfwr.ps |
| +++ b/Resource/Init/gs_pdfwr.ps |
| @@ -660,7 +660,7 @@ currentdict /.pdfmarkparams .undef |
| { |
| pop |
| } ifelse |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| % Use the DSC processing hook to pass DSC comments to the driver. |
| % We use a pseudo-parameter named DSC whose value is an array: |
| diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps |
| index 8fa7c51..afb4ffa 100644 |
| --- a/Resource/Init/gs_setpd.ps |
| +++ b/Resource/Init/gs_setpd.ps |
| @@ -608,6 +608,20 @@ NOMEDIAATTRS { |
| % in the <failed> dictionary with the policy value, |
| % and we replace the key in the <merged> dictionary with its prior value |
| % (or remove it if it had no prior value). |
| + |
| +% Making this an operator means we can properly hide |
| +% the contents - specifically .forceput |
| +/1Policy |
| +{ |
| + % Roll back the failed request to its previous status. |
| + 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 } |
| + { 3 index exch .undef } |
| + ifelse |
| +} bind executeonly odef |
| + |
| /.policyprocs mark |
| % These procedures are called with the following on the stack: |
| % <orig> <merged> <failed> <Policies> <key> <policy> |
| @@ -631,14 +645,7 @@ NOMEDIAATTRS { |
| /setpagedevice .systemvar /configurationerror signalerror |
| } ifelse |
| } bind |
| - 1 { % Roll back the failed request to its previous status. |
| -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 } |
| - { 3 index exch .undef } |
| - ifelse |
| - } .bind executeonly % must be bound and hidden for .forceput |
| + 1 /1Policy load |
| 7 { % For PageSize only, just impose the request. |
| 1 index /PageSize eq |
| { pop pop 1 index /PageSize 7 put } |
| @@ -646,6 +653,8 @@ SETPDDEBUG { (Rolling back.) = pstack flush } if |
| ifelse |
| } bind |
| .dicttomark readonly def |
| +currentdict /1Policy undef |
| + |
| /.applypolicies % <orig> <merged> <failed> .applypolicies |
| % <orig> <merged'> <failed'> |
| { 1 index /Policies get 1 index |
| diff --git a/Resource/Init/gs_typ32.ps b/Resource/Init/gs_typ32.ps |
| index b6600b0..9150f71 100644 |
| --- a/Resource/Init/gs_typ32.ps |
| +++ b/Resource/Init/gs_typ32.ps |
| @@ -79,15 +79,19 @@ systemdict /.removeglyphs .undef |
| .dicttomark /ProcSet defineresource pop |
| |
| /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse |
| -.cidfonttypes begin |
| - |
| -4 % CIDFontType 4 = FontType 32 |
| -{ dup /FontType 32 .forceput |
| +/CIDFontType4 |
| +{ |
| + dup /FontType 32 .forceput |
| dup /CharStrings 20 dict .forceput |
| 1 index exch .buildfont32 exch pop |
| -} .bind executeonly def % must be bound and hidden for .forceput |
| +} .bind executeonly odef |
| +.cidfonttypes begin |
| + |
| + |
| +4 /CIDFontType4 load def % CIDFontType 4 = FontType 32 |
| |
| end % .cidfonttypes |
| +currentdict /CIDFontType4 .forceundef |
| |
| % Define the BuildGlyph procedure. |
| % Since Type 32 fonts are indexed by CID, there is no BuildChar procedure. |
| diff --git a/Resource/Init/gs_type1.ps b/Resource/Init/gs_type1.ps |
| index efdae48..2935d9c 100644 |
| --- a/Resource/Init/gs_type1.ps |
| +++ b/Resource/Init/gs_type1.ps |
| @@ -283,7 +283,7 @@ currentdict /closesourcedict .undef |
| } if |
| 2 copy /WeightVector exch .forceput |
| .setweightvector |
| -} .bind executeonly def |
| +} .bind executeonly odef |
| end |
| |
| % Register the font types for definefont. |
| diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps |
| index a82a2a3..7ccd4cd 100644 |
| --- a/Resource/Init/pdf_base.ps |
| +++ b/Resource/Init/pdf_base.ps |
| @@ -218,7 +218,7 @@ currentdict /num-chars-dict .undef |
| } ifelse |
| } ifelse |
| } ifelse |
| -} bind executeonly def |
| +} bind executeonly odef |
| /PDFScanRules_true << /PDFScanRules //true >> def |
| /PDFScanRules_null << /PDFScanRules //null >> def |
| /.pdfrun { % <file> <opdict> .pdfrun - |
| diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps |
| index d1b6ac9..c239daf 100644 |
| --- a/Resource/Init/pdf_draw.ps |
| +++ b/Resource/Init/pdf_draw.ps |
| @@ -1158,7 +1158,7 @@ currentdict end readonly def |
| Q |
| PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if |
| PDFfile exch setfileposition |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /.pdfpaintproc { |
| %% Get the /m from pdfopdict (must be present) |
| @@ -1189,7 +1189,7 @@ currentdict end readonly def |
| { |
| switch_to_text_marking_ops |
| } if |
| -}bind executeonly def |
| +}bind executeonly odef |
| |
| /resolvepattern { % <patternstreamdict> resolvepattern <patterndict> |
| % Don't do the resolvestream now: just capture the data |
| @@ -2353,7 +2353,7 @@ currentdict /last-ditch-bpc-csp undef |
| }{ |
| pdfdict /AppearanceNumber 0 .forceput |
| } ifelse |
| -}bind executeonly def |
| +}bind executeonly odef |
| |
| /MakeAppearanceName { |
| pdfdict /AppearanceNumber get |
| @@ -2382,7 +2382,7 @@ currentdict /last-ditch-bpc-csp undef |
| DoForm |
| pdfdict /.PreservePDFForm 3 -1 roll .forceput |
| grestore |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /DoForm { |
| %% save the current value, if its true we will set it to false later, in order |
| @@ -2541,7 +2541,7 @@ currentdict /last-ditch-bpc-csp undef |
| end |
| } if |
| pdfdict /.PreservePDFForm 3 -1 roll .forceput |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /_dops_save 1 array def |
| |
| diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps |
| index feaf0d0..535b14a 100644 |
| --- a/Resource/Init/pdf_font.ps |
| +++ b/Resource/Init/pdf_font.ps |
| @@ -718,7 +718,7 @@ currentdict end readonly def |
| {pop pop pop} |
| ifelse |
| |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| currentdict /.DoToUnicode? .forceundef |
| |
| @@ -1241,7 +1241,7 @@ currentdict /eexec_pdf_param_dict .undef |
| } bdef |
| dup currentdict Encoding .processToUnicode |
| currentdict end .completefont exch pop |
| -} bind executeonly def |
| +} bind executeonly odef |
| /.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'> |
| % Enforce the metrics, in glyph space, to the values found in the PDF Font object |
| % - force wy == 0 (assumed, and not stored in the PDF font) |
| @@ -2026,7 +2026,7 @@ currentdict /CMap_read_dict undef |
| } if |
| /findresource cvx /undefined signalerror |
| } loop |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font> |
| dup /BaseFont get findCIDFont exch pop |
| @@ -2211,7 +2211,7 @@ currentdict /CMap_read_dict undef |
| /Type0 //buildType0 |
| /Type1 //buildType1 |
| /MMType1 //buildType1 |
| - /Type3 //buildType3 |
| + /Type3 /buildType3 load |
| /TrueType //buildTrueType |
| /CIDFontType0 //buildCIDType0 |
| /CIDFontType2 //buildCIDType2 |
| diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps |
| index 09f8735..c823e69 100644 |
| --- a/Resource/Init/pdf_main.ps |
| +++ b/Resource/Init/pdf_main.ps |
| @@ -660,7 +660,7 @@ currentdict /runpdfstring .undef |
| } forall |
| pop |
| } ifelse |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| currentdict /pdf_collection_files .undef |
| |
| @@ -2715,7 +2715,7 @@ currentdict /PDF2PS_matrix_key undef |
| .setglobal |
| /RepairedAnError exch def |
| /Repaired exch def |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| % Display the contents of a page (including annotations). |
| /showpagecontents { % <pagedict> showpagecontents - |
| diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps |
| index c45fc51..8672d61 100644 |
| --- a/Resource/Init/pdf_ops.ps |
| +++ b/Resource/Init/pdf_ops.ps |
| @@ -193,7 +193,7 @@ currentdict /gput_always_allow .undef |
| pdfformaterror |
| } ifelse |
| } if |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| % Save PDF gstate |
| /qstate { % - qstate <qstate> |
| @@ -451,7 +451,7 @@ currentdict /gput_always_allow .undef |
| %% a gsave, so we haven't copied it to /self, if we don't do that here |
| %% then transparent annotations cause an invalid access error. |
| currentdict //nodict eq {/self dup load end 5 dict begin def} if |
| -} bind executeonly def |
| +} bind executeonly odef |
| /AIS { .setalphaisshape } bind executeonly def |
| /BM { |
| /.setblendmode where { |
| @@ -1077,7 +1077,7 @@ end readonly def |
| pdfopdict /v {inside_text_v} bind .forceput |
| pdfopdict /y {inside_text_y} bind .forceput |
| pdfopdict /re {inside_text_re} bind .forceput |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /switch_to_normal_marking_ops { |
| pdfopdict /m {normal_m} bind .forceput |
| @@ -1086,7 +1086,7 @@ end readonly def |
| pdfopdict /v {normal_v} bind .forceput |
| pdfopdict /y {normal_y} bind .forceput |
| pdfopdict /re {normal_re} bind .forceput |
| -} bind executeonly def |
| +} bind executeonly odef |
| |
| /BT { |
| currentdict /TextSaveMatrix known { |
| -- |
| 2.7.4 |
| |