rebase to latest upstream version 9.27

security fixes added for:
  CVE-2019-14811 (bug #1747908)
  CVE-2019-14812 (bug #1747907)
  CVE-2019-14813 (bug #1747906)
  CVE-2019-14817 (bug #1747909)
This commit is contained in:
Martin Osvald 2019-09-19 11:24:57 +02:00
parent 31934cab83
commit 34e4475551
9 changed files with 288 additions and 1481 deletions

1
.gitignore vendored
View File

@ -53,3 +53,4 @@ ghostscript-8.71.tar.xz
/ghostscript-9.24.tar.xz
/ghostscript-9.25.tar.xz
/ghostscript-9.26.tar.xz
/ghostscript-9.27.tar.xz

View File

@ -0,0 +1,56 @@
From 885444fcbe10dc42787ecb76686c8ee4dd33bf33 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Tue, 20 Aug 2019 10:10:28 +0100
Subject: make .forceput inaccessible
Bug #701343, #701344, #701345
More defensive programming. We don't want people to access .forecput
even though it is no longer sufficient to bypass SAFER. The exploit
in #701343 didn't work anyway because of earlier work to stop the error
handler being used, but nevertheless, prevent access to .forceput from
.setuserparams2.
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 4cc7f820f..0fd416465 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -158,7 +158,7 @@ end
{
pop pop
} ifelse
- } forall
+ } executeonly forall
% A context switch might have occurred during the above loop,
% causing the interpreter-level parameters to be reset.
% Set them again to the new values. From here on, we are safe,
@@ -229,9 +229,9 @@ end
{ pop pop
}
ifelse
- }
+ } executeonly
forall pop
-} .bind odef
+} .bind executeonly odef
% Initialize the passwords.
% NOTE: the names StartJobPassword and SystemParamsPassword are known to
diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
index c158a8faf..422e66e1a 100644
--- a/Resource/Init/gs_pdfwr.ps
+++ b/Resource/Init/gs_pdfwr.ps
@@ -658,11 +658,11 @@ currentdict /.pdfmarkparams .undef
systemdict /.pdf_hooked_DSC_Creator //true .forceput
} executeonly if
pop
- } if
+ } executeonly if
} {
pop
} ifelse
- }
+ } executeonly
{
pop
} ifelse

View File

@ -0,0 +1,216 @@
From 3b65a4569a7b8da4678890b842e368daf85d6887 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Wed, 21 Aug 2019 10:10:51 +0100
Subject: [PATCH] PDF interpreter - review .forceput security
Bug #701450 "Safer Mode Bypass by .forceput Exposure in .pdfexectoken"
By abusing the error handler it was possible to get the PDFDEBUG portion
of .pdfexectoken, which uses .forceput left readable.
Add an executeonly appropriately to make sure that clause isn't readable
no mstter what.
Review all the uses of .forceput searching for similar cases, add
executeonly as required to secure those. All cases in the PostScript
support files seem to be covered already.
---
Resource/Init/pdf_base.ps | 2 +-
Resource/Init/pdf_draw.ps | 14 +++++++-------
Resource/Init/pdf_font.ps | 23 ++++++++++++-----------
Resource/Init/pdf_main.ps | 6 +++---
Resource/Init/pdf_ops.ps | 11 ++++++-----
5 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
index 1a218f4..cffde5c 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -157,7 +157,7 @@ currentdict /num-chars-dict .undef
{
dup ==only () = flush
} ifelse % PDFSTEP
- } if % PDFDEBUG
+ } executeonly if % PDFDEBUG
2 copy .knownget {
exch pop exch pop exch pop exec
} {
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index e18a7c2..0a3924c 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -501,8 +501,8 @@ end
( Output may be incorrect.\n) pdfformaterror
//pdfdict /.gs_warning_issued //true .forceput
PDFSTOPONERROR { /gs /undefined signalerror } if
- } if
- }
+ } executeonly if
+ } executeonly
ifelse
} bind executeonly def
@@ -1142,7 +1142,7 @@ currentdict end readonly def
.setglobal
pdfformaterror
} executeonly ifelse
- }
+ } executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
@@ -1150,8 +1150,8 @@ currentdict end readonly def
pdfformaterror
} executeonly ifelse
end
- } ifelse
- } loop
+ } executeonly ifelse
+ } executeonly loop
{
(\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n)
//pdfdict /.Qqwarning_issued .knownget
@@ -1165,14 +1165,14 @@ currentdict end readonly def
.setglobal
pdfformaterror
} executeonly ifelse
- }
+ } executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
- } if
+ } executeonly if
pop
% restore pdfemptycount
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index 9fb85f6..357ba30 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -677,7 +677,7 @@ currentdict end readonly def
currentglobal 2 index dup gcheck setglobal
/FontInfo 5 dict dup 5 1 roll .forceput
setglobal
- } if
+ } executeonly if
dup /GlyphNames2Unicode .knownget not {
//true % No existing G2U, make one
} {
@@ -701,9 +701,9 @@ currentdict end readonly def
} if
PDFDEBUG {
(.processToUnicode end) =
- } if
- } if
- } stopped
+ } executeonly if
+ } executeonly if
+ } executeonly stopped
{
.dstackdepth 1 countdictstack 1 sub
{pop end} for
@@ -1233,19 +1233,20 @@ currentdict /eexec_pdf_param_dict .undef
//pdfdict /.Qqwarning_issued //true .forceput
} executeonly if
Q
- } repeat
+ } executeonly repeat
Q
- } PDFfile fileposition 2 .execn % Keep pdfcount valid.
+ } executeonly PDFfile fileposition 2 .execn % Keep pdfcount valid.
PDFfile exch setfileposition
- } ifelse
- } {
+ } executeonly ifelse
+ } executeonly
+ {
% PDF Type 3 fonts don't use .notdef
% d1 implementation adjusts the width as needed
0 0 0 0 0 0
pdfopdict /d1 get exec
} ifelse
end end
- } bdef
+ } executeonly bdef
dup currentdict Encoding .processToUnicode
currentdict end .completefont exch pop
} bind executeonly odef
@@ -2045,9 +2046,9 @@ currentdict /CMap_read_dict undef
(Will continue, but content may be missing.) = flush
} ifelse
} if
- } if
+ } executeonly if
/findresource cvx /undefined signalerror
- } loop
+ } executeonly loop
} bind executeonly odef
/buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 5305ea6..a59e63c 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -2749,15 +2749,15 @@ currentdict /PDF2PS_matrix_key undef
.setglobal
pdfformaterror
} executeonly ifelse
- }
+ } executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
- } if
- } if
+ } executeonly if
+ } executeonly if
pop
count PDFexecstackcount sub { pop } repeat
(after exec) VMDEBUG
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index 285e582..6c1f100 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -186,14 +186,14 @@ currentdict /gput_always_allow .undef
.setglobal
pdfformaterror
} executeonly ifelse
- }
+ } executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
- } if
+ } executeonly if
} bind executeonly odef
% Save PDF gstate
@@ -440,11 +440,12 @@ currentdict /gput_always_allow .undef
dup type /booleantype eq {
.currentSMask type /dicttype eq {
.currentSMask /Processed 2 index .forceput
+ } executeonly
+ {
+ .setSMask
+ }ifelse
} executeonly
{
- .setSMask
- }ifelse
- }{
.setSMask
}ifelse
--
2.20.1

View File

@ -1,615 +0,0 @@
From 779664d79f0dca77dbdd66b753679bfd12dcbbad Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Mon, 26 Nov 2018 18:01:25 +0000
Subject: [PATCH 1/4] Have gs_cet.ps run from gs_init.ps
Previously gs_cet.ps was run on the command line, to set up the interpreter
state so our output more closely matches the example output for the QL CET
tests.
Allow a -dCETMODE command line switch, which will cause gs_init.ps to run the
file directly.
This works better for gpdl as it means the changes are made in the intial
interpreter state, rather than after initialisation is complete.
This also means adding a definition of the default procedure for black
generation and under color removal (rather it being defined in-line in
.setdefaultbgucr
Also, add a check so gs_cet.ps only runs once - if we try to run it a second
time, we'll just skip over the file, flushing through to the end.
---
Resource/Init/gs_cet.ps | 11 ++++++++++-
Resource/Init/gs_init.ps | 13 ++++++++++++-
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/Resource/Init/gs_cet.ps b/Resource/Init/gs_cet.ps
index d3e1686..75534bb 100644
--- a/Resource/Init/gs_cet.ps
+++ b/Resource/Init/gs_cet.ps
@@ -1,6 +1,11 @@
%!PS
% Set defaults for Ghostscript to match Adobe CPSI behaviour for CET
+systemdict /product get (PhotoPRINT SE 5.0v2) readonly eq
+{
+ (%END GS_CET) .skipeof
+} if
+
% do this in the server level so it is persistent across jobs
//true 0 startjob not {
(*** Warning: CET startup is not in server default) = flush
@@ -25,7 +30,9 @@ currentglobal //true setglobal
/UNROLLFORMS true def
-{ } bind dup
+(%.defaultbgrucrproc) cvn { } bind def
+
+(%.defaultbgrucrproc) cvn load dup
setblackgeneration
setundercolorremoval
0 array cvx readonly dup dup dup setcolortransfer
@@ -109,3 +116,5 @@ userdict /.smoothness currentsmoothness put
% end of slightly nasty hack to give consistent cluster results
//false 0 startjob pop % re-enter encapsulated mode
+
+%END GS_CET
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index d9a0829..152e98a 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -1544,10 +1544,18 @@ setpacking
% any-part-of-pixel rule.
0.5 .setfilladjust
} bind def
+
% Set the default screen and BG/UCR.
+% We define the proc here, rather than inline in .setdefaultbgucr
+% for the benefit of gs_cet.ps so jobs that do anything that causes
+% .setdefaultbgucr to be called will still get the redefined proc
+% in gs_cet.ps
+(%.defaultbgrucrproc) cvn { pop 0 } def
+
/.setdefaultbgucr {
systemdict /setblackgeneration known {
- { pop 0 } dup setblackgeneration setundercolorremoval
+ (%.defaultbgrucrproc) cvn load dup
+ setblackgeneration setundercolorremoval
} if
} bind def
/.useloresscreen { % - .useloresscreen <bool>
@@ -2499,4 +2507,7 @@ WRITESYSTEMDICT {
% be 'true' in some cases.
userdict /AGM_preserve_spots //false put
+systemdict /CETMODE .knownget
+{ { (gs_cet.ps) runlibfile } if } if
+
% The interpreter will run the initial procedure (start).
--
2.20.1
From e8acf6d1aa1fc92f453175509bfdad6f2b12dc73 Mon Sep 17 00:00:00 2001
From: Nancy Durgin <nancy.durgin@artifex.com>
Date: Thu, 14 Feb 2019 10:09:00 -0800
Subject: [PATCH 2/4] Undef /odef in gs_init.ps
Made a new temporary utility function in gs_cet.ps (.odef) to use instead
of /odef. This makes it fine to undef odef with all the other operators in
gs_init.ps
This punts the bigger question of what to do with .makeoperator, but it
doesn't make the situation any worse than it already was.
---
Resource/Init/gs_cet.ps | 10 ++++++++--
Resource/Init/gs_init.ps | 1 +
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Resource/Init/gs_cet.ps b/Resource/Init/gs_cet.ps
index 75534bb..dbc5c4e 100644
--- a/Resource/Init/gs_cet.ps
+++ b/Resource/Init/gs_cet.ps
@@ -1,6 +1,10 @@
%!PS
% Set defaults for Ghostscript to match Adobe CPSI behaviour for CET
+/.odef { % <name> <proc> odef -
+ 1 index exch .makeoperator def
+} bind def
+
systemdict /product get (PhotoPRINT SE 5.0v2) readonly eq
{
(%END GS_CET) .skipeof
@@ -93,8 +97,8 @@ userdict /.smoothness currentsmoothness put
} {
/setsmoothness .systemvar /typecheck signalerror
} ifelse
-} bind odef
-/currentsmoothness { userdict /.smoothness get } bind odef % for 09-55.PS, 09-57.PS .
+} bind //.odef exec
+/currentsmoothness { userdict /.smoothness get } bind //.odef exec % for 09-55.PS, 09-57.PS .
% slightly nasty hack to give consistent cluster results
/ofnfa systemdict /filenameforall get def
@@ -113,6 +117,8 @@ userdict /.smoothness currentsmoothness put
} ifelse
ofnfa
} bind def
+
+currentdict /.odef undef
% end of slightly nasty hack to give consistent cluster results
//false 0 startjob pop % re-enter encapsulated mode
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 152e98a..723c447 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2263,6 +2263,7 @@ SAFER { .setsafeglobal } if
/.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams
/.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath /.currentoutputdevice
/.type /.writecvs /.setSMask /.currentSMask /.needinput /.countexecstack /.execstack /.applypolicies
+ /odef
% 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
--
2.20.1
From 205591753126802da850ada6511a0ff8411aa287 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Thu, 14 Feb 2019 10:20:03 -0800
Subject: [PATCH 3/4] Fix bug 700585: Restrict superexec and remove it from
internals and gs_cet.ps
Also while changing things, restructure the CETMODE so that it will
work with -dSAFER. The gs_cet.ps is now run when we are still at save
level 0 with systemdict writeable. Allows us to undefine .makeoperator
and .setCPSImode internal operators after CETMODE is handled.
Change previous uses of superexec to using .forceput (with the usual
.bind executeonly to hide it).
---
Resource/Init/gs_cet.ps | 39 ++++++++++++++-------------------------
Resource/Init/gs_dps1.ps | 2 +-
Resource/Init/gs_fonts.ps | 8 ++++----
Resource/Init/gs_init.ps | 38 +++++++++++++++++++++++++++-----------
Resource/Init/gs_ttf.ps | 8 ++++----
Resource/Init/gs_type1.ps | 6 +++---
6 files changed, 53 insertions(+), 48 deletions(-)
diff --git a/Resource/Init/gs_cet.ps b/Resource/Init/gs_cet.ps
index dbc5c4e..58da404 100644
--- a/Resource/Init/gs_cet.ps
+++ b/Resource/Init/gs_cet.ps
@@ -1,37 +1,28 @@
-%!PS
% Set defaults for Ghostscript to match Adobe CPSI behaviour for CET
-/.odef { % <name> <proc> odef -
- 1 index exch .makeoperator def
-} bind def
-
+% skip if we've already run this -- based on fake "product"
systemdict /product get (PhotoPRINT SE 5.0v2) readonly eq
{
(%END GS_CET) .skipeof
} if
-% do this in the server level so it is persistent across jobs
-//true 0 startjob not {
- (*** Warning: CET startup is not in server default) = flush
-} if
+% Note: this must be run at save level 0 and when systemdict is writeable
+currentglobal //true setglobal
+systemdict dup dup dup
+/version (3017.102) readonly .forceput % match CPSI 3017.102
+/product (PhotoPRINT SE 5.0v2) readonly .forceput % match CPSI 3017.102
+/revision 0 put % match CPSI 3017.103 Tek shows revision 5
+/serialnumber dup {233640} readonly .makeoperator .forceput % match CPSI 3017.102 Tek shows serialnumber 1401788461
+
+systemdict /.odef { % <name> <proc> odef -
+ 1 index exch //.makeoperator def
+} .bind .forceput % this will be undefined at the end
300 .sethiresscreen % needed for language switch build since it
% processes gs_init.ps BEFORE setting the resolution
0 array 0 setdash % CET 09-08 wants local setdash
-currentglobal //true setglobal
-
-{
- systemdict dup dup dup
- /version (3017.102) readonly put % match CPSI 3017.102
- /product (PhotoPRINT SE 5.0v2) readonly put % match CPSI 3017.102
- /revision 0 put % match CPSI 3017.103 Tek shows revision 5
- /serialnumber dup {233640} readonly .makeoperator put % match CPSI 3017.102 Tek shows serialnumber 1401788461
- systemdict /deviceinfo undef % for CET 20-23-1
-% /UNROLLFORMS true put % CET files do unreasonable things inside forms
-} 1183615869 internaldict /superexec get exec
-
/UNROLLFORMS true def
(%.defaultbgrucrproc) cvn { } bind def
@@ -118,9 +109,7 @@ userdict /.smoothness currentsmoothness put
ofnfa
} bind def
-currentdict /.odef undef
-% end of slightly nasty hack to give consistent cluster results
-
-//false 0 startjob pop % re-enter encapsulated mode
+systemdict /.odef .undef
+% end of slightly nasty hack to give consistent cluster results
%END GS_CET
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index b75ea14..01475ac 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -85,7 +85,7 @@ level2dict begin
% definition, copy it into the local directory.
//systemdict /SharedFontDirectory .knownget
{ 1 index .knownget
- { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+ { //.FontDirectory 2 index 3 -1 roll .forceput } % readonly
if
}
if
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index c13a2fc..787dc07 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -512,11 +512,11 @@ buildfontdict 3 /.buildfont3 cvx put
% the font in LocalFontDirectory.
.currentglobal
{ //systemdict /LocalFontDirectory .knownget
- { 2 index 2 index { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+ { 2 index 2 index .forceput } % readonly
if
}
if
- dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
+ dup //.FontDirectory 4 -2 roll .forceput % readonly
% If the font originated as a resource, register it.
currentfile .currentresourcefile eq { dup .registerfont } if
readonly
@@ -1179,13 +1179,13 @@ currentdict /.putgstringcopy .undef
//.FontDirectory 1 index known not {
2 dict dup /FontName 3 index put
dup /FontType 1 put
- //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
+ //.FontDirectory 3 1 roll //.forceput exec % readonly
} {
pop
} ifelse
} forall
} forall
- }
+ } executeonly % hide .forceput
FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined
% Install initial fonts from Fontmap.
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 723c447..7ab8c6c 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2194,9 +2194,6 @@ SAFER { .setsafeglobal } if
/.endtransparencygroup % transparency-example.ps
/.setdotlength % Bug687720.ps
/.sort /.setdebug /.mementolistnewblocks /getenv
-
- /.makeoperator /.setCPSImode % gs_cet.ps, this won't work on cluster with -dSAFER
-
/unread
]
{systemdict exch .forceundef} forall
@@ -2276,7 +2273,6 @@ SAFER { .setsafeglobal } if
% Used by our own test suite files
%/.fileposition %image-qa.ps
- %/.makeoperator /.setCPSImode % gs_cet.ps
% Either our code uses these in ways which mean they can't be undefined, or they are used directly by
% test files/utilities, or engineers expressed a desire to keep them visible.
@@ -2464,6 +2460,16 @@ end
/vmreclaim where
{ pop NOGC not { 2 .vmreclaim 0 vmreclaim } if
} if
+
+% Do this before systemdict is locked (see below for additional CETMODE setup using gs_cet.ps)
+systemdict /CETMODE .knownget {
+ {
+ (gs_cet.ps) runlibfile
+ } if
+} if
+systemdict /.makeoperator .undef % must be after gs_cet.ps
+systemdict /.setCPSImode .undef % must be after gs_cet.ps
+
DELAYBIND not {
systemdict /.bindnow .undef % We only need this for DELAYBIND
systemdict /.forcecopynew .undef % remove temptation
@@ -2472,16 +2478,29 @@ DELAYBIND not {
systemdict /.forceundef .undef % ditto
} if
-% Move superexec to internaldict if superexec is defined.
-systemdict /superexec .knownget {
- 1183615869 internaldict /superexec 3 -1 roll put
- systemdict /superexec .undef
+% Move superexec to internaldict if superexec is defined. (Level 2 or later)
+systemdict /superexec known {
+ % restrict superexec to single known use by PScript5.dll
+ % We could do this only for SAFER mode, but internaldict and superexec are
+ % not very well documented, and we don't want them to be used.
+ 1183615869 internaldict /superexec {
+ 2 index /Private eq % first check for typical use in PScript5.dll
+ 1 index length 1 eq and % expected usage is: dict /Private <value> {put} superexec
+ 1 index 0 get systemdict /put get eq and
+ {
+ //superexec exec % the only usage we allow
+ } {
+ /superexec load /invalidaccess signalerror
+ } ifelse
+ } bind cvx executeonly put
+ systemdict /superexec .undef % get rid of the dangerous (unrestricted) operator
} if
% Can't remove this one until the last minute :-)
DELAYBIND not {
systemdict /.undef .undef
} if
+
WRITESYSTEMDICT {
SAFER {
(\n *** WARNING - you have selected SAFER, indicating you want Ghostscript\n) print
@@ -2508,7 +2527,4 @@ WRITESYSTEMDICT {
% be 'true' in some cases.
userdict /AGM_preserve_spots //false put
-systemdict /CETMODE .knownget
-{ { (gs_cet.ps) runlibfile } if } if
-
% The interpreter will run the initial procedure (start).
diff --git a/Resource/Init/gs_ttf.ps b/Resource/Init/gs_ttf.ps
index 05943c5..064b6c8 100644
--- a/Resource/Init/gs_ttf.ps
+++ b/Resource/Init/gs_ttf.ps
@@ -1421,7 +1421,7 @@ mark
TTFDEBUG { (\n1 setting alias: ) print dup ==only
( to be the same as ) print 2 index //== exec } if
- 7 index 2 index 3 -1 roll exch //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+ 7 index 2 index 3 -1 roll exch .forceput
} forall
pop pop pop
}
@@ -1439,7 +1439,7 @@ mark
exch pop
TTFDEBUG { (\n2 setting alias: ) print 1 index ==only
( to use glyph index: ) print dup //== exec } if
- 5 index 3 1 roll //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+ 5 index 3 1 roll .forceput
//false
}
{
@@ -1456,7 +1456,7 @@ mark
{ % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) gindex(integer)
TTFDEBUG { (\3 nsetting alias: ) print 1 index ==only
( to be index: ) print dup //== exec } if
- exch pop 5 index 3 1 roll //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+ exch pop 5 index 3 1 roll .forceput
}
{
pop pop
@@ -1486,7 +1486,7 @@ mark
} ifelse
]
TTFDEBUG { (Encoding: ) print dup === flush } if
-} bind def
+} .bind executeonly odef % hides .forceput
% to be removed 9.09......
currentdict /postalias undef
diff --git a/Resource/Init/gs_type1.ps b/Resource/Init/gs_type1.ps
index 96e1ced..61f5269 100644
--- a/Resource/Init/gs_type1.ps
+++ b/Resource/Init/gs_type1.ps
@@ -116,7 +116,7 @@
{ % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname aglname
CFFDEBUG { (\nsetting alias: ) print dup ==only
( to be the same as glyph: ) print 1 index //== exec } if
- 3 index exch 3 index //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+ 3 index exch 3 index .forceput
% scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname
}
{pop} ifelse
@@ -135,7 +135,7 @@
3 1 roll pop pop
} if
pop
- dup /.AGLprocessed~GS //true //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse
+ dup /.AGLprocessed~GS //true .forceput
} if
%% We need to excute the C .buildfont1 in a stopped context so that, if there
@@ -148,7 +148,7 @@
{//.buildfont1} stopped
4 3 roll .setglobal
{//.buildfont1 $error /errorname get signalerror} if
- } bind def
+ } .bind executeonly def % hide .forceput
% If the diskfont feature isn't included, define a dummy .loadfontdict.
/.loadfontdict where
--
2.20.1
From d683d1e6450d74619e6277efeebfc222d9a5cb91 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Sun, 24 Feb 2019 22:01:04 -0800
Subject: [PATCH 4/4] Bug 700585: Obliterate "superexec". We don't need it, nor
do any known apps.
We were under the impression that the Windows driver 'PScript5.dll' used
superexec, but after testing with our extensive suite of PostScript file,
and analysis of the PScript5 "Adobe CoolType ProcSet, it does not appear
that this operator is needed anymore. Get rid of superexec and all of the
references to it, since it is a potential security hole.
---
Resource/Init/gs_init.ps | 18 ------------------
psi/icontext.c | 1 -
psi/icstate.h | 1 -
psi/zcontrol.c | 30 ------------------------------
psi/zdict.c | 6 ++----
psi/zgeneric.c | 3 +--
6 files changed, 3 insertions(+), 56 deletions(-)
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 7ab8c6c..af881b5 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2478,24 +2478,6 @@ DELAYBIND not {
systemdict /.forceundef .undef % ditto
} if
-% Move superexec to internaldict if superexec is defined. (Level 2 or later)
-systemdict /superexec known {
- % restrict superexec to single known use by PScript5.dll
- % We could do this only for SAFER mode, but internaldict and superexec are
- % not very well documented, and we don't want them to be used.
- 1183615869 internaldict /superexec {
- 2 index /Private eq % first check for typical use in PScript5.dll
- 1 index length 1 eq and % expected usage is: dict /Private <value> {put} superexec
- 1 index 0 get systemdict /put get eq and
- {
- //superexec exec % the only usage we allow
- } {
- /superexec load /invalidaccess signalerror
- } ifelse
- } bind cvx executeonly put
- systemdict /superexec .undef % get rid of the dangerous (unrestricted) operator
-} if
-
% Can't remove this one until the last minute :-)
DELAYBIND not {
systemdict /.undef .undef
diff --git a/psi/icontext.c b/psi/icontext.c
index 1fbe486..7462ea3 100644
--- a/psi/icontext.c
+++ b/psi/icontext.c
@@ -151,7 +151,6 @@ context_state_alloc(gs_context_state_t ** ppcst,
pcst->rand_state = rand_state_initial;
pcst->usertime_total = 0;
pcst->keep_usertime = false;
- pcst->in_superexec = 0;
pcst->plugin_list = 0;
make_t(&pcst->error_object, t__invalid);
{ /*
diff --git a/psi/icstate.h b/psi/icstate.h
index 4c6a14d..1009d85 100644
--- a/psi/icstate.h
+++ b/psi/icstate.h
@@ -54,7 +54,6 @@ struct gs_context_state_s {
long usertime_total; /* total accumulated usertime, */
/* not counting current time if running */
bool keep_usertime; /* true if context ever executed usertime */
- int in_superexec; /* # of levels of superexec */
/* View clipping is handled in the graphics state. */
ref error_object; /* t__invalid or error object from operator */
ref userparams; /* t_dictionary */
diff --git a/psi/zcontrol.c b/psi/zcontrol.c
index 0362cf4..dc813e8 100644
--- a/psi/zcontrol.c
+++ b/psi/zcontrol.c
@@ -158,34 +158,6 @@ zexecn(i_ctx_t *i_ctx_p)
return o_push_estack;
}
-/* <obj> superexec - */
-static int end_superexec(i_ctx_t *);
-static int
-zsuperexec(i_ctx_t *i_ctx_p)
-{
- os_ptr op = osp;
- es_ptr ep;
-
- check_op(1);
- if (!r_has_attr(op, a_executable))
- return 0; /* literal object just gets pushed back */
- check_estack(2);
- ep = esp += 3;
- make_mark_estack(ep - 2, es_other, end_superexec); /* error case */
- make_op_estack(ep - 1, end_superexec); /* normal case */
- ref_assign(ep, op);
- esfile_check_cache();
- pop(1);
- i_ctx_p->in_superexec++;
- return o_push_estack;
-}
-static int
-end_superexec(i_ctx_t *i_ctx_p)
-{
- i_ctx_p->in_superexec--;
- return 0;
-}
-
/* <array> <executable> .runandhide <obj> */
/* before executing <executable>, <array> is been removed from */
/* the operand stack and placed on the execstack with attributes */
@@ -971,8 +943,6 @@ const op_def zcontrol3_op_defs[] = {
{"0%loop_continue", loop_continue},
{"0%repeat_continue", repeat_continue},
{"0%stopped_push", stopped_push},
- {"1superexec", zsuperexec},
- {"0%end_superexec", end_superexec},
{"2.runandhide", zrunandhide},
{"0%end_runandhide", end_runandhide},
op_def_end(0)
diff --git a/psi/zdict.c b/psi/zdict.c
index b0deaaa..e2e525d 100644
--- a/psi/zdict.c
+++ b/psi/zdict.c
@@ -212,8 +212,7 @@ zundef(i_ctx_t *i_ctx_p)
int code;
check_type(*op1, t_dictionary);
- if (i_ctx_p->in_superexec == 0)
- check_dict_write(*op1);
+ check_dict_write(*op1);
code = idict_undef(op1, op);
if (code < 0 && code != gs_error_undefined) /* ignore undefined error */
return code;
@@ -504,8 +503,7 @@ zsetmaxlength(i_ctx_t *i_ctx_p)
int code;
check_type(*op1, t_dictionary);
- if (i_ctx_p->in_superexec == 0)
- check_dict_write(*op1);
+ check_dict_write(*op1);
check_type(*op, t_integer);
if (op->value.intval < 0)
return_error(gs_error_rangecheck);
diff --git a/psi/zgeneric.c b/psi/zgeneric.c
index 8048e28..d4edddb 100644
--- a/psi/zgeneric.c
+++ b/psi/zgeneric.c
@@ -204,8 +204,7 @@ zput(i_ctx_t *i_ctx_p)
switch (r_type(op2)) {
case t_dictionary:
- if (i_ctx_p->in_superexec == 0)
- check_dict_write(*op2);
+ check_dict_write(*op2);
{
int code = idict_put(op2, op1, op);
--
2.20.1

View File

@ -1,56 +0,0 @@
From ed9fcd95bb01f0768bf273b2526732e381202319 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 20 Feb 2019 09:54:28 +0000
Subject: [PATCH 1/2] Bug 700576: Make a transient proc executeonly (in
DefineResource).
This prevents access to .forceput
Solution originally suggested by cbuissar@redhat.com.
---
Resource/Init/gs_res.ps | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
index d9b3459..b646329 100644
--- a/Resource/Init/gs_res.ps
+++ b/Resource/Init/gs_res.ps
@@ -425,7 +425,7 @@ status {
% so we have to use .forcedef here.
/.Instances 1 index .forcedef % Category dict is read-only
} executeonly if
- }
+ } executeonly
{ .LocalInstances dup //.emptydict eq
{ pop 3 dict localinstancedict Category 2 index put
}
--
2.20.1
From a82601e8f95a2f2147f3b3b9e44ec2b8f3a6be8b Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Fri, 22 Feb 2019 12:28:23 +0000
Subject: [PATCH 2/2] Bug 700576(redux): an extra transient proc needs
executeonly'ed.
---
Resource/Init/gs_res.ps | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
index b646329..8c1f29f 100644
--- a/Resource/Init/gs_res.ps
+++ b/Resource/Init/gs_res.ps
@@ -437,7 +437,7 @@ status {
% Now make the resource value read-only.
0 2 copy get { readonly } .internalstopped pop
dup 4 1 roll put exch pop exch pop
- }
+ } executeonly
{ /defineresource cvx /typecheck signaloperror
}
ifelse
--
2.20.1

View File

@ -1,770 +0,0 @@
From 13b0a36f8181db66a91bcc8cea139998b53a8996 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 5 Dec 2018 12:22:13 +0000
Subject: [PATCH 1/4] Sanitize op stack for error conditions
We save the stacks to an array and store the array for the error handler to
access.
For SAFER, we traverse the array, and deep copy any op arrays (procedures). As
we make these copies, we check for operators that do *not* exist in systemdict,
when we find one, we replace the operator with a name object (of the form
"/--opname--").
---
psi/int.mak | 3 +-
psi/interp.c | 8 ++++++
psi/istack.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
psi/istack.h | 3 ++
4 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/psi/int.mak b/psi/int.mak
index 6ab5bf0..6b349cb 100644
--- a/psi/int.mak
+++ b/psi/int.mak
@@ -204,7 +204,8 @@ $(PSOBJ)iparam.$(OBJ) : $(PSSRC)iparam.c $(GH)\
$(PSOBJ)istack.$(OBJ) : $(PSSRC)istack.c $(GH) $(memory__h)\
$(ierrors_h) $(gsstruct_h) $(gsutil_h)\
$(ialloc_h) $(istack_h) $(istkparm_h) $(istruct_h) $(iutil_h) $(ivmspace_h)\
- $(store_h) $(INT_MAK) $(MAKEDIRS)
+ $(store_h) $(icstate_h) $(iname_h) $(dstack_h) $(idict_h) \
+ $(INT_MAK) $(MAKEDIRS)
$(PSCC) $(PSO_)istack.$(OBJ) $(C_) $(PSSRC)istack.c
$(PSOBJ)iutil.$(OBJ) : $(PSSRC)iutil.c $(GH) $(math__h) $(memory__h) $(string__h)\
diff --git a/psi/interp.c b/psi/interp.c
index 6dc0dda..aa5779c 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -761,6 +761,7 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
uint size = ref_stack_count(pstack) - skip;
uint save_space = ialloc_space(idmemory);
int code, i;
+ ref *safety, *safe;
if (size > 65535)
size = 65535;
@@ -778,6 +779,13 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
make_null(&arr->value.refs[i]);
}
}
+ if (pstack == &o_stack && dict_find_string(systemdict, "SAFETY", &safety) > 0 &&
+ dict_find_string(safety, "safe", &safe) > 0 && r_has_type(safe, t_boolean) &&
+ safe->value.boolval == true) {
+ code = ref_stack_array_sanitize(i_ctx_p, arr, arr);
+ if (code < 0)
+ return code;
+ }
ialloc_set_space(idmemory, save_space);
return code;
}
diff --git a/psi/istack.c b/psi/istack.c
index 8fe151f..f1a3e51 100644
--- a/psi/istack.c
+++ b/psi/istack.c
@@ -27,6 +27,10 @@
#include "iutil.h"
#include "ivmspace.h" /* for local/global test */
#include "store.h"
+#include "icstate.h"
+#include "iname.h"
+#include "dstack.h"
+#include "idict.h"
/* Forward references */
static void init_block(ref_stack_t *pstack, const ref *pblock_array,
@@ -294,6 +298,80 @@ ref_stack_store_check(const ref_stack_t *pstack, ref *parray, uint count,
return 0;
}
+int
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr)
+{
+ int i, code;
+ ref obj, arr2;
+ ref *pobj2;
+ gs_memory_t *mem = (gs_memory_t *)idmemory->current;
+
+ if (!r_is_array(sarr) || !r_has_type(darr, t_array))
+ return_error(gs_error_typecheck);
+
+ for (i = 0; i < r_size(sarr); i++) {
+ code = array_get(mem, sarr, i, &obj);
+ if (code < 0)
+ make_null(&obj);
+ switch(r_type(&obj)) {
+ case t_operator:
+ {
+ int index = op_index(&obj);
+
+ if (index > 0 && index < op_def_count) {
+ const byte *data = (const byte *)(op_index_def(index)->oname + 1);
+ if (dict_find_string(systemdict, (const char *)data, &pobj2) <= 0) {
+ byte *s = gs_alloc_bytes(mem, strlen((char *)data) + 5, "ref_stack_array_sanitize");
+ if (s) {
+ s[0] = '\0';
+ strcpy((char *)s, "--");
+ strcpy((char *)s + 2, (char *)data);
+ strcpy((char *)s + strlen((char *)data) + 2, "--");
+ }
+ else {
+ s = (byte *)data;
+ }
+ code = name_ref(imemory, s, strlen((char *)s), &obj, 1);
+ if (code < 0) make_null(&obj);
+ if (s != data)
+ gs_free_object(mem, s, "ref_stack_array_sanitize");
+ }
+ }
+ else {
+ make_null(&obj);
+ }
+ ref_assign(darr->value.refs + i, &obj);
+ break;
+ }
+ case t_array:
+ case t_shortarray:
+ case t_mixedarray:
+ {
+ int attrs = r_type_attrs(&obj) & (a_write | a_read | a_execute | a_executable);
+ /* We only want to copy executable arrays */
+ if (attrs & (a_execute | a_executable)) {
+ code = ialloc_ref_array(&arr2, attrs, r_size(&obj), "ref_stack_array_sanitize");
+ if (code < 0) {
+ make_null(&arr2);
+ }
+ else {
+ code = ref_stack_array_sanitize(i_ctx_p, &obj, &arr2);
+ }
+ ref_assign(darr->value.refs + i, &arr2);
+ }
+ else {
+ ref_assign(darr->value.refs + i, &obj);
+ }
+ break;
+ }
+ default:
+ ref_assign(darr->value.refs + i, &obj);
+ }
+ }
+ return 0;
+}
+
+
/*
* Store the top 'count' elements of a stack, starting 'skip' elements below
* the top, into an array, with or without store/undo checking. age=-1 for
diff --git a/psi/istack.h b/psi/istack.h
index 051dcbe..54be405 100644
--- a/psi/istack.h
+++ b/psi/istack.h
@@ -129,6 +129,9 @@ int ref_stack_store(const ref_stack_t *pstack, ref *parray, uint count,
uint skip, int age, bool check,
gs_dual_memory_t *idmem, client_name_t cname);
+int
+ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr);
+
/*
* Pop the top N elements off a stack.
* The number must not exceed the number of elements in use.
--
2.20.1
From 2db98f9c66135601efb103d8db7d020a672308db Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 13 Dec 2018 15:28:34 +0000
Subject: [PATCH 2/4] Any transient procedures that call .force* operators
(i.e. for conditionals or loops) make them executeonly.
---
Resource/Init/gs_diskn.ps | 2 +-
Resource/Init/gs_dps1.ps | 4 ++--
Resource/Init/gs_fntem.ps | 4 ++--
Resource/Init/gs_fonts.ps | 12 ++++++------
Resource/Init/gs_init.ps | 4 ++--
Resource/Init/gs_lev2.ps | 11 ++++++-----
Resource/Init/gs_pdfwr.ps | 2 +-
Resource/Init/gs_res.ps | 4 ++--
Resource/Init/gs_setpd.ps | 2 +-
Resource/Init/pdf_base.ps | 13 ++++++++-----
Resource/Init/pdf_draw.ps | 16 +++++++++-------
Resource/Init/pdf_font.ps | 6 +++---
Resource/Init/pdf_main.ps | 4 ++--
Resource/Init/pdf_ops.ps | 7 ++++---
14 files changed, 49 insertions(+), 42 deletions(-)
diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps
index fd694bc..8bf2054 100644
--- a/Resource/Init/gs_diskn.ps
+++ b/Resource/Init/gs_diskn.ps
@@ -51,7 +51,7 @@ systemdict begin
mark 5 1 roll ] mark exch { { } forall } forall ]
//systemdict /.searchabledevs 2 index .forceput
exch .setglobal
- }
+ } executeonly
if
} .bind executeonly odef % must be bound and hidden for .forceput
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index ec5db61..4fae283 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -78,7 +78,7 @@ level2dict begin
.currentglobal
{ % Current mode is global; delete from local directory too.
//systemdict /LocalFontDirectory .knownget
- { 1 index .forceundef } % LocalFontDirectory is readonly
+ { 1 index .forceundef } executeonly % LocalFontDirectory is readonly
if
}
{ % Current mode is local; if there was a shadowed global
@@ -126,7 +126,7 @@ level2dict begin
}
ifelse
} forall
- pop counttomark 2 idiv { .forceundef } repeat pop % readonly
+ pop counttomark 2 idiv { .forceundef } executeonly repeat pop % readonly
}
if
//SharedFontDirectory exch .forcecopynew pop
diff --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps
index c1f7651..6eb672a 100644
--- a/Resource/Init/gs_fntem.ps
+++ b/Resource/Init/gs_fntem.ps
@@ -401,12 +401,12 @@ currentdict end def
.forceput % FontInfo can be read-only.
pop % bool <font>
exit
- } if
+ } executeonly if
dup /FontInfo get % bool <font> <FI>
/GlyphNames2Unicode /Unicode /Decoding findresource
.forceput % FontInfo can be read-only.
exit
- } loop
+ } executeonly loop
exch setglobal
} .bind executeonly odef % must be bound and hidden for .forceput
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 803faca..290da0c 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -374,7 +374,7 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
/.setnativefontmapbuilt { % set whether we've been run
dup type /booleantype eq {
systemdict exch /.nativefontmapbuilt exch .forceput
- }
+ } executeonly
{pop}
ifelse
} .bind executeonly odef
@@ -1007,11 +1007,11 @@ $error /SubstituteFont { } put
{ 2 index gcheck currentglobal
2 copy eq {
pop pop .forceput
- } {
+ } executeonly {
5 1 roll setglobal
dup length string copy
.forceput setglobal
- } ifelse
+ } executeonly ifelse
} .bind executeonly odef % must be bound and hidden for .forceput
% Attempt to load a font from a file.
@@ -1084,7 +1084,7 @@ $error /SubstituteFont { } put
.FontDirectory 3 index .forceundef % readonly
1 index (r) file .loadfont .FontDirectory exch
/.setglobal .systemvar exec
- }
+ } executeonly
{ .loadfont .FontDirectory
}
ifelse
@@ -1105,7 +1105,7 @@ $error /SubstituteFont { } put
dup 3 index .fontknownget
{ dup /PathLoad 4 index .putgstringcopy
4 1 roll pop pop pop //true exit
- } if
+ } executeonly if
% Maybe the file had a different FontName.
% See if we can get a FontName from the file, and if so,
@@ -1134,7 +1134,7 @@ $error /SubstituteFont { } put
ifelse % Stack: origfontname fontdict
exch pop //true exit
% Stack: fontdict
- }
+ } executeonly
if pop % Stack: origfontname fontdirectory path
}
if pop pop % Stack: origfontname
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index d733124..56c0bd2 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2357,7 +2357,7 @@ SAFER { .setsafeglobal } if
% Update the copy of the user parameters.
mark .currentuserparams counttomark 2 idiv {
userparams 3 1 roll .forceput % userparams is read-only
- } repeat pop
+ } executeonly repeat pop
% Turn on idiom recognition, if available.
currentuserparams /IdiomRecognition known {
/IdiomRecognition //true .definepsuserparam
@@ -2376,7 +2376,7 @@ SAFER { .setsafeglobal } if
% Remove real system params from pssystemparams.
mark .currentsystemparams counttomark 2 idiv {
pop pssystemparams exch .forceundef
- } repeat pop
+ } executeonly repeat pop
} if
% Set up AlignToPixels :
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 44fe619..0f0d573 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -154,7 +154,8 @@ end
% protect top level of parameters that we copied
dup type dup /arraytype eq exch /stringtype eq or { readonly } if
/userparams .systemvar 3 1 roll .forceput % userparams is read-only
- } {
+ } executeonly
+ {
pop pop
} ifelse
} forall
@@ -224,7 +225,7 @@ end
% protect top level parameters that we copied
dup type dup /arraytype eq exch /stringtype eq or { readonly } if
//pssystemparams 3 1 roll .forceput % pssystemparams is read-only
- }
+ } executeonly
{ pop pop
}
ifelse
@@ -934,7 +935,7 @@ mark
dup /PaintProc get
1 index /Implementation known not {
1 index dup /Implementation //null .forceput readonly pop
- } if
+ } executeonly if
exec
}.bind odef
@@ -958,7 +959,7 @@ mark
dup /PaintProc get
1 index /Implementation known not {
1 index dup /Implementation //null .forceput readonly pop
- } if
+ } executeonly if
/UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not
%% [CTM] <<Form>> PaintProc .beginform -
{
@@ -1005,7 +1006,7 @@ mark
%% Form dictioanry using the /Implementation key).
1 dict dup /FormID 4 -1 roll put
1 index exch /Implementation exch .forceput readonly pop
- }
+ } executeonly
ifelse
}
{
diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
index 58e75d3..b425103 100644
--- a/Resource/Init/gs_pdfwr.ps
+++ b/Resource/Init/gs_pdfwr.ps
@@ -650,7 +650,7 @@ currentdict /.pdfmarkparams .undef
} ifelse
} bind .makeoperator .forceput
systemdict /.pdf_hooked_DSC_Creator //true .forceput
- } if
+ } executeonly if
pop
} if
} {
diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
index 8eb8bb0..d9b3459 100644
--- a/Resource/Init/gs_res.ps
+++ b/Resource/Init/gs_res.ps
@@ -152,7 +152,7 @@ setglobal
% use .forceput / .forcedef later to replace the dummy,
% empty .Instances dictionary with the real one later.
readonly
- } {
+ }{
/defineresource cvx /typecheck signaloperror
} ifelse
} bind executeonly odef
@@ -424,7 +424,7 @@ status {
% As noted above, Category dictionaries are read-only,
% so we have to use .forcedef here.
/.Instances 1 index .forcedef % Category dict is read-only
- } if
+ } executeonly if
}
{ .LocalInstances dup //.emptydict eq
{ pop 3 dict localinstancedict Category 2 index put
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
index e22597e..7875d1f 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -634,7 +634,7 @@ NOMEDIAATTRS {
SETPDDEBUG { (Rolling back.) = pstack flush } if
3 index 2 index 3 -1 roll .forceput
4 index 1 index .knownget
- { 4 index 3 1 roll .forceput }
+ { 4 index 3 1 roll .forceput } executeonly
{ 3 index exch .undef }
ifelse
} bind executeonly odef
diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
index b45e980..7312729 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -130,26 +130,29 @@ currentdict /num-chars-dict .undef
/.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ?
PDFDEBUG {
- pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if
+ pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if
PDFSTEP {
pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
PDFSTEPcount 1 gt {
pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
- } {
+ } executeonly
+ {
dup ==only
( step # ) print PDFtokencount =only
( ? ) print flush 1 //false .outputpage
(%stdin) (r) file 255 string readline {
token {
exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput
- } {
+ } executeonly
+ {
pdfdict /PDFSTEPcount 1 .forceput
- } ifelse % token
+ } executeonly ifelse % token
} {
pop /PDFSTEP //false def % EOF on stdin
} ifelse % readline
} ifelse % PDFSTEPcount > 1
- } {
+ } executeonly
+ {
dup ==only () = flush
} ifelse % PDFSTEP
} if % PDFDEBUG
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index 6b0ba93..40c6ac8 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -1118,14 +1118,14 @@ currentdict end readonly def
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
}
{
currentglobal pdfdict gcheck .setglobal
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
end
} ifelse
} loop
@@ -1141,14 +1141,14 @@ currentdict end readonly def
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
}
{
currentglobal pdfdict gcheck .setglobal
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
} if
pop
@@ -2350,9 +2350,10 @@ currentdict /last-ditch-bpc-csp undef
/IncrementAppearanceNumber {
pdfdict /AppearanceNumber .knownget {
1 add pdfdict /AppearanceNumber 3 -1 roll .forceput
- }{
+ } executeonly
+ {
pdfdict /AppearanceNumber 0 .forceput
- } ifelse
+ } executeonly ifelse
}bind executeonly odef
/MakeAppearanceName {
@@ -2510,7 +2511,8 @@ currentdict /last-ditch-bpc-csp undef
%% want to preserve it.
pdfdict /.PreservePDFForm false .forceput
/q cvx /execform cvx 5 -2 roll
- }{
+ } executeonly
+ {
/q cvx /PDFexecform cvx 5 -2 roll
} ifelse
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index bea9ea9..4cd62b9 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -714,7 +714,7 @@ currentdict end readonly def
pop pop pop
currentdict /.stackdepth .forceundef
currentdict /.dstackdepth .forceundef
- }
+ } executeonly
{pop pop pop}
ifelse
@@ -1232,7 +1232,7 @@ currentdict /eexec_pdf_param_dict .undef
(\n **** Warning: Type 3 glyph has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n)
pdfformatwarning
pdfdict /.Qqwarning_issued //true .forceput
- } if
+ } executeonly if
Q
} repeat
Q
@@ -2016,7 +2016,7 @@ currentdict /CMap_read_dict undef
/CIDFallBack /CIDFont findresource
} if
exit
- } if
+ } executeonly if
} if
} if
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 00da47a..37e69b3 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -2701,14 +2701,14 @@ currentdict /PDF2PS_matrix_key undef
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
}
{
currentglobal pdfdict gcheck .setglobal
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
} if
} if
pop
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index 8672d61..aa09641 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -184,14 +184,14 @@ currentdict /gput_always_allow .undef
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
}
{
currentglobal pdfdict gcheck .setglobal
pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
- } ifelse
+ } executeonly ifelse
} if
} bind executeonly odef
@@ -439,7 +439,8 @@ currentdict /gput_always_allow .undef
dup type /booleantype eq {
.currentSMask type /dicttype eq {
.currentSMask /Processed 2 index .forceput
- } {
+ } executeonly
+ {
.setSMask
}ifelse
}{
--
2.20.1
From 99f13091a3f309bdc95d275ea9fec10bb9f42d9a Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Sat, 15 Dec 2018 09:08:32 +0000
Subject: [PATCH 3/4] Bug700317: Fix logic for an older change
Unlike almost every other function in gs, dict_find_string() returns 1 on
success 0 or <0 on failure. The logic for this case was wrong.
---
psi/interp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/psi/interp.c b/psi/interp.c
index aa5779c..f6c45bb 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -703,7 +703,7 @@ again:
* i.e. it's an internal operator we have hidden
*/
code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
- if (code < 0) {
+ if (code <= 0) {
buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
rlen += 4;
bufptr = buf;
--
2.20.1
From 59d8f4deef90c1598ff50616519d5576756b4495 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Tue, 18 Dec 2018 10:42:10 +0000
Subject: [PATCH 4/4] Harden some uses of .force* operators
by adding a few immediate evalutions
---
Resource/Init/gs_dps1.ps | 4 ++--
Resource/Init/gs_fonts.ps | 20 ++++++++++----------
Resource/Init/gs_init.ps | 6 +++---
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index 4fae283..b75ea14 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -74,7 +74,7 @@ level2dict begin
} odef
% undefinefont has to take local/global VM into account.
/undefinefont % <fontname> undefinefont -
- { .FontDirectory 1 .argindex .forceundef % FontDirectory is readonly
+ { //.FontDirectory 1 .argindex .forceundef % FontDirectory is readonly
.currentglobal
{ % Current mode is global; delete from local directory too.
//systemdict /LocalFontDirectory .knownget
@@ -85,7 +85,7 @@ level2dict begin
% definition, copy it into the local directory.
//systemdict /SharedFontDirectory .knownget
{ 1 index .knownget
- { .FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+ { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
if
}
if
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 290da0c..c13a2fc 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -516,7 +516,7 @@ buildfontdict 3 /.buildfont3 cvx put
if
}
if
- dup .FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
+ dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
% If the font originated as a resource, register it.
currentfile .currentresourcefile eq { dup .registerfont } if
readonly
@@ -943,7 +943,7 @@ $error /SubstituteFont { } put
% Try to find a font using only the present contents of Fontmap.
/.tryfindfont { % <fontname> .tryfindfont <font> true
% <fontname> .tryfindfont false
- .FontDirectory 1 index .fontknownget
+ //.FontDirectory 1 index .fontknownget
{ % Already loaded
exch pop //true
}
@@ -975,7 +975,7 @@ $error /SubstituteFont { } put
{ % Font with a procedural definition
exec % The procedure will load the font.
% Check to make sure this really happened.
- .FontDirectory 1 index .knownget
+ //.FontDirectory 1 index .knownget
{ exch pop //true exit }
if
}
@@ -1081,11 +1081,11 @@ $error /SubstituteFont { } put
% because it's different depending on language level.
.currentglobal exch /.setglobal .systemvar exec
% Remove the fake definition, if any.
- .FontDirectory 3 index .forceundef % readonly
- 1 index (r) file .loadfont .FontDirectory exch
+ //.FontDirectory 3 index .forceundef % readonly
+ 1 index (r) file .loadfont //.FontDirectory exch
/.setglobal .systemvar exec
} executeonly
- { .loadfont .FontDirectory
+ { .loadfont //.FontDirectory
}
ifelse
% Stack: fontname fontfilename fontdirectory
@@ -1119,8 +1119,8 @@ $error /SubstituteFont { } put
% Stack: origfontname fontdirectory filefontname fontdict
3 -1 roll pop
% Stack: origfontname filefontname fontdict
- dup /FontName get dup FontDirectory exch .forceundef
- GlobalFontDirectory exch .forceundef
+ dup /FontName get dup //.FontDirectory exch .forceundef
+ /GlobalFontDirectory .systemvar exch .forceundef
dup length dict .copydict dup 3 index /FontName exch put
2 index exch definefont
exch
@@ -1176,10 +1176,10 @@ currentdict /.putgstringcopy .undef
{
{
pop dup type /stringtype eq { cvn } if
- .FontDirectory 1 index known not {
+ //.FontDirectory 1 index known not {
2 dict dup /FontName 3 index put
dup /FontType 1 put
- .FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
+ //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse % readonly
} {
pop
} ifelse
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 56c0bd2..d9a0829 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -1168,8 +1168,8 @@ errordict /unknownerror .undef
}ifelse
}forall
noaccess pop
- systemdict /.setsafeerrors .forceundef
- systemdict /.SAFERERRORLIST .forceundef
+ //systemdict /.setsafeerrors .forceundef
+ //systemdict /.SAFERERRORLIST .forceundef
} bind executeonly odef
SAFERERRORS {.setsafererrors} if
@@ -2114,7 +2114,7 @@ currentdict /tempfilepaths undef
/.locksafe {
.locksafe_userparams
- systemdict /getenv {pop //false} .forceput
+ //systemdict /getenv {pop //false} .forceput
% setpagedevice has the side effect of clearing the page, but
% we will just document that. Using setpagedevice keeps the device
% properties and pagedevice .LockSafetyParams in agreement even
--
2.20.1

View File

@ -1,28 +0,0 @@
From fae21f1668d2b44b18b84cf0923a1d5f3008a696 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Tue, 4 Dec 2018 21:31:31 +0000
Subject: subclassing devices - fix put_image method
The subclassing devices need to change the 'memory device' parameter to
be the child device, when its the same as the subclassing device.
Otherwise we end up trying to access the child device's memory pointers
in the subclassing device, which may not contain valid copies of
those pointers.
diff --git a/base/gdevsclass.c b/base/gdevsclass.c
index d9c85d2e4..51092585a 100644
--- a/base/gdevsclass.c
+++ b/base/gdevsclass.c
@@ -797,7 +797,10 @@ int default_subclass_put_image(gx_device *dev, gx_device *mdev, const byte **buf
int alpha_plane_index, int tag_plane_index)
{
if (dev->child)
- return dev_proc(dev->child, put_image)(dev->child, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
+ if (dev == mdev)
+ return dev_proc(dev->child, put_image)(dev->child, dev->child, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
+ else
+ return dev_proc(dev->child, put_image)(dev->child, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
return 0;
}

View File

@ -42,8 +42,8 @@
Name: ghostscript
Summary: Interpreter for PostScript language & PDF
Version: 9.26
Release: 6%{?dist}
Version: 9.27
Release: 1%{?dist}
License: AGPLv3+
@ -93,11 +93,9 @@ BuildRequires: libXt-devel
# Upstream patches -- official upstream patches released by upstream since the
# ---------------- last rebase that are necessary for any reason:
#Patch000: example000.patch
Patch000: ghostscript-cve-2019-6116.patch
Patch001: ghostscript-subclassing-devices-fix-put_image-method.patch
Patch002: ghostscript-cve-2019-3835.patch
Patch003: ghostscript-cve-2019-3838.patch
Patch004: ghostscript-cve-2019-10216.patch
Patch000: ghostscript-cve-2019-10216.patch
Patch001: ghostscript-cve-2019-14811-14812-14813.patch
Patch002: ghostscript-cve-2019-14817.patch
# Downstream patches -- these should be always included when doing rebase:
@ -260,10 +258,7 @@ It will be removed once the Fedora 28 has reached EOL (End Of Life).
%autosetup -N -S git
# Libraries that we already have packaged in Fedora (see Build Requirements):
rm -rf cups/libs freetype ijs jbig2dec jpeg lcms2* libpng openjpeg tiff zlib
# Yeah, not actually needed in Fedora (^_^):
rm -rf windows
rm -rf cups/libs freetype ijs jbig2dec jpeg lcms2* libpng openjpeg tiff windows zlib
# Add the remaining source code to the initial commit, patch the source code:
git add --all --force .
@ -466,6 +461,14 @@ done
# =============================================================================
%changelog
* Fri Sep 06 2019 Martin Osvald <mosvald@redhat.com> - 9.27-1
- rebase to latest upstream version 9.27
- security fixes added for:
- CVE-2019-14811 (bug #1747908)
- CVE-2019-14812 (bug #1747907)
- CVE-2019-14813 (bug #1747906)
- CVE-2019-14817 (bug #1747909)
* Mon Aug 12 2019 Martin Osvald <mosvald@redhat.com> - 9.26-6
- Fix for CVE-2019-10216 added

View File

@ -1 +1 @@
SHA512 (ghostscript-9.26.tar.xz) = 3ddb83029edf32282357bf606f4045a9ac73df6543cd423cfad09158ec12ada083a0dbb5aac3b73ae24cbc6c1e9d7574257a5c1fae63ba8776fbb00150ef2a3e
SHA512 (ghostscript-9.27.tar.xz) = 5e67ad45a80f01c6ef0eabb1c76dfa8fb6e7f0fde8d82fd5daaf12f370c288a672f8fa69c74d9e30255582267e9a906e4e8b13655f8d993fefdfc8dbdb5d5401