| From 9096beaa4451c12dd2a2caf000658fbac4a5bcdf Mon Sep 17 00:00:00 2001 |
| From: Ken Sharp <ken.sharp@artifex.com> |
| Date: Mon, 5 Nov 2018 15:51:32 +0800 |
| Subject: [PATCH] Make .forceput unavailable from '.policyprocs' helper |
| dictionary |
| |
| Bug #69963 "1Policy is a dangerous operator, any callers should be odef" |
| |
| Leaving the .policyprocs dictionary with a procedure which is a simple |
| wrapper for .forceput effectively leaves .forceput available. |
| |
| It seems that the only reason to have .policyprocs is to minimise the |
| code in .applypolicies, so we can remove the dictionary and put the |
| code straight into .applypolicies, which we can then bind and make |
| executeonly, which hides the .forceput. Also, since we don't need |
| .applypolicies after startup, we can undefine that from systemdict too. |
| |
| While we're here, review all the uses of .force* to make certain that |
| there are no other similar cases. This showed a few places where we |
| hadn't made a function executeonly, so do that too. Its probably not |
| required, since I'm reasonably sure its impossible to load those |
| functions as packed arrays (they are all defined as operators), but lets |
| have a belt and braces approach, the additional time cost is negligible. |
| |
| CVE: CVE-2018-18284 |
| 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_epsf.ps | 2 +- |
| Resource/Init/gs_fonts.ps | 4 +- |
| Resource/Init/gs_init.ps | 2 +- |
| Resource/Init/gs_setpd.ps | 100 ++++++++++++++++++++++++---------------------- |
| 6 files changed, 58 insertions(+), 54 deletions(-) |
| |
| diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps |
| index 26ec0b5..fd694bc 100644 |
| --- a/Resource/Init/gs_diskn.ps |
| +++ b/Resource/Init/gs_diskn.ps |
| @@ -61,7 +61,7 @@ systemdict begin |
| % doesn't get run enough to justify the complication |
| //.putdevparams |
| //systemdict /.searchabledevs .forceundef |
| -} .bind odef % must be bound and hidden for .forceundef |
| +} .bind executeonly odef % must be bound and hidden for .forceundef |
| |
| % ------ extend filenameforall to handle wildcards in %dev% part of pattern -------% |
| /filenameforall { |
| diff --git a/Resource/Init/gs_dps.ps b/Resource/Init/gs_dps.ps |
| index daf7b0f..00c14d5 100644 |
| --- a/Resource/Init/gs_dps.ps |
| +++ b/Resource/Init/gs_dps.ps |
| @@ -124,7 +124,7 @@ |
| /savedinitialgstate .systemvar setgstate gsave |
| % Wrap up. |
| end .setglobal |
| -} odef |
| +} bind executeonly odef |
| |
| % Check whether an object is a procedure. |
| /.proccheck { % <obj> .proccheck <bool> |
| diff --git a/Resource/Init/gs_epsf.ps b/Resource/Init/gs_epsf.ps |
| index e4037d9..2d0f677 100644 |
| --- a/Resource/Init/gs_epsf.ps |
| +++ b/Resource/Init/gs_epsf.ps |
| @@ -31,7 +31,7 @@ |
| /EPSBoundingBoxState 5 def |
| /EPSBoundingBoxSetState { |
| //systemdict /EPSBoundingBoxState 3 -1 roll .forceput |
| -} .bind odef % .forceput must be bound and hidden |
| +} .bind executeonly odef % .forceput must be bound and hidden |
| |
| % Parse 4 numbers for a bounding box |
| /EPSBoundingBoxParse { % (llx lly urx ury) -- llx lly urx ury true OR false |
| diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps |
| index 72feff2..803faca 100644 |
| --- a/Resource/Init/gs_fonts.ps |
| +++ b/Resource/Init/gs_fonts.ps |
| @@ -583,7 +583,7 @@ buildfontdict 3 /.buildfont3 cvx put |
| } bind def |
| /.setloadingfont { |
| //systemdict /.loadingfont 3 -1 roll .forceput |
| -} .bind odef % .forceput must be bound and hidden |
| +} .bind executeonly odef % .forceput must be bound and hidden |
| /.loadfont |
| { % Some buggy fonts leave extra junk on the stack, |
| % so we have to make a closure that records the stack depth |
| @@ -1012,7 +1012,7 @@ $error /SubstituteFont { } put |
| dup length string copy |
| .forceput setglobal |
| } ifelse |
| -} .bind odef % must be bound and hidden for .forceput |
| +} .bind executeonly odef % must be bound and hidden for .forceput |
| |
| % Attempt to load a font from a file. |
| /.tryloadfont { % <fontname> .tryloadfont <font> true |
| diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| index f4c1053..07ee968 100644 |
| --- a/Resource/Init/gs_init.ps |
| +++ b/Resource/Init/gs_init.ps |
| @@ -2230,7 +2230,7 @@ SAFER { .setsafeglobal } if |
| /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile |
| /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams |
| /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath |
| - /.type /.writecvs /.setSMask /.currentSMask /.countexecstack /.execstack |
| + /.type /.writecvs /.setSMask /.currentSMask /.countexecstack /.execstack /.applypolicies |
| |
| % Used by a free user in the Library of Congress. Apparently this is used to |
| % draw a partial page, which is then filled in by the results of a barcode |
| diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps |
| index afb4ffa..7c076ad 100644 |
| --- a/Resource/Init/gs_setpd.ps |
| +++ b/Resource/Init/gs_setpd.ps |
| @@ -609,6 +609,23 @@ NOMEDIAATTRS { |
| % and we replace the key in the <merged> dictionary with its prior value |
| % (or remove it if it had no prior value). |
| |
| +% These procedures are called with the following on the stack: |
| +% <orig> <merged> <failed> <Policies> <key> <policy> |
| +% They are expected to consume the top 2 operands. |
| +% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) |
| +% the same as 0, i.e., we signal an error. |
| +/0Policy { % Set errorinfo and signal a configurationerror. |
| + NOMEDIAATTRS { |
| + % NOMEDIAATTRS means that the default policy is 7... |
| + pop 2 index exch 7 put |
| + } { |
| + pop dup 4 index exch get 2 array astore |
| + $error /errorinfo 3 -1 roll put |
| + cleartomark |
| + /setpagedevice .systemvar /configurationerror signalerror |
| + } ifelse |
| +} bind executeonly odef |
| + |
| % Making this an operator means we can properly hide |
| % the contents - specifically .forceput |
| /1Policy |
| @@ -617,59 +634,46 @@ 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 } |
| - { 3 index exch .undef } |
| + { 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> |
| -% They are expected to consume the top 2 operands. |
| -% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) |
| -% the same as 0, i.e., we signal an error. |
| -% |
| -% M. Sweet, Easy Software Products: |
| -% |
| -% Define NOMEDIAATTRS to turn off the default (but unimplementable) media |
| -% selection policies for setpagedevice. This is used by CUPS to support |
| -% the standard Adobe media attributes. |
| - 0 { % Set errorinfo and signal a configurationerror. |
| - NOMEDIAATTRS { |
| - % NOMEDIAATTRS means that the default policy is 7... |
| - pop 2 index exch 7 put |
| - } { |
| - pop dup 4 index exch get 2 array astore |
| - $error /errorinfo 3 -1 roll put |
| - cleartomark |
| - /setpagedevice .systemvar /configurationerror signalerror |
| - } ifelse |
| - } bind |
| - 1 /1Policy load |
| - 7 { % For PageSize only, just impose the request. |
| - 1 index /PageSize eq |
| - { pop pop 1 index /PageSize 7 put } |
| - { .policyprocs 0 get exec } |
| - ifelse |
| - } bind |
| -.dicttomark readonly def |
| -currentdict /1Policy undef |
| +/7Policy { % For PageSize only, just impose the request. |
| + 1 index /PageSize eq |
| + { pop pop 1 index /PageSize 7 put } |
| + { .policyprocs 0 get exec } |
| + ifelse |
| +} bind executeonly odef |
| |
| /.applypolicies % <orig> <merged> <failed> .applypolicies |
| % <orig> <merged'> <failed'> |
| - { 1 index /Policies get 1 index |
| - { type /integertype eq |
| - { pop % already processed |
| - } |
| - { 2 copy .knownget not { 1 index /PolicyNotFound get } if |
| - % Stack: <orig> <merged> <failed> <Policies> <key> |
| - % <policy> |
| - .policyprocs 1 index .knownget not { .policyprocs 0 get } if exec |
| - } |
| - ifelse |
| - } |
| - forall pop |
| - } bind def |
| +{ |
| + 1 index /Policies get 1 index |
| + { type /integertype eq |
| + { |
| + pop % already processed |
| + }{ |
| + 2 copy .knownget not { 1 index /PolicyNotFound get } if |
| + % Stack: <orig> <merged> <failed> <Policies> <key> |
| + % <policy> |
| + dup 1 eq { |
| + 1Policy |
| + }{ |
| + dup 7 eq { |
| + 7Policy |
| + }{ |
| + 0Policy |
| + } ifelse |
| + } ifelse |
| + } ifelse |
| + } |
| + forall pop |
| +} bind executeonly odef |
| + |
| +currentdict /0Policy undef |
| +currentdict /1Policy undef |
| +currentdict /7Policy undef |
| |
| % Prepare to present parameters to the device, by spreading them onto the |
| % operand stack and removing any that shouldn't be presented. |
| @@ -1006,7 +1010,7 @@ SETPDDEBUG { (Installing.) = pstack flush } if |
| .postinstall |
| } ifelse |
| setglobal % return to original VM allocation mode |
| -} odef |
| +} bind executeonly odef |
| |
| % We break out the code after calling the Install procedure into a |
| % separate procedure, since it is executed even if Install causes an error. |
| -- |
| 2.7.4 |
| |