Browse Source

ghostscript package update

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 3 years ago
parent
commit
c185ec073e
  1. 22
      SOURCES/ghostscript-9.23-100-run-dvipdf-securely.patch
  2. 54
      SOURCES/ghostscript-9.25-101-reenable-cups-filters.patch
  3. 842
      SOURCES/ghostscript-cve-2018-17961.patch
  4. 289
      SOURCES/ghostscript-cve-2018-18073.patch
  5. 240
      SOURCES/ghostscript-cve-2018-18284.patch
  6. 153
      SOURCES/ghostscript-cve-2018-19134.patch
  7. 322
      SOURCES/ghostscript-cve-2018-19409.patch
  8. 29
      SOURCES/ghostscript-cve-2018-19475.patch
  9. 666
      SOURCES/ghostscript-cve-2018-19476.patch
  10. 32
      SOURCES/ghostscript-cve-2018-19477.patch
  11. 43
      SOURCES/ghostscript-cve-2019-10216.patch
  12. 56
      SOURCES/ghostscript-cve-2019-14811-14812-14813.patch
  13. 258
      SOURCES/ghostscript-cve-2019-14817.patch
  14. 40
      SOURCES/ghostscript-cve-2019-14869.patch
  15. 615
      SOURCES/ghostscript-cve-2019-3835.patch
  16. 56
      SOURCES/ghostscript-cve-2019-3838.patch
  17. 866
      SOURCES/ghostscript-cve-2019-3839.patch
  18. 39
      SOURCES/ghostscript-cve-2019-6116-downstream.patch
  19. 1178
      SOURCES/ghostscript-cve-2019-6116.patch
  20. 201
      SOURCES/ghostscript-fix-DSC-comment-parsing.patch
  21. 56
      SOURCES/ghostscript-pdf2dsc-regression.patch
  22. 1712
      SPECS/ghostscript.spec

22
SOURCES/ghostscript-9.23-100-run-dvipdf-securely.patch

@ -0,0 +1,22 @@
From 91c9c6d17d445781ee572c281b8b9d75d96f9df8 Mon Sep 17 00:00:00 2001
From: "David Kaspar [Dee'Kej]" <dkaspar@redhat.com>
Date: Fri, 7 Oct 2016 13:57:01 +0200
Subject: [PATCH] Make sure 'dvipdf' is being run securely

---
lib/dvipdf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dvipdf b/lib/dvipdf
index 802aeab..c92dfb0 100755
--- a/lib/dvipdf
+++ b/lib/dvipdf
@@ -43,4 +43,4 @@ fi
# We have to include the options twice because -I only takes effect if it
# appears before other options.
-exec dvips -Ppdf $DVIPSOPTIONS -q -f "$infile" | $GS_EXECUTABLE $OPTIONS -q -P- -dSAFER -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr -sOutputFile="$outfile" $OPTIONS -c .setpdfwrite -
+exec dvips -R -Ppdf $DVIPSOPTIONS -q -f "$infile" | $GS_EXECUTABLE $OPTIONS -q -P- -dSAFER -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr -sOutputFile="$outfile" $OPTIONS -c .setpdfwrite -
--
2.14.3

54
SOURCES/ghostscript-9.25-101-reenable-cups-filters.patch

@ -0,0 +1,54 @@
From 9a6564bc1a2f2eeaf9faffd4d3b0a5a562855123 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 9 Oct 2018 15:42:09 +0200
Subject: [PATCH] Fix to re-enable CUPS filters creation (needed for
ghostscript-cups)

---
Makefile.in | 2 ++
configure.ac | 9 +++++++++
2 files changed, 11 insertions(+)

diff --git a/Makefile.in b/Makefile.in
index d6f114a..bdf0ae7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -351,6 +351,8 @@ CUPSSERVERROOT=@CUPSSERVERROOT@
CUPSDATA=@CUPSDATA@
CUPSPDFTORASTER=@CUPSPDFTORASTER@
+CUPSINSTTARGET=@CUPSINSTALL@
+
SHARE_LCUPS=@SHARELCUPS@
LCUPS_NAME=cups
LCUPSSRCDIR=@CUPS_DIR@
diff --git a/configure.ac b/configure.ac
index 8ecaccc..d063c1f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1400,6 +1400,10 @@ AC_ARG_WITH([local-cups], AC_HELP_STRING([--with-local-cups],
[Force using the GS supplied cups code - only useful for debugging]),
[with_local_cups=yes], [with_local_cups=no])
+AC_ARG_WITH([install-cups], AC_HELP_STRING([--with-install-cups],
+ [Install the cups conversion tools]),
+ [CUPSINSTALL=install-cups], [CUPSINSTALL=])
+
AC_ARG_WITH([cups-serverbin], AC_HELP_STRING([--with-cups-serverbin],
[override the "cups-config --serverbin" path]), CUPS_SERVERBIN="$withval", CUPS_SERVERBIN="")
@@ -3029,6 +3033,11 @@ if test x"$THEMAKEFILE" != x"$MAKEFILE" && test x"$CCAUX" = x"$CC"; then
CONFIG_FILES_LIST="$CONFIG_FILES_LIST"
fi
+if ( test -d cups ); then
+AC_OUTPUT(cups/gstopxl)
+chmod +x cups/gstopxl
+fi
+
if test "x$AFS" = "x1"; then
AC_MSG_WARN([Using "native" font scaler which is now deprecated (rather than freetype),])
AC_MSG_WARN([Support for this will be removed in a future release])
--
2.14.4

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

@ -0,0 +1,842 @@
From b0222e5e39712999f22084996a6b85a120b9389e Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 20 Sep 2018 16:35:28 +0100
Subject: [PATCH 1/6] Bug 699795: add operand checking to
.setnativefontmapbuilt

.setnativefontmapbuilt .forceputs a value into systemdict - it is intended
to be a boolean, but in this case was being called with a compound object
(a dictionary). Such an object, in local VM, being forced into systemdict
would then confuse the garbager, since it could be restored away with the
reference remaining.

This adds operand checking, so .setnativefontmapbuilt will simply ignore
anything other than a boolean value, and also removes the definition of
.setnativefontmapbuilt after use, since it is only used in two, closely
related places.
---
Resource/Init/gs_fonts.ps | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 38f0f6c..45b6613 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -372,9 +372,13 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
% of strings: what the system thinks is the ps name,
% and the access path.
/.setnativefontmapbuilt { % set whether we've been run
- systemdict exch /.nativefontmapbuilt exch .forceput
+ dup type /booleantype eq {
+ systemdict exch /.nativefontmapbuilt exch .forceput
+ }
+ {pop}
+ ifelse
} .bind executeonly def
-systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
+systemdict /NONATIVEFONTMAP known //.setnativefontmapbuilt exec
/.buildnativefontmap { % - .buildnativefontmap <bool>
systemdict /.nativefontmapbuilt .knownget not
{ //false} if
@@ -415,9 +419,10 @@ systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
} forall
} if
% record that we've been run
- //true .setnativefontmapbuilt
+ //true //.setnativefontmapbuilt exec
} ifelse
} bind def
+currentdict /.setnativefontmapbuilt .forceundef
% Create the dictionary that registers the .buildfont procedure
% (called by definefont) for each FontType.
--
2.17.2


From a54c9e61e7d02bbc620bcba9b1c208462a876afb 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/6] 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'.
---
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.17.2


From 1778db6bc10a8d60dfe986b22d2300326733ddd6 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 4 Oct 2018 10:42:13 +0100
Subject: [PATCH 3/6] Bug 699832: add control over hiding error handlers.

With a previous commit changing error handling in SAFER so the handler gets
passed a name object (rather than executable object), it is less critical to
hide the error handlers.

This introduces a -dSAFERERRORS option to force only use of the default error
handlers.

It also adds a .setsafererrors Postscript call, meaning a caller, without
-dSAFERERRORS, can create their own default error handlers (in errordict, as
normal), and then call .setsafererrors meaning their own handlers are always
called.

With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is
removed.
---
Resource/Init/gs_init.ps | 42 ++++++++++++++++++++++++----------
psi/interp.c | 49 ++++++++++++++++++++++++----------------
2 files changed, 59 insertions(+), 32 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index b94f873..a627eec 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if
currentdict /PARANOIDSAFER known or % PARANOIDSAFER is equivalent
}
ifelse def
+
+/SAFERERRORS
+currentdict /NOSAFERERRORS known
+{
+ //false
+}
+{
+ currentdict /SAFERERRORS known
+} ifelse def
+
currentdict /SHORTERRORS known /SHORTERRORS exch def
currentdict /TTYPAUSE known /TTYPAUSE exch def
currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def
@@ -1137,12 +1147,23 @@ errordict begin
} bind def
end % errordict
-% Put all the default handlers in gserrordict
-gserrordict
-errordict {2 index 3 1 roll put} forall
-noaccess pop
-% remove the non-standard errors from errordict
+gserrordict /unknownerror errordict /unknownerror get put
errordict /unknownerror .undef
+
+/.SAFERERRORLIST ErrorNames def
+/.setsafererrors
+{
+% Put all the requested handlers in gserrordict
+ gserrordict
+ //.SAFERERRORLIST
+ {dup errordict exch get 2 index 3 1 roll put} forall
+ noaccess pop
+ systemdict /.setsafeerrors .forceundef
+ systemdict /.SAFERERRORLIST .forceundef
+} bind executeonly odef
+
+SAFERERRORS {.setsafererrors} if
+
% Define a stable private copy of handleerror that we will always use under
% JOBSERVER mode.
/.GShandleerror errordict /handleerror get def
@@ -1774,18 +1795,15 @@ currentdict /.runlibfile .undef
% Bind all the operators defined as procedures.
/.bindoperators % binds operators in currentdict
- { % Temporarily disable the typecheck error.
- errordict /typecheck 2 copy get
- errordict /typecheck { pop } put % pop the command
+ {
currentdict
{ dup type /operatortype eq
- { % This might be a real operator, so bind might cause a typecheck,
- % but we've made the error a no-op temporarily.
- .bind
+ {
+ % This might be a real operator, so bind might cause a typecheck
+ {.bind} .internalstopped pop
}
if pop pop
} forall
- put
} def
DELAYBIND not { .bindoperators } if
diff --git a/psi/interp.c b/psi/interp.c
index 1dec9b6..d60c733 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -661,27 +661,18 @@ again:
if (gs_errorname(i_ctx_p, code, &error_name) < 0)
return code; /* out-of-range error code! */
- /* If LockFilePermissions is true, we only refer to gserrordict, which
- * is not accessible to Postcript jobs
+ /* We refer to gserrordict first, which is not accessible to Postcript jobs
+ * If we're running with SAFERERRORS all the handlers are copied to gserrordict
+ * so we'll always find the default one. If not SAFERERRORS, only gs specific
+ * errors are in gserrordict.
*/
- if (i_ctx_p->LockFilePermissions) {
- if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
- dict_find(perrordict, &error_name, &epref) <= 0))
- )
- return code; /* error name not in errordict??? */
- }
- else {
- /*
- * For greater Adobe compatibility, only the standard PostScript errors
- * are defined in errordict; the rest are in gserrordict.
- */
- if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
- (dict_find(perrordict, &error_name, &epref) <= 0 &&
- (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
- dict_find(perrordict, &error_name, &epref) <= 0))
- )
- return code; /* error name not in errordict??? */
- }
+ if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
+ (dict_find(perrordict, &error_name, &epref) <= 0 &&
+ (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
+ dict_find(perrordict, &error_name, &epref) <= 0))
+ )
+ return code; /* error name not in errordict??? */
+
doref = *epref;
epref = &doref;
/* Push the error object on the operand stack if appropriate. */
@@ -694,6 +685,24 @@ again:
}
*osp = *perror_object;
errorexec_find(i_ctx_p, osp);
+ /* If using SAFER, hand a name object to the error handler, rather than the executable
+ * object/operator itself.
+ */
+ if (i_ctx_p->LockFilePermissions) {
+ code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
+ if (code < 0) {
+ const char *unknownstr = "--unknown--";
+ rlen = strlen(unknownstr);
+ memcpy(buf, unknownstr, rlen);
+ }
+ else {
+ buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
+ rlen += 4;
+ }
+ code = name_ref(imemory, buf, rlen, osp, 1);
+ if (code < 0)
+ make_null(osp);
+ }
}
goto again;
}
--
2.17.2


From a6807394bd94b708be24758287b606154daaaed9 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Tue, 2 Oct 2018 16:02:58 +0100
Subject: [PATCH 4/6] For hidden operators, pass a name object to error
handler.

In normal operation, Postscript error handlers are passed the object which
triggered the error: this is invariably an operator object.

The issue arises when an error is triggered by an operator which is for internal
use only, and that operator is then passed to the error handler, meaning it
becomes visible to the error handler code.

By converting to a name object, the error message is still valid, but we no
longer expose internal use only operators.

The change in gs_dps1.ps is related to the above: previously an error in
scheck would throw an error against .gcheck, but as .gcheck is now a hidden
operator, it resulted in a name object being passed to the error handler. As
scheck is a 'real' operator, it's better to use the real operator, rather than
the name of an internal, hidden one.
---
Resource/Init/gs_dps1.ps | 2 +-
psi/interp.c | 33 ++++++++++++++++++++++++---------
2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps
index 1182f53..ec5db61 100644
--- a/Resource/Init/gs_dps1.ps
+++ b/Resource/Init/gs_dps1.ps
@@ -21,7 +21,7 @@ level2dict begin
% ------ Virtual memory ------ %
/currentshared /.currentglobal load def
-/scheck /.gcheck load def
+/scheck {.gcheck} bind odef
%****** FOLLOWING IS WRONG ******
/shareddict currentdict /globaldict .knownget not { 20 dict } if def
diff --git a/psi/interp.c b/psi/interp.c
index d60c733..6dc0dda 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -677,6 +677,8 @@ again:
epref = &doref;
/* Push the error object on the operand stack if appropriate. */
if (!GS_ERROR_IS_INTERRUPT(code)) {
+ byte buf[260], *bufptr;
+ uint rlen;
/* Replace the error object if within an oparray or .errorexec. */
osp++;
if (osp >= ostop) {
@@ -685,23 +687,36 @@ again:
}
*osp = *perror_object;
errorexec_find(i_ctx_p, osp);
- /* If using SAFER, hand a name object to the error handler, rather than the executable
- * object/operator itself.
- */
- if (i_ctx_p->LockFilePermissions) {
+
+ if (!r_has_type(osp, t_string) && !r_has_type(osp, t_name)) {
code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
if (code < 0) {
const char *unknownstr = "--unknown--";
rlen = strlen(unknownstr);
memcpy(buf, unknownstr, rlen);
+ bufptr = buf;
}
else {
- buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
- rlen += 4;
+ ref *tobj;
+ bufptr[rlen] = '\0';
+ /* Only pass a name object if the operator doesn't exist in systemdict
+ * i.e. it's an internal operator we have hidden
+ */
+ code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
+ if (code < 0) {
+ buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
+ rlen += 4;
+ bufptr = buf;
+ }
+ else {
+ bufptr = NULL;
+ }
+ }
+ if (bufptr) {
+ code = name_ref(imemory, buf, rlen, osp, 1);
+ if (code < 0)
+ make_null(osp);
}
- code = name_ref(imemory, buf, rlen, osp, 1);
- if (code < 0)
- make_null(osp);
}
}
goto again;
--
2.17.2


From a5a9bf8c6a63aa4ac6874234fe8cd63e72077291 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 10 Oct 2018 23:25:51 +0100
Subject: [PATCH 5/6] Bug 699938: .loadfontloop must be an operator

In the fix for Bug 699816, I omitted to make .loadfontloop into an operator, to
better hide .forceundef and .putgstringcopy.
---
Resource/Init/gs_fonts.ps | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 89c3ab7..72feff2 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -1148,7 +1148,7 @@ $error /SubstituteFont { } put
} loop % end of loop
- } bind executeonly def % must be bound and hidden for .putgstringcopy
+ } bind executeonly odef % must be bound and hidden for .putgstringcopy
currentdict /.putgstringcopy .undef
--
2.17.2


From 2756f0efae1d3966989b15a6526c5d80848b5015 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 28 Nov 2018 17:12:08 +0000
Subject: [PATCH 6/6] Bug 700290: Fix problems with DELAYBIND and font
substitution

Judicious use of immediate evaluation for .setnativefontmapbuilt and
.putgstringcopy to avoid problems with DELAYBIND
---
Resource/Init/gs_fonts.ps | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 72feff2..7a57366 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -419,7 +419,7 @@ systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
} forall
} if
% record that we've been run
- //true .setnativefontmapbuilt
+ //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
+ { 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
+ dup 4 -1 roll /PathLoad exch //.putgstringcopy
% Stack: origfontname fontdirectory filefontname fontdict
3 -1 roll pop
% Stack: origfontname filefontname fontdict
@@ -1149,8 +1149,7 @@ $error /SubstituteFont { } put
} loop % end of loop
} bind executeonly odef % must be bound and hidden for .putgstringcopy
-
-currentdict /.putgstringcopy .undef
+currentdict /.putgstringcopy .forceundef
% Define a procedure to load all known fonts.
% This isn't likely to be very useful.
--
2.17.2

289
SOURCES/ghostscript-cve-2018-18073.patch

@ -0,0 +1,289 @@
From c76bf1cb7cc419534006631ea139ae20801fd824 Mon Sep 17 00:00:00 2001
From: Nancy Durgin <nancy.durgin@artifex.com>
Date: Tue, 18 Sep 2018 11:54:58 -0700
Subject: [PATCH 1/3] Undefine some additional internal operators.

.type, .writecvs, .setSMask, .currentSMask

These don't seem to be referenced anywhere outside of the initialization code,
which binds their usages. Passes cluster if they are removed.
---
Resource/Init/gs_init.ps | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 55d6923..4aff036 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2212,6 +2212,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 /.currentoutputdevice
+ /.type /.writecvs /.setSMask /.currentSMask
% 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
@@ -2230,7 +2231,7 @@ SAFER { .setsafeglobal } if
% test files/utilities, or engineers expressed a desire to keep them visible.
%
%/currentdevice /.sort /.buildfont0 /.buildfont1 /.buildfont2 /.buildfont3 /.buildfont4 /.buildfont9 /.buildfont10 /.buildfont11
- %/.buildfotn32 /.buildfont42 /.type9mapcid /.type11mapcid /.swapcolors
+ %/.buildfont32 /.buildfont42 /.type9mapcid /.type11mapcid /.swapcolors
%/currentdevice /.quit /.setuseciecolor /.needinput /.setoverprintmode /.special_op /.dicttomark /.knownget
%/.FAPIavailable /.FAPIpassfont /.FAPIrebuildfont /.FAPIBuildGlyph /.FAPIBuildChar /.FAPIBuildGlyph9
%/.tempfile /.numicc_components /.set_outputintent /.max /.min /.vmreclaim /.getpath /.setglobal
--
2.17.2


From f8ccc7dfb990336b1ca55f65f2e1a8ecdcb76adf Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Tue, 25 Sep 2018 15:38:14 +0100
Subject: [PATCH 2/3] Bug 699793: Hide the .needinput operator

This removes the .needinput operator from systemdict, ensuring it can only
be used in the initialization code, and not called erroneously from random
Postscript.
---
Resource/Init/gs_init.ps | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 4aff036..6a5c1df 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -831,12 +831,26 @@ userdict /.currentresourcefile //null put
/.runstring {
0 0 .systemvmstring .systemvmSFD cvx { .runexec } execute0
} bind def
+
% Define the procedure that the C code uses to set up for executing
% a string that may be received in pieces.
+%
+% Immediate evaluation doesn't work on operators (like .needinput)
+% so calling .runstringbegin will throw an undefined error if we
+% undefined .needinput so it cannot be accessed outside the init
+% code. But, we can store the operator in an array, use immediate
+% evaluation on the array to get the operator, then undefined the
+% array (and because they are both of the same name, the operator
+% get undefined too).
+% This prevents random Postscript from erroneously calling .needinput
+% and forcing the interpreter into an invalid state.
+/.needinput
+1 .systemvmarray dup 0 /.needinput load put
+def
/.runstringbegin {
- 1 .systemvmarray dup 0 /.needinput load put cvx % { .needinput } in systemvm
+ 1 .systemvmarray dup 0 //.needinput 0 get put cvx % { .needinput } in systemvm
0 0 .systemvmstring .systemvmSFD cvx .runexec
-} bind def
+} bind executeonly def
% Define a special version of runlibfile that aborts on errors.
/runlibfile0
@@ -2212,7 +2226,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 /.currentoutputdevice
- /.type /.writecvs /.setSMask /.currentSMask
+ /.type /.writecvs /.setSMask /.currentSMask /.needinput
% 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.17.2


From 34cc326eb2c5695833361887fe0b32e8d987741c Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 10 Oct 2018 15:38:10 +0100
Subject: [PATCH 3/3] Bug 699927: don't include operator arrays in execstack
output

When we transfer the contents of the execution stack into the array, take the
extra step of replacing any operator arrays on the stack with the operator
that reference them.

This prevents the contents of Postscript defined, internal only operators (those
created with .makeoperator) being exposed via execstack (and thus, via error
handling).

This necessitates a change in the resource remapping 'resource', which contains
a procedure which relies on the contents of the operators arrays being present.
As we already had internal-only variants of countexecstack and execstack
(.countexecstack and .execstack) - using those, and leaving thier operation
including the operator arrays means the procedure continues to work correctly.

Both .countexecstack and .execstack are undefined after initialization.

Also, when we store the execstack (or part thereof) for an execstackoverflow
error, make the same oparray/operator substitution as above for execstack.
---
Resource/Init/gs_init.ps | 4 ++--
Resource/Init/gs_resmp.ps | 2 +-
psi/int.mak | 2 +-
psi/interp.c | 14 +++++++++++---
psi/interp.h | 2 ++
psi/zcontrol.c | 13 ++++++++++---
6 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 6a5c1df..5bec480 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2187,7 +2187,7 @@ SAFER { .setsafeglobal } if
%% but can be easily restored (just delete the name from the list in the array). In future
%% we may remove the operator and the code implementation entirely.
[
- /.bitadd /.charboxpath /.cond /.countexecstack /.execstack /.runandhide /.popdevicefilter
+ /.bitadd /.charboxpath /.cond /.runandhide /.popdevicefilter
/.execfile /.filenamesplit /.file_name_parent
/.setdefaultmatrix /.isprocfilter /.unread /.psstringencode
/.buildsampledfunction /.isencapfunction /.currentaccuratecurves /.currentcurvejoin /.currentdashadapt /.currentdotlength
@@ -2226,7 +2226,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 /.currentoutputdevice
- /.type /.writecvs /.setSMask /.currentSMask /.needinput
+ /.type /.writecvs /.setSMask /.currentSMask /.needinput /.countexecstack /.execstack
% 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_resmp.ps b/Resource/Init/gs_resmp.ps
index 7cacaf8..9bb4263 100644
--- a/Resource/Init/gs_resmp.ps
+++ b/Resource/Init/gs_resmp.ps
@@ -183,7 +183,7 @@ setpacking
% We don't check them.
currentglobal //false setglobal % <object> bGlobal
- countexecstack array execstack % <object> bGlobal [execstack]
+ //false .countexecstack array //false .execstack % <object> bGlobal [execstack]
dup //null exch % <object> bGlobal [execstack] null [execstack]
length 3 sub -1 0 { % <object> bGlobal [execstack] null i
2 index exch get % <object> bGlobal [execstack] null proc
diff --git a/psi/int.mak b/psi/int.mak
index 5d9b3d5..6ab5bf0 100644
--- a/psi/int.mak
+++ b/psi/int.mak
@@ -323,7 +323,7 @@ $(PSOBJ)zarray.$(OBJ) : $(PSSRC)zarray.c $(OP) $(memory__h)\
$(PSOBJ)zcontrol.$(OBJ) : $(PSSRC)zcontrol.c $(OP) $(string__h)\
$(estack_h) $(files_h) $(ipacked_h) $(iutil_h) $(store_h) $(stream_h)\
- $(INT_MAK) $(MAKEDIRS)
+ $(interp_h) $(INT_MAK) $(MAKEDIRS)
$(PSCC) $(PSO_)zcontrol.$(OBJ) $(C_) $(PSSRC)zcontrol.c
$(PSOBJ)zdict.$(OBJ) : $(PSSRC)zdict.c $(OP)\
diff --git a/psi/interp.c b/psi/interp.c
index 3dd5f7a..1dec9b6 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -142,7 +142,6 @@ static int oparray_pop(i_ctx_t *);
static int oparray_cleanup(i_ctx_t *);
static int zerrorexec(i_ctx_t *);
static int zfinderrorobject(i_ctx_t *);
-static int errorexec_find(i_ctx_t *, ref *);
static int errorexec_pop(i_ctx_t *);
static int errorexec_cleanup(i_ctx_t *);
static int zsetstackprotect(i_ctx_t *);
@@ -737,7 +736,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;
+ int code, i;
if (size > 65535)
size = 65535;
@@ -746,6 +745,15 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
if (code >= 0)
code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory,
"copy_stack");
+ /* If we are copying the exec stack, try to replace any oparrays with
+ * with the operator than references them
+ */
+ if (pstack == &e_stack) {
+ for (i = 0; i < size; i++) {
+ if (errorexec_find(i_ctx_p, &arr->value.refs[i]) < 0)
+ make_null(&arr->value.refs[i]);
+ }
+ }
ialloc_set_space(idmemory, save_space);
return code;
}
@@ -1910,7 +1918,7 @@ zfinderrorobject(i_ctx_t *i_ctx_p)
* .errorexec with errobj != null, store it in *perror_object and return 1,
* otherwise return 0;
*/
-static int
+int
errorexec_find(i_ctx_t *i_ctx_p, ref *perror_object)
{
long i;
diff --git a/psi/interp.h b/psi/interp.h
index e9275b9..4f551d1 100644
--- a/psi/interp.h
+++ b/psi/interp.h
@@ -91,5 +91,7 @@ void gs_interp_reset(i_ctx_t *i_ctx_p);
/* Define the top-level interface to the interpreter. */
int gs_interpret(i_ctx_t **pi_ctx_p, ref * pref, int user_errors,
int *pexit_code, ref * perror_object);
+int
+errorexec_find(i_ctx_t *i_ctx_p, ref *perror_object);
#endif /* interp_INCLUDED */
diff --git a/psi/zcontrol.c b/psi/zcontrol.c
index 36da22c..0362cf4 100644
--- a/psi/zcontrol.c
+++ b/psi/zcontrol.c
@@ -24,6 +24,7 @@
#include "ipacked.h"
#include "iutil.h"
#include "store.h"
+#include "interp.h"
/* Forward references */
static int check_for_exec(const_os_ptr);
@@ -787,7 +788,7 @@ zexecstack2(i_ctx_t *i_ctx_p)
/* Continuation operator to do the actual transfer. */
/* r_size(op1) was set just above. */
static int
-do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1)
+do_execstack(i_ctx_t *i_ctx_p, bool include_marks, bool include_oparrays, os_ptr op1)
{
os_ptr op = osp;
ref *arefs = op1->value.refs;
@@ -829,6 +830,12 @@ do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1)
strlen(tname), (const byte *)tname);
break;
}
+ case t_array:
+ case t_shortarray:
+ case t_mixedarray:
+ if (!include_oparrays && errorexec_find(i_ctx_p, rq) < 0)
+ make_null(rq);
+ break;
default:
;
}
@@ -841,14 +848,14 @@ execstack_continue(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- return do_execstack(i_ctx_p, false, op);
+ return do_execstack(i_ctx_p, false, false, op);
}
static int
execstack2_continue(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- return do_execstack(i_ctx_p, op->value.boolval, op - 1);
+ return do_execstack(i_ctx_p, op->value.boolval, true, op - 1);
}
/* - .needinput - */
--
2.17.2

240
SOURCES/ghostscript-cve-2018-18284.patch

@ -0,0 +1,240 @@
From 8d19fdf63f91f50466b08f23e2d93d37a4c5ea0b Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Mon, 15 Oct 2018 11:28:28 +0100
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.
---
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 7a57366..052a191 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 2114a2a..0b900e6 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2244,7 +2244,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 /.currentoutputdevice
- /.type /.writecvs /.setSMask /.currentSMask /.needinput /.countexecstack /.execstack
+ /.type /.writecvs /.setSMask /.currentSMask /.needinput /.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 fab8b84..71eb622 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.
@@ -1012,7 +1016,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.17.2

153
SOURCES/ghostscript-cve-2018-19134.patch

@ -0,0 +1,153 @@
From 693baf02152119af6e6afd30bb8ec76d14f84bbf Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Thu, 8 Nov 2018 14:43:32 +0000
Subject: [PATCH] PS interpreter - check the Implementation of a Pattern before
use

Bug #700141 "Type confusion in setpattern"

As the bug thread says, we were not checking that the Implementation
of a pattern dictionary was a structure type, leading to a crash when
we tried to treat it as one.

Here we make the st_pattern1_instance and st_pattern2_instance
structures public definitions and in zsetcolor we check the object
stored under the Implementation key in the supplied dictionary to see if
its a t_struct or t_astruct type, and if it is that its a
st_pattern1_instance or st_pattern2_instance structure.

If either check fails we throw a typecheck error.

We need to make the st_pattern1_instance and st_pattern2_instance
definitions public as they are defined in the graphics library and we
need to check in the interpreter.
---
base/gsptype1.c | 2 +-
base/gsptype2.c | 6 +++---
base/gsptype2.h | 4 ++--
base/gxcolor2.h | 4 ++--
psi/zcolor.c | 11 ++++++++---
5 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/base/gsptype1.c b/base/gsptype1.c
index 27fdd5a..e98dde1 100644
--- a/base/gsptype1.c
+++ b/base/gsptype1.c
@@ -50,7 +50,7 @@
/* GC descriptors */
private_st_pattern1_template();
-private_st_pattern1_instance();
+public_st_pattern1_instance();
/* GC procedures */
static ENUM_PTRS_BEGIN(pattern1_instance_enum_ptrs) {
diff --git a/base/gsptype2.c b/base/gsptype2.c
index 791e538..c53eb2e 100644
--- a/base/gsptype2.c
+++ b/base/gsptype2.c
@@ -33,7 +33,7 @@
/* GC descriptors */
private_st_pattern2_template();
-private_st_pattern2_instance();
+public_st_pattern2_instance();
/* GC procedures */
static ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs) {
@@ -206,10 +206,10 @@ gs_pattern2_set_color(const gs_client_color * pcc, gs_gstate * pgs)
pinst->saved->overprint_mode = pgs->overprint_mode;
pinst->saved->overprint = pgs->overprint;
-
+
num_comps = pgs->device->color_info.num_components;
for (k = 0; k < num_comps; k++) {
- pgs->color_component_map.color_map[k] =
+ pgs->color_component_map.color_map[k] =
pinst->saved->color_component_map.color_map[k];
}
code = pcs->type->set_overprint(pcs, pgs);
diff --git a/base/gsptype2.h b/base/gsptype2.h
index f0f26d1..4186201 100644
--- a/base/gsptype2.h
+++ b/base/gsptype2.h
@@ -57,8 +57,8 @@ typedef struct gs_pattern2_instance_s {
bool shfill;
} gs_pattern2_instance_t;
-#define private_st_pattern2_instance() /* in gsptype2.c */\
- gs_private_st_composite(st_pattern2_instance, gs_pattern2_instance_t,\
+#define public_st_pattern2_instance() /* in gsptype2.c */\
+ gs_public_st_composite(st_pattern2_instance, gs_pattern2_instance_t,\
"gs_pattern2_instance_t", pattern2_instance_enum_ptrs,\
pattern2_instance_reloc_ptrs)
diff --git a/base/gxcolor2.h b/base/gxcolor2.h
index 62ec05e..d5b1095 100644
--- a/base/gxcolor2.h
+++ b/base/gxcolor2.h
@@ -92,8 +92,8 @@ struct gs_pattern1_instance_s {
gx_bitmap_id id; /* key for cached bitmap (= id of mask) */
};
-#define private_st_pattern1_instance() /* in gsptype1.c */\
- gs_private_st_composite(st_pattern1_instance, gs_pattern1_instance_t,\
+#define public_st_pattern1_instance() /* in gsptype1.c */\
+ gs_public_st_composite(st_pattern1_instance, gs_pattern1_instance_t,\
"gs_pattern1_instance_t", pattern1_instance_enum_ptrs,\
pattern1_instance_reloc_ptrs)
diff --git a/psi/zcolor.c b/psi/zcolor.c
index 7a00d4e..fe81e79 100644
--- a/psi/zcolor.c
+++ b/psi/zcolor.c
@@ -65,6 +65,8 @@ static const float default_0_1[] = {0, 1, 0, 1, 0, 1, 0, 1};
/* imported from gsht.c */
extern void gx_set_effective_transfer(gs_gstate *);
+extern_st(st_pattern1_instance);
+extern_st(st_pattern2_instance);
/* Essential forward declarations */
static int validate_spaces(i_ctx_t *i_ctx_p, ref *arr, int *depth);
@@ -289,6 +291,9 @@ zsetcolor(i_ctx_t * i_ctx_p)
code = array_get(imemory, pImpl, 0, &pPatInst);
if (code < 0)
return code;
+ if (!r_is_struct(&pPatInst) || (!r_has_stype(&pPatInst, imemory, st_pattern1_instance) && !r_has_stype(&pPatInst, imemory, st_pattern2_instance)))
+ return_error(gs_error_typecheck);
+
cc.pattern = r_ptr(&pPatInst, gs_pattern_instance_t);
n_numeric_comps = ( pattern_instance_uses_base_space(cc.pattern)
? n_comps - 1
@@ -4421,7 +4426,7 @@ static int setindexedspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int
/* If we have a named color profile and the base space is DeviceN or
Separation use a different set of procedures to ensure the named
color remapping code is used */
- if (igs->icc_manager->device_named != NULL &&
+ if (igs->icc_manager->device_named != NULL &&
(base_type == gs_color_space_index_Separation ||
base_type == gs_color_space_index_DeviceN))
pcs = gs_cspace_alloc(imemory, &gs_color_space_type_Indexed_Named);
@@ -5573,7 +5578,7 @@ static int iccompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
return 0;
/* As a quick check see if current is same as new */
- if (ICCdict1.value.bytes == ICCdict2.value.bytes)
+ if (ICCdict1.value.bytes == ICCdict2.value.bytes)
return 1;
/* Need to check all the various parts */
@@ -5593,7 +5598,7 @@ static int iccompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
code2 = dict_find_string(&ICCdict2, "DataSource", &tempref2);
if (code2 <= 0)
return 0;
- if (r_size(tempref1) != r_size(tempref2))
+ if (r_size(tempref1) != r_size(tempref2))
return 0;
buff_size = r_size(tempref1);
--
2.17.2

322
SOURCES/ghostscript-cve-2018-19409.patch

@ -0,0 +1,322 @@
From 661e8d8fb8248c38d67958beda32f3a5876d0c3f Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 14 Nov 2018 09:50:08 +0000
Subject: [PATCH 1/4] Bug 700176: check the *output* device for
LockSafetyParams

When calling .setdevice we were checking if LockSafetyParams was set, and if so
throwing an invalidaccess error.

The problem is, if another device, for example the pdf14 compositor is the 'top'
device, that does not (and cannot) honour LockSafetyParams.

To solve this, we'll now use the (relatively new) gxdso_current_output_device
spec_op to retrieve the *actual* output device, and check the LockSafetyParams
flag in that.
---
psi/zdevice.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/psi/zdevice.c b/psi/zdevice.c
index 8d48b74..c276746 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -461,13 +461,17 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
int
zsetdevice(i_ctx_t *i_ctx_p)
{
- gx_device *dev = gs_currentdevice(igs);
+ gx_device *odev = NULL, *dev = gs_currentdevice(igs);
os_ptr op = osp;
- int code = 0;
+ int code = dev_proc(dev, dev_spec_op)(dev,
+ gxdso_current_output_device, (void *)&odev, 0);
+
+ if (code < 0)
+ return code;
check_write_type(*op, t_device);
- if (dev->LockSafetyParams) { /* do additional checking if locked */
- if(op->value.pdevice != dev) /* don't allow a different device */
+ if (odev->LockSafetyParams) { /* do additional checking if locked */
+ if(op->value.pdevice != odev) /* don't allow a different device */
return_error(gs_error_invalidaccess);
}
dev->ShowpageCount = 0;
--
2.17.2


From ea1b3ef437f39e45874f821c06bd953196625ac5 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 14 Nov 2018 21:04:46 +0000
Subject: [PATCH 2/4] Bug 700176: Use the actual output device for both devices
in setdevice

Also fixes bug 700189.

The pdf14 compositor device, despite being a forwarding device, does not forward
all spec_ops to it's target, only a select few are special cased for that.
gxdso_current_output_device needs to be included in those special cases.

The original commit (661e8d8fb8248) changed the code to use the spec_op to
retrieve the output device, checking that for LockSafetyParams. If
LockSafetyParams is set, it returns an invalidaccess error if the new device
differs from the current device.

When we do the comparison between the two devices, we need to check the
output device in both cases.

This is complicated by the fact that the new device may not have ever been set
(and thus fully initialised), and may not have a spec_op method available at
that point.
---
base/gdevp14.c | 3 ++-
psi/zdevice.c | 18 ++++++++++++++++--
2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/base/gdevp14.c b/base/gdevp14.c
index f89bc04..f47ed30 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -5618,7 +5618,8 @@ pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op,
return 0;
}
}
- if (dev_spec_op == gxdso_get_dev_param || dev_spec_op == gxdso_restrict_bbox) {
+ if (dev_spec_op == gxdso_get_dev_param || dev_spec_op == gxdso_restrict_bbox
+ || dev_spec_op == gxdso_current_output_device) {
return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size);
}
diff --git a/psi/zdevice.c b/psi/zdevice.c
index c276746..4beda04 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -462,16 +462,30 @@ int
zsetdevice(i_ctx_t *i_ctx_p)
{
gx_device *odev = NULL, *dev = gs_currentdevice(igs);
+ gx_device *ndev = NULL;
os_ptr op = osp;
int code = dev_proc(dev, dev_spec_op)(dev,
gxdso_current_output_device, (void *)&odev, 0);
if (code < 0)
return code;
-
check_write_type(*op, t_device);
+
+ /* slightly icky special case: the new device may not have had
+ * it's procs initialised, at this point - but we need to check
+ * whether we're being asked to change the device here
+ */
+ if (dev_proc((op->value.pdevice), dev_spec_op) == NULL)
+ ndev = op->value.pdevice;
+ else
+ code = dev_proc((op->value.pdevice), dev_spec_op)(op->value.pdevice,
+ gxdso_current_output_device, (void *)&ndev, 0);
+
+ if (code < 0)
+ return code;
+
if (odev->LockSafetyParams) { /* do additional checking if locked */
- if(op->value.pdevice != odev) /* don't allow a different device */
+ if(ndev != odev) /* don't allow a different device */
return_error(gs_error_invalidaccess);
}
dev->ShowpageCount = 0;
--
2.17.2


From 7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Mon, 17 Sep 2018 14:06:12 +0100
Subject: [PATCH 3/4] Implement .currentoutputdevice operator

The currentdevice operator returns the device currently installed in the
graphics state. This can be the output/page device, but also could be a
forwarding device (bbox device), compositor (pdf14) or subclass device
(erasepage optimisation, First/Last page etc).

In certain circumstances (for example during a setpagedevice) we want to be
sure we're retrieving the *actual* output/page device.

The new .currentoutputdevice operator uses the spec_op device method to traverse
any chain of devices and retrieve the final device in the chain, which
should always be the output/page device.
---
Resource/Init/gs_init.ps | 2 +-
Resource/Init/gs_setpd.ps | 8 +++++++-
base/gdevdflt.c | 5 +++++
base/gxdevsop.h | 4 ++++
psi/zdevice.c | 30 ++++++++++++++++++++++++++++++
5 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index bec307d..55d6923 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2211,7 +2211,7 @@ SAFER { .setsafeglobal } if
/.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
/.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
+ /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath /.currentoutputdevice
% 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 8fa7c51..aa79b3f 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -877,7 +877,13 @@ SETPDDEBUG { (Selecting.) = pstack flush } if
% Stack: mark <orig> <request> <merged> <failed>
SETPDDEBUG { (Constructing.) = pstack flush } if
- currentdevice .devicename 2 index /OutputDevice get eq
+ % Non-obvious: we need to check the name of the output device, to tell
+ % whether we're going to have to replace the entire device chain (which
+ % may be only one device, or may be multiple devices.
+ % If we're not replacing the entire change, we have to use the device in
+ % the graphics state, so the configuration of the entire device chain is
+ % correctly set.
+ .currentoutputdevice .devicename 2 index /OutputDevice get eq
{ currentdevice }
{ 1 index /OutputDevice get finddevice }
ifelse
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index 3cb9fbd..b5bd82b 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -1044,6 +1044,11 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
dev_param_req_t *request = (dev_param_req_t *)data;
return gx_default_get_param(pdev, request->Param, request->list);
}
+ case gxdso_current_output_device:
+ {
+ *(gx_device **)data = pdev;
+ return 0;
+ }
}
return_error(gs_error_undefined);
}
diff --git a/base/gxdevsop.h b/base/gxdevsop.h
index cd3b632..27e3e84 100644
--- a/base/gxdevsop.h
+++ b/base/gxdevsop.h
@@ -327,6 +327,10 @@ enum {
gxdso_JPEG_passthrough_data,
gxdso_JPEG_passthrough_end,
gxdso_supports_iccpostrender,
+ /* Retrieve the last device in a device chain
+ (either forwarding or subclass devices).
+ */
+ gxdso_current_output_device,
/* Add new gxdso_ keys above this. */
gxdso_pattern__LAST
};
diff --git a/psi/zdevice.c b/psi/zdevice.c
index 4beda04..03285dc 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -57,6 +57,7 @@ zcopydevice2(i_ctx_t *i_ctx_p)
}
/* - currentdevice <device> */
+/* Returns the current device in the graphics state */
int
zcurrentdevice(i_ctx_t *i_ctx_p)
{
@@ -71,6 +72,34 @@ zcurrentdevice(i_ctx_t *i_ctx_p)
return 0;
}
+/* - .currentoutputdevice <device> */
+/* Returns the *output* device - which will often
+ be the same as above, but not always: if a compositor
+ or other forwarding device, or subclassing device is
+ in force, that will be referenced by the graphics state
+ rather than the output device.
+ This is equivalent of currentdevice device, but returns
+ the *device* object, rather than the dictionary describing
+ the device and device state.
+ */
+static int
+zcurrentoutputdevice(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ gx_device *odev = NULL, *dev = gs_currentdevice(igs);
+ gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
+ int code = dev_proc(dev, dev_spec_op)(dev,
+ gxdso_current_output_device, (void *)&odev, 0);
+ if (code < 0)
+ return code;
+
+ push(1);
+ make_tav(op, t_device,
+ (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
+ pdevice, odev);
+ return 0;
+}
+
/* <device> .devicename <string> */
static int
zdevicename(i_ctx_t *i_ctx_p)
@@ -632,6 +661,7 @@ const op_def zdevice_op_defs[] =
{
{"1.copydevice2", zcopydevice2},
{"0currentdevice", zcurrentdevice},
+ {"0.currentoutputdevice", zcurrentoutputdevice},
{"1.devicename", zdevicename},
{"0.doneshowpage", zdoneshowpage},
{"0flushpage", zflushpage},
--
2.17.2


From 4d98293c72cc5b5fe456065a3252d39e9ab28e4d Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Mon, 19 Nov 2018 09:00:54 +0000
Subject: [PATCH 4/4] Coverity ID 327264 - move pointer NULL check

Due to recent changes in this code, the pointer was being dereferenced
before we checked it to see if it was NULL. Moe the check so that we
check for NULL before dereferencing.

The 'pvalue' of the operand can be NULL, even if the object is a t_device
type, because invalidate_stack_devices traverses the operand stack
looking for devices, and sets their pvalue member to NULL in order to
invalidate them so that they cannot be used.
---
psi/zdevice.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/psi/zdevice.c b/psi/zdevice.c
index 03285dc..63865f1 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -500,6 +500,9 @@ zsetdevice(i_ctx_t *i_ctx_p)
return code;
check_write_type(*op, t_device);
+ if (op->value.pdevice == 0)
+ return gs_note_error(gs_error_undefined);
+
/* slightly icky special case: the new device may not have had
* it's procs initialised, at this point - but we need to check
* whether we're being asked to change the device here
@@ -519,9 +522,6 @@ zsetdevice(i_ctx_t *i_ctx_p)
}
dev->ShowpageCount = 0;
- if (op->value.pdevice == 0)
- return gs_note_error(gs_error_undefined);
-
code = gs_setdevice_no_erase(igs, op->value.pdevice);
if (code < 0)
return code;
--
2.17.2

29
SOURCES/ghostscript-cve-2018-19475.patch

@ -0,0 +1,29 @@
From aeea342904978c9fe17d85f4906a0f6fcce2d315 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Mon, 12 Nov 2018 17:21:33 +0000
Subject: [PATCH] Bug 700153: restore: always check available stack

Previously, we were checking there was enough stack space available when the
restore operation required a device change, but since we have to use
Postscript to reset the userparams (ick!), we need the stack check even when
not changing the device.
---
psi/zdevice2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/psi/zdevice2.c b/psi/zdevice2.c
index 159a0c0..e11b075 100644
--- a/psi/zdevice2.c
+++ b/psi/zdevice2.c
@@ -277,7 +277,7 @@ restore_page_device(i_ctx_t *i_ctx_p, const gs_gstate * pgs_old, const gs_gstate
samepagedevice = false;
}
- if (LockSafetyParams && !samepagedevice) {
+ if (LockSafetyParams) {
const int required_ops = 512;
const int required_es = 32;
--
2.17.2

666
SOURCES/ghostscript-cve-2018-19476.patch

@ -0,0 +1,666 @@
From fac7eb144135f3ed8fbb0028ab1f33ce4dcc1985 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Fri, 21 Sep 2018 13:02:56 +0100
Subject: [PATCH 1/3] Check all uses of dict_find* to ensure 0 return properly
handled

dict_find and friends have the surprising quirk of returning < 0 for
an error and > 0 for no error. But they can also return 0 which means
'not found' without it being an error.

From bug 699801, if the code assumes the usual case where 0 is a success
then an attempt might be made to use the empty dictionary slot returned
by dict_find*, which can lead to seg faults, and certainly won't have
the expected result.
---
psi/icontext.c | 4 ++--
psi/zcid.c | 6 ++++--
psi/zfapi.c | 33 ++++++++++++++++++---------------
psi/zfcid0.c | 39 +++++++++++++++++++++++++++++----------
psi/zfcid1.c | 14 ++++++++++----
psi/zicc.c | 4 ++++
psi/zpdf_r6.c | 31 +++++++++++++++++++++++--------
psi/ztoken.c | 2 +-
8 files changed, 91 insertions(+), 42 deletions(-)

diff --git a/psi/icontext.c b/psi/icontext.c
index 4db78e0..1fbe486 100644
--- a/psi/icontext.c
+++ b/psi/icontext.c
@@ -162,7 +162,7 @@ context_state_alloc(gs_context_state_t ** ppcst,
uint size;
ref *system_dict = &pcst->dict_stack.system_dict;
- if (dict_find_string(system_dict, "userparams", &puserparams) >= 0)
+ if (dict_find_string(system_dict, "userparams", &puserparams) > 0)
size = dict_length(puserparams);
else
size = 300;
@@ -286,7 +286,7 @@ context_state_store(gs_context_state_t * pcst)
/* We need i_ctx_p for access to the d_stack. */
i_ctx_t *i_ctx_p = pcst;
- if (dict_find_string(systemdict, "userparams", &puserparams) < 0)
+ if (dict_find_string(systemdict, "userparams", &puserparams) <= 0)
return_error(gs_error_Fatal);
pcst->userparams = *puserparams;
}
diff --git a/psi/zcid.c b/psi/zcid.c
index e394877..5c98fc9 100644
--- a/psi/zcid.c
+++ b/psi/zcid.c
@@ -72,11 +72,13 @@ TT_char_code_from_CID_no_subst(const gs_memory_t *mem,
} else
return false; /* Must not happen. */
for (;n--; i++) {
+ int code;
+
if (array_get(mem, DecodingArray, i, &char_code1) < 0 ||
!r_has_type(&char_code1, t_integer))
return false; /* Must not happen. */
- if (dict_find(TT_cmap, &char_code1, &glyph_index) >= 0 &&
- r_has_type(glyph_index, t_integer)) {
+ code = dict_find(TT_cmap, &char_code1, &glyph_index);
+ if (code > 0 && r_has_type(glyph_index, t_integer)) {
*c = glyph_index->value.intval;
found = true;
if (*c != 0)
diff --git a/psi/zfapi.c b/psi/zfapi.c
index 48e1d54..1b687b0 100644
--- a/psi/zfapi.c
+++ b/psi/zfapi.c
@@ -1826,6 +1826,9 @@ FAPI_get_xlatmap(i_ctx_t *i_ctx_p, char **xlatmap)
if ((code = dict_find_string(systemdict, ".xlatmap", &pref)) < 0)
return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+
if (r_type(pref) != t_string)
return_error(gs_error_typecheck);
*xlatmap = (char *)pref->value.bytes;
@@ -1881,11 +1884,11 @@ ps_get_server_param(gs_fapi_server *I, const byte *subtype,
ref *FAPIconfig, *options, *server_options;
i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p;
- if (dict_find_string(systemdict, ".FAPIconfig", &FAPIconfig) >= 0
+ if (dict_find_string(systemdict, ".FAPIconfig", &FAPIconfig) > 0
&& r_has_type(FAPIconfig, t_dictionary)) {
- if (dict_find_string(FAPIconfig, "ServerOptions", &options) >= 0
+ if (dict_find_string(FAPIconfig, "ServerOptions", &options) > 0
&& r_has_type(options, t_dictionary)) {
- if (dict_find_string(options, (char *)subtype, &server_options) >=
+ if (dict_find_string(options, (char *)subtype, &server_options) >
0 && r_has_type(server_options, t_string)) {
*server_param = (byte *) server_options->value.const_bytes;
*server_param_size = r_size(server_options);
@@ -2070,7 +2073,7 @@ zFAPIrebuildfont(i_ctx_t *i_ctx_p)
pdata = (font_data *) pfont->client_data;
I = pbfont->FAPI;
- if (dict_find_string((op - 1), "SubfontId", &v) >= 0
+ if (dict_find_string((op - 1), "SubfontId", &v) > 0
&& r_has_type(v, t_integer))
subfont = v->value.intval;
else
@@ -2277,8 +2280,8 @@ ps_get_glyphname_or_cid(gs_text_enum_t *penum,
if (pbfont->FontType == ft_CID_TrueType && font_file_path) {
ref *pdr2, *fidr, *dummy;
pdr2 = pfont_dict(gs_rootfont(igs));
- if (dict_find_string(pdr2, "FontInfo", &fidr) &&
- dict_find_string(fidr, "GlyphNames2Unicode", &dummy))
+ if (dict_find_string(pdr2, "FontInfo", &fidr) > 0 &&
+ dict_find_string(fidr, "GlyphNames2Unicode", &dummy) > 0)
{
unsigned char uc[4] = {0};
unsigned int cc = 0;
@@ -2417,13 +2420,13 @@ ps_get_glyphname_or_cid(gs_text_enum_t *penum,
fdict = pfont_dict(gs_rootfont(igs));
code = dict_find_string(fdict, "CMap", &CMapDict);
- if (code >= 0 && r_has_type(CMapDict, t_dictionary)) {
+ if (code > 0 && r_has_type(CMapDict, t_dictionary)) {
code = dict_find_string(CMapDict, "WMode", &WMode);
- if (code >= 0 && r_has_type(WMode, t_integer)) {
+ if (code > 0 && r_has_type(WMode, t_integer)) {
wmode = WMode->value.intval;
}
code = dict_find_string(CMapDict, "CMapName", &CMapName);
- if (code >= 0 && r_has_type(CMapName, t_name)) {
+ if (code > 0 && r_has_type(CMapName, t_name)) {
name_string_ref(imemory, CMapName, &CMapNameStr);
cmapnm = (char *)CMapNameStr.value.bytes;
cmapnmlen = r_size(&CMapNameStr);
@@ -2432,10 +2435,10 @@ ps_get_glyphname_or_cid(gs_text_enum_t *penum,
/* We only have to lookup the char code if we're *not* using an identity ordering
with the exception of Identity-UTF16 which is a different beast altogether */
if (unicode_cp || (cmapnmlen > 0 && !strncmp(cmapnm, utfcmap, cmapnmlen > utfcmaplen ? utfcmaplen : cmapnmlen))
- || (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) >= 0
+ || (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) > 0
&& r_has_type(CIDSystemInfo, t_dictionary)
&& dict_find_string(CIDSystemInfo, "Ordering",
- &Ordering) >= 0
+ &Ordering) > 0
&& r_has_type(Ordering, t_string)
&& strncmp((const char *)Ordering->value.bytes,
"Identity", 8) != 0)) {
@@ -2463,7 +2466,7 @@ ps_get_glyphname_or_cid(gs_text_enum_t *penum,
ref cc32;
ref *gid;
make_int(&cc32, 32);
- if (dict_find(TT_cmap, &cc32, &gid) >= 0)
+ if (dict_find(TT_cmap, &cc32, &gid) > 0)
c = gid->value.intval;
}
cr->char_codes[0] = c;
@@ -2536,7 +2539,7 @@ ps_get_glyphname_or_cid(gs_text_enum_t *penum,
if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0
|| !r_has_type(CharStrings, t_dictionary))
return_error(gs_error_invalidfont);
- if ((dict_find(CharStrings, &char_name, &glyph_index) < 0)
+ if ((dict_find(CharStrings, &char_name, &glyph_index) <= 0)
|| r_has_type(glyph_index, t_null)) {
#ifdef DEBUG
ref *pvalue;
@@ -2955,7 +2958,7 @@ zFAPIpassfont(i_ctx_t *i_ctx_p)
if (code < 0)
return code;
- if (dict_find_string(op, "SubfontId", &v) >= 0
+ if (dict_find_string(op, "SubfontId", &v) > 0
&& r_has_type(v, t_integer))
subfont = v->value.intval;
else
@@ -2968,7 +2971,7 @@ zFAPIpassfont(i_ctx_t *i_ctx_p)
/* If the font dictionary contains a FAPIPlugInReq key, the the PS world wants us
* to try to use a specific FAPI plugin, so find it, and try it....
*/
- if (dict_find_string(op, "FAPIPlugInReq", &v) >= 0 && r_type(v) == t_name) {
+ if (dict_find_string(op, "FAPIPlugInReq", &v) > 0 && r_type(v) == t_name) {
name_string_ref(imemory, v, &reqstr);
diff --git a/psi/zfcid0.c b/psi/zfcid0.c
index 2aba09a..ba00b21 100644
--- a/psi/zfcid0.c
+++ b/psi/zfcid0.c
@@ -410,13 +410,25 @@ zbuildfont9(i_ctx_t *i_ctx_p)
* from a file, GlyphData will be an integer, and DataSource will be
* a (reusable) stream.
*/
- if (code < 0 ||
- (code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 ||
- (code = dict_find_string(op, "FDArray", &prfda)) < 0 ||
- (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
- (code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0
- )
+ if (code < 0)
+ return code;
+ code = cid_font_data_param(op, &common, &GlyphDirectory);
+ if (code < 0)
+ return code;
+ code = dict_find_string(op, "FDArray", &prfda);
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ code = dict_find_string(op, "CIDFontName", &pCIDFontName);
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes);
+ if (code < 0)
return code;
+
/*
* Since build_gs_simple_font may resize the dictionary and cause
* pointers to become invalid, save CIDFontName
@@ -426,17 +438,24 @@ zbuildfont9(i_ctx_t *i_ctx_p)
/* Standard CIDFont, require GlyphData and CIDMapOffset. */
ref *pGlyphData;
- if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 ||
- (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1,
- max_uint, &CIDMapOffset)) < 0)
+ code = dict_find_string(op, "GlyphData", &pGlyphData);
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1, max_uint, &CIDMapOffset);
+ if (code < 0)
return code;
GlyphData = *pGlyphData;
if (r_has_type(&GlyphData, t_integer)) {
ref *pds;
stream *ignore_s;
- if ((code = dict_find_string(op, "DataSource", &pds)) < 0)
+ code = dict_find_string(op, "DataSource", &pds);
+ if (code < 0)
return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
check_read_file(i_ctx_p, ignore_s, pds);
DataSource = *pds;
} else {
diff --git a/psi/zfcid1.c b/psi/zfcid1.c
index ef3ece0..e3643a0 100644
--- a/psi/zfcid1.c
+++ b/psi/zfcid1.c
@@ -347,11 +347,17 @@ zbuildfont11(i_ctx_t *i_ctx_p)
ref rcidmap, ignore_gdir, file, *pfile, cfnstr, *pCIDFontName, CIDFontName, *t;
ulong loca_glyph_pos[2][2];
int code = cid_font_data_param(op, &common, &ignore_gdir);
+ if (code < 0)
+ return code;
- if (code < 0 ||
- (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
- (code = dict_int_param(op, "MetricsCount", 0, 4, 0, &MetricsCount)) < 0
- )
+ code = dict_find_string(op, "CIDFontName", &pCIDFontName);
+ if (code <= 0) {
+ if (code == 0)
+ return_error(gs_error_undefined);
+ return code;
+ }
+ code = dict_int_param(op, "MetricsCount", 0, 4, 0, &MetricsCount);
+ if (code < 0)
return code;
/*
* Since build_gs_simple_font may resize the dictionary and cause
diff --git a/psi/zicc.c b/psi/zicc.c
index ebf25fe..53bdf34 100644
--- a/psi/zicc.c
+++ b/psi/zicc.c
@@ -261,6 +261,8 @@ zset_outputintent(i_ctx_t * i_ctx_p)
code = dict_find_string(op, "N", &pnval);
if (code < 0)
return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
ncomps = pnval->value.intval;
/* verify the DataSource entry. Creat profile from stream */
@@ -491,6 +493,8 @@ znumicc_components(i_ctx_t * i_ctx_p)
code = dict_find_string(op, "N", &pnval);
if (code < 0)
return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
ncomps = pnval->value.intval;
/* verify the DataSource entry. Create profile from stream */
if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
diff --git a/psi/zpdf_r6.c b/psi/zpdf_r6.c
index bcd4907..992f316 100644
--- a/psi/zpdf_r6.c
+++ b/psi/zpdf_r6.c
@@ -145,21 +145,36 @@ zcheck_r6_password(i_ctx_t * i_ctx_p)
return_error(gs_error_typecheck);
code = dict_find_string(CryptDict, "O", &Oref);
- if (code < 0 || !r_has_type(Oref, t_string)) {
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ if (!r_has_type(Oref, t_string))
return_error(gs_error_typecheck);
- }
+
code = dict_find_string(CryptDict, "OE", &OEref);
- if (code < 0 || !r_has_type(OEref, t_string)) {
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ if (!r_has_type(OEref, t_string))
return_error(gs_error_typecheck);
- }
+
code = dict_find_string(CryptDict, "U", &Uref);
- if (code < 0 || !r_has_type(Uref, t_string)) {
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ if (!r_has_type(Uref, t_string))
return_error(gs_error_typecheck);
- }
+
code = dict_find_string(CryptDict, "UE", &UEref);
- if (code < 0 || !r_has_type(UEref, t_string)) {
+ if (code < 0)
+ return code;
+ if (code == 0)
+ return_error(gs_error_undefined);
+ if (!r_has_type(UEref, t_string))
return_error(gs_error_typecheck);
- }
pop(2);
op = osp;
diff --git a/psi/ztoken.c b/psi/ztoken.c
index 519cd09..9314d97 100644
--- a/psi/ztoken.c
+++ b/psi/ztoken.c
@@ -356,7 +356,7 @@ ztoken_scanner_options(const ref *upref, int old_options)
int code = dict_find_string(upref, pnso->pname, &ppcproc);
/* Update the options only if the parameter has changed. */
- if (code >= 0) {
+ if (code > 0) {
if (r_has_type(ppcproc, t_null))
options &= ~pnso->option;
else
--
2.17.2


From 434753adbe8be5534bfb9b7d91746023e8073d16 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Wed, 14 Nov 2018 09:25:13 +0000
Subject: [PATCH 2/3] Bug #700169 - unchecked type

Bug #700169 "Type confusion in setcolorspace"

In seticc() we extract "Name" from a dictionary, if it succeeds we then
use it as a string, without checking the type to see if it is in fact
a string.

Add a check on the type, and add a couple to check that 'N' is an integer
in a few places too.
---
psi/zicc.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/psi/zicc.c b/psi/zicc.c
index 53bdf34..dbd2562 100644
--- a/psi/zicc.c
+++ b/psi/zicc.c
@@ -76,7 +76,7 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
want to have this buffer. */
/* Check if we have the /Name entry. This is used to associate with
specs that have enumerated types to indicate sRGB sGray etc */
- if (dict_find_string(ICCdict, "Name", &pnameval) > 0){
+ if (dict_find_string(ICCdict, "Name", &pnameval) > 0 && r_has_type(pnameval, t_string)){
uint size = r_size(pnameval);
char *str = (char *)gs_alloc_bytes(gs_gstate_memory(igs), size+1, "seticc");
memcpy(str, (const char *)pnameval->value.bytes, size);
@@ -263,6 +263,8 @@ zset_outputintent(i_ctx_t * i_ctx_p)
return code;
if (code == 0)
return_error(gs_error_undefined);
+ if (r_type(pnval) != t_integer)
+ return gs_note_error(gs_error_typecheck);
ncomps = pnval->value.intval;
/* verify the DataSource entry. Creat profile from stream */
@@ -495,6 +497,8 @@ znumicc_components(i_ctx_t * i_ctx_p)
return code;
if (code == 0)
return_error(gs_error_undefined);
+ if (r_type(pnval) != t_integer)
+ return gs_note_error(gs_error_typecheck);
ncomps = pnval->value.intval;
/* verify the DataSource entry. Create profile from stream */
if (dict_find_string(op, "DataSource", &pstrmval) <= 0)
--
2.17.2


From 9a1b3ac61761094713f44dedfce56013308a3b1d Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Wed, 14 Nov 2018 09:31:10 +0000
Subject: [PATCH 3/3] PS interpreter - add some type checking

These were 'probably' safe anyway, since they mostly treat the objects
as integers without checking, which at least can't result in a crash.

Nevertheless, we ought to check.

The return from comparedictkeys could be wrong if one of the keys had
a value which was not an array, it could incorrectly decide the two
were in fact the same.
---
psi/zbfont.c | 15 +++++++++------
psi/zcolor.c | 24 +++++++++++++++++++++++-
psi/zcrd.c | 4 +++-
psi/zfjpx.c | 2 ++
psi/zfont.c | 3 +++
psi/zfont0.c | 3 +++
psi/zimage3.c | 2 ++
psi/ztrans.c | 4 ++++
8 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/psi/zbfont.c b/psi/zbfont.c
index c1d0461..5b830a2 100644
--- a/psi/zbfont.c
+++ b/psi/zbfont.c
@@ -666,6 +666,9 @@ sub_font_params(gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pom
return_error(gs_error_invalidfont);
if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
porigfont = NULL;
+ if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
+ return_error(gs_error_typecheck);
+
if (pomat!= NULL) {
if (porigfont == NULL ||
dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
@@ -676,8 +679,8 @@ sub_font_params(gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pom
/* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
r_has_type(pfontinfo, t_dictionary) &&
- (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0)) {
- if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) &&
+ (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0) && (r_has_type(pfontname, t_name) || r_has_type(pfontname, t_string))) {
+ if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) && (r_has_type(pfontname, t_name) || r_has_type(pfontname, t_string)) &&
r_size(pfontstyle) > 0) {
const byte *tmpStr1 = pfontname->value.const_bytes;
const byte *tmpStr2 = pfontstyle->value.const_bytes;
@@ -775,11 +778,11 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
avm_space useglob = r_is_local(pencoding) ? avm_local : avm_global;
ialloc_set_space(idmemory, useglob);
-
+
count = r_size(pencoding);
if ((code = ialloc_ref_array(&penc, (r_type_attrs(pencoding) & a_readonly), count, "build_gs_font")) < 0)
return code;
-
+
while (count--) {
ref r;
if (array_get(imemory, pencoding, count, &r) < 0){
@@ -790,7 +793,7 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
ref_assign(&(penc.value.refs[count]), &r);
}
else {
-
+
if ((code = obj_cvs(imemory, &r, (byte *)buf, 32, &size, (const byte **)(&bptr))) < 0) {
return(code);
}
@@ -799,7 +802,7 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
ref_assign(&(penc.value.refs[count]), &r);
}
}
-
+
if ((code = dict_put_string(osp, "Encoding", &penc, NULL)) < 0)
return code;
ialloc_set_space(idmemory, curglob);
diff --git a/psi/zcolor.c b/psi/zcolor.c
index fe81e79..b69b8f5 100644
--- a/psi/zcolor.c
+++ b/psi/zcolor.c
@@ -1877,7 +1877,12 @@ static int comparedictkey(i_ctx_t * i_ctx_p, ref *CIEdict1, ref *CIEdict2, char
if (r_type(tempref1) == t_null)
return 1;
- return comparearrays(i_ctx_p, tempref1, tempref2);
+ code = comparearrays(i_ctx_p, tempref1, tempref2);
+
+ if (code > 0)
+ return 1;
+ else
+ return 0;
}
static int hasharray(i_ctx_t * i_ctx_p, ref *m1, gs_md5_state_t *md5)
@@ -5473,6 +5478,9 @@ static int seticcspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIE
return code;
if (code == 0)
return gs_note_error(gs_error_undefined);
+ if (r_type(tempref) != t_integer)
+ return gs_note_error(gs_error_typecheck);
+
components = tempref->value.intval;
if (components > count_of(range)/2)
return_error(gs_error_rangecheck);
@@ -5584,6 +5592,10 @@ static int iccompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
/* Need to check all the various parts */
code1 = dict_find_string(&ICCdict1, "N", &tempref1);
code2 = dict_find_string(&ICCdict2, "N", &tempref2);
+
+ if (!r_has_type(tempref1, t_integer) || !r_has_type(tempref2, t_integer))
+ return 0;
+
if (code1 != code2)
return 0;
if (tempref1->value.intval != tempref2->value.intval)
@@ -5737,6 +5749,8 @@ static int iccalternatespace(i_ctx_t * i_ctx_p, ref *space, ref **r, int *CIESub
return code;
if (code == 0)
return gs_note_error(gs_error_undefined);
+ if (!r_has_type(tempref, t_integer))
+ return_error(gs_error_typecheck);
components = tempref->value.intval;
@@ -5775,6 +5789,9 @@ static int icccomponents(i_ctx_t * i_ctx_p, ref *space, int *n)
return code;
if (code == 0)
return gs_note_error(gs_error_undefined);
+ if (!r_has_type(tempref, t_integer))
+ return gs_note_error(gs_error_typecheck);
+
*n = tempref->value.intval;
return 0;
}
@@ -5791,6 +5808,9 @@ static int iccdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
return code;
if (code == 0)
return gs_note_error(gs_error_undefined);
+ if (!r_has_type(tempref, t_integer))
+ return gs_note_error(gs_error_typecheck);
+
components = tempref->value.intval;
code = dict_find_string(&ICCdict, "Range", &tempref);
if (code > 0 && !r_has_type(tempref, t_null)) {
@@ -5824,6 +5844,8 @@ static int iccrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
return code;
if (code == 0)
return gs_note_error(gs_error_undefined);
+ if (!r_has_type(tempref, t_integer))
+ return gs_note_error(gs_error_typecheck);
components = tempref->value.intval;
code = dict_find_string(&ICCdict, "Range", &tempref);
if (code > 0 && !r_has_type(tempref, t_null)) {
diff --git a/psi/zcrd.c b/psi/zcrd.c
index 7993b15..d58160d 100644
--- a/psi/zcrd.c
+++ b/psi/zcrd.c
@@ -231,8 +231,10 @@ zcrd1_params(os_ptr op, gs_cie_render * pcrd,
return code;
if (dict_find_string(op, "RenderTable", &pRT) > 0) {
- const ref *prte = pRT->value.const_refs;
+ const ref *prte;
+ check_read_type(*pRT, t_array);
+ prte = pRT->value.const_refs;
/* Finish unpacking and checking the RenderTable parameter. */
check_type_only(prte[4], t_integer);
if (!(prte[4].value.intval == 3 || prte[4].value.intval == 4))
diff --git a/psi/zfjpx.c b/psi/zfjpx.c
index c622f48..db1fae2 100644
--- a/psi/zfjpx.c
+++ b/psi/zfjpx.c
@@ -115,6 +115,8 @@ z_jpx_decode(i_ctx_t * i_ctx_p)
dict_find_string(csdict, "N", &nref) > 0) {
if_debug1m('w', imemory, "[w] JPX image has an external %"PRIpsint
" channel colorspace\n", nref->value.intval);
+ if (r_type(nref) != t_integer)
+ return gs_note_error(gs_error_typecheck);
switch (nref->value.intval) {
case 1: state.colorspace = gs_jpx_cs_gray;
break;
diff --git a/psi/zfont.c b/psi/zfont.c
index 9c51792..f6c5ae1 100644
--- a/psi/zfont.c
+++ b/psi/zfont.c
@@ -596,6 +596,9 @@ zfont_info(gs_font *font, const gs_point *pscale, int members,
info->members |= FONT_INFO_FULL_NAME;
if ((members & FONT_INFO_EMBEDDING_RIGHTS)
&& (dict_find_string(pfontinfo, "FSType", &pvalue) > 0)) {
+ if (r_type(pvalue) != t_integer)
+ return gs_note_error(gs_error_typecheck);
+
info->EmbeddingRights = pvalue->value.intval;
info->members |= FONT_INFO_EMBEDDING_RIGHTS;
}
diff --git a/psi/zfont0.c b/psi/zfont0.c
index 4b01c20..a179d7b 100644
--- a/psi/zfont0.c
+++ b/psi/zfont0.c
@@ -243,6 +243,9 @@ zbuildfont0(i_ctx_t *i_ctx_p)
array_get(pfont->memory, &fdepvector, i, &fdep);
/* The lookup can't fail, because of the pre-check above. */
dict_find_string(&fdep, "FID", &pfid);
+ if (!r_has_type(pfid, t_fontID))
+ return gs_note_error(gs_error_typecheck);
+
data.FDepVector[i] = r_ptr(pfid, gs_font);
}
pfont->data = data;
diff --git a/psi/zimage3.c b/psi/zimage3.c
index 87a3dce..2beda9f 100644
--- a/psi/zimage3.c
+++ b/psi/zimage3.c
@@ -53,6 +53,8 @@ zimage3(i_ctx_t *i_ctx_p)
dict_find_string(op, "MaskDict", &pMaskDict) <= 0
)
return_error(gs_error_rangecheck);
+ check_type(*pDataDict, t_dictionary);
+ check_type(*pMaskDict, t_dictionary);
if ((code = pixel_image_params(i_ctx_p, pDataDict,
(gs_pixel_image_t *)&image, &ip_data,
12, false, gs_currentcolorspace(igs))) < 0 ||
diff --git a/psi/ztrans.c b/psi/ztrans.c
index 64defda..0550a10 100644
--- a/psi/ztrans.c
+++ b/psi/ztrans.c
@@ -417,6 +417,7 @@ zimage3x(i_ctx_t *i_ctx_p)
gs_image3x_t_init(&image, NULL);
if (dict_find_string(op, "DataDict", &pDataDict) <= 0)
return_error(gs_error_rangecheck);
+ check_type(*pDataDict, t_dictionary);
if ((code = pixel_image_params(i_ctx_p, pDataDict,
(gs_pixel_image_t *)&image, &ip_data,
16, false, gs_currentcolorspace(igs))) < 0 ||
@@ -453,6 +454,9 @@ image_params *pip_data, const char *dict_name,
if (dict_find_string(op, dict_name, &pMaskDict) <= 0)
return 1;
+ if (!r_has_type(pMaskDict, t_dictionary))
+ return gs_note_error(gs_error_typecheck);
+
if ((mcode = code = data_image_params(mem, pMaskDict, &pixm->MaskDict,
&ip_mask, false, 1, 16, false, false)) < 0 ||
(code = dict_int_param(pMaskDict, "ImageType", 1, 1, 0, &ignored)) < 0 ||
--
2.17.2

32
SOURCES/ghostscript-cve-2018-19477.patch

@ -0,0 +1,32 @@
From 606a22e77e7f081781e99e44644cd0119f559e03 Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Wed, 14 Nov 2018 09:27:00 +0000
Subject: [PATCH] Bug #700168 - add a type check

Bug #700168 "Type confusion in JBIG2Decode"

The code was assuming that .jbig2globalctx was a structure allocated
by the graphics library, without checking.

Add a check to see that it is a structure and that its the correct
type of structure.
---
psi/zfjbig2.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/psi/zfjbig2.c b/psi/zfjbig2.c
index a3d13a2..07b470f 100644
--- a/psi/zfjbig2.c
+++ b/psi/zfjbig2.c
@@ -72,6 +72,8 @@ z_jbig2decode(i_ctx_t * i_ctx_p)
if (r_has_type(op, t_dictionary)) {
check_dict_read(*op);
if ( dict_find_string(op, ".jbig2globalctx", &sop) > 0) {
+ if (!r_is_struct(sop) || !r_has_stype(sop, imemory, st_jbig2_global_data_t))
+ return_error(gs_error_typecheck);
gref = r_ptr(sop, s_jbig2_global_data_t);
s_jbig2decode_set_global_data((stream_state*)&state, gref);
}
--
2.17.2

43
SOURCES/ghostscript-cve-2019-10216.patch

@ -0,0 +1,43 @@
From 5b85ddd19a8420a1bd2d5529325be35d78e94234 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Fri, 2 Aug 2019 15:18:26 +0100
Subject: Bug 701394: protect use of .forceput with executeonly


diff --git a/Resource/Init/gs_type1.ps b/Resource/Init/gs_type1.ps
index 6c7735bc0c..a039ccee35 100644
--- a/Resource/Init/gs_type1.ps
+++ b/Resource/Init/gs_type1.ps
@@ -118,25 +118,25 @@
( to be the same as glyph: ) print 1 index //== exec } if
3 index exch 3 index .forceput
% scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname
- }
+ }executeonly
{pop} ifelse
- } forall
+ } executeonly forall
pop pop
- }
+ } executeonly
{
pop pop pop
} ifelse
- }
+ } executeonly
{
% scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname
pop pop
} ifelse
- } forall
+ } executeonly forall
3 1 roll pop pop
- } if
+ } executeonly if
pop
dup /.AGLprocessed~GS //true .forceput
- } if
+ } executeonly if
%% We need to excute the C .buildfont1 in a stopped context so that, if there
%% are errors we can put the stack back sanely and exit. Otherwise callers won't

56
SOURCES/ghostscript-cve-2019-14811-14812-14813.patch

@ -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

258
SOURCES/ghostscript-cve-2019-14817.patch

@ -0,0 +1,258 @@
From be86d2ff2f0f0ea0e365707f3be0fa0c9e7315ee Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Mon, 18 Feb 2019 12:11:45 -0800
Subject: [PATCH 1/2] Bug 700599: Issue an error message if an ExtGstate is not
found.

Previously, this was silently ignored. Only issue a single warning,
and respect PDFSTOPONERROR to prevent continuing with potentially
incorrect output.

Note that tests_private/pdf/uploads/bug696410.pdf also now gets this
error message (ExtGState" instead of ExtGState in object 10).
---
Resource/Init/pdf_draw.ps | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index 1add3f7..6a2773a 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -494,7 +494,16 @@ end
dup {
oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
} forall pop
- } if
+ } {
+ //pdfdict /.gs_warning_issued known not {
+ (\n **** Error 'gs' ignored -- ExtGState missing from Resources.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ //pdfdict /.gs_warning_issued //true .forceput
+ PDFSTOPONERROR { /gs /undefined signalerror } if
+ } if
+ }
+ ifelse
} bind executeonly def
% ------ Transparency support ------ %
--
2.20.1


From cd1b1cacadac2479e291efe611979bdc1b3bdb19 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 2/2] 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 d3c3a5f..5dabe4d 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -154,7 +154,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 6a2773a..068ba7c 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
@@ -1127,7 +1127,7 @@ currentdict end readonly def
.setglobal
pdfformaterror
} executeonly ifelse
- }
+ } executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
@@ -1135,8 +1135,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
@@ -1150,14 +1150,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 8b8fef8..86b1870 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
@@ -1225,19 +1225,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
@@ -2022,9 +2023,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 e44288e..ecde3d4 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -2696,15 +2696,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 c2e7461..12d5a66 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

40
SOURCES/ghostscript-cve-2019-14869.patch

@ -0,0 +1,40 @@
diff --git a/Resource/Init/gs_ttf.ps b/Resource/Init/gs_ttf.ps
index 064b6c8..600907e 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 .forceput
+ 7 index 2 index 3 -1 roll exch put
} 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 .forceput
+ 5 index 3 1 roll put
//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 .forceput
+ exch pop 5 index 3 1 roll put
}
{
pop pop
@@ -1486,7 +1486,7 @@ mark
} ifelse
]
TTFDEBUG { (Encoding: ) print dup === flush } if
-} .bind executeonly odef % hides .forceput
+} .bind odef
% to be removed 9.09......
currentdict /postalias undef

615
SOURCES/ghostscript-cve-2019-3835.patch

@ -0,0 +1,615 @@
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 a2503f1..9a1f2b2 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -1534,10 +1534,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>
@@ -2506,4 +2514,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 9a1f2b2..e5678b9 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2253,6 +2253,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 | 6 +++---
Resource/Init/gs_type1.ps | 6 +++---
6 files changed, 52 insertions(+), 47 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 01eca35..ab062e1 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
@@ -1178,13 +1178,13 @@ currentdict /.putgstringcopy .forceundef
//.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 e5678b9..a054222 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2184,9 +2184,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
@@ -2266,7 +2263,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.
@@ -2471,6 +2467,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
@@ -2479,16 +2485,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
@@ -2515,7 +2534,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..996d1e2 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 2935d9c..1f38dd7 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 a054222..ca20f12 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2485,24 +2485,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

56
SOURCES/ghostscript-cve-2019-3838.patch

@ -0,0 +1,56 @@
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

866
SOURCES/ghostscript-cve-2019-3839.patch

@ -0,0 +1,866 @@
From 95aa78beae9489d5c9f898fe2032aa23f860867d Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Fri, 21 Sep 2018 11:16:18 -0700
Subject: [PATCH 1/6] Catch errors in setpagesize, .setpagesize and
setpagedevice and cleanup

Bug 699794 showed that attempt to change page size in SAFER mode when the
nulldevice was the currentdevice would leave 'false' on the stack. Run
.setdevice in stopped and clean up, and also clean up .setpagesize
---
Resource/Init/gs_lev2.ps | 9 ++++++++-
Resource/Init/gs_setpd.ps | 9 +++++++--
Resource/Init/gs_statd.ps | 22 ++++++++++++++++++----
3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index b69303d..ab0c32e 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -616,7 +616,14 @@ currentuserparams /WaitTimeout known
.dicttomark setpagedevice
/WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
} bind def
-/.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def
+/.setpagesize
+ { 2 copy 2 array astore /PageSize .dict1 { setpagedevice } stopped {
+ pop % the setpagedevice dict
+ /setpagesize $error /errorname get signalerror
+ } {
+ pop pop % success -- pop the arguments
+ } ifelse
+ } bind def
/setduplexmode { /Duplex .dict1 setpagedevice } bind def
/setmargins
{ exch 2 array astore /Margins .dict1 setpagedevice
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
index 46e5810..7875d1f 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -932,10 +932,15 @@ SETPDDEBUG { (Recovering.) = pstack flush } if
% Stack: mark ... <merged> <failed> <device> <eraseflag>
SETPDDEBUG { (Installing.) = pstack flush } if
- pop
+ pop
% .setdevice clears the current page device!
.currentpagedevice pop exch
- .setdevice pop
+ { .setdevice } stopped {
+ cleartomark exch pop
+ /setpagedevice $error /errorname get
+ signalerror
+ } if
+ pop
.setpagedevice
% Implement UseCIEColor directly if this is a LL3 system.
diff --git a/Resource/Init/gs_statd.ps b/Resource/Init/gs_statd.ps
index 64c6463..34b759c 100644
--- a/Resource/Init/gs_statd.ps
+++ b/Resource/Init/gs_statd.ps
@@ -39,7 +39,13 @@ statusdict begin
% These procedures are also accessed as data structures during initialization,
% so the page dimensions must be the first two elements of the procedure.
-/.setpagesize { /statusdict .systemvar begin .setpagesize end } bind def
+/.setpagesize {
+ /statusdict .systemvar begin
+ { .setpagesize } stopped {
+ /setpagesize $error /errorname get signalerror
+ } if
+ end
+} bind def
% Page sizes defined by Adobe documentation
% Note: these executable arrays should all begin with two
@@ -261,9 +267,17 @@ readonly def
% The Adobe documentation only defines setpagetype
% (a Level 1 operator) as accepting the values 0 and 1,
% so we do too.
- {/letter /note} 1 index get
- //systemdict /userdict get exch get cvx exec
- /pagetype exch def
+ dup type /integertype ne {
+ /setpage /typecheck signalerror
+ } {
+ dup 0 ne 1 index 1 ne or {
+ /setpage /rangecheck signalerror
+ } {
+ {/letter /note} 1 index get
+ //systemdict /userdict get exch get cvx exec
+ } ifelse
+ /pagetype exch def
+ } ifelse
end
} bind def
--
2.20.1


From c29ec2fff76e45bbf9cd767ff541556c5d064be4 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Fri, 21 Sep 2018 12:00:50 -0700
Subject: [PATCH 2/6] Add parameter checking in setresolution

Found in sequence for bug 699794
---
Resource/Init/gs_lev2.ps | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index ab0c32e..0f0d573 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -637,7 +637,14 @@ currentuserparams /WaitTimeout known
.dicttomark setpagedevice
} bind def
/setresolution
- { dup 2 array astore /HWResolution .dict1 setpagedevice
+ { count 1 lt { /setresolution /stackunderflow signalerror } if
+ dup type dup /integertype eq exch /realtype eq or not
+ {
+ /setresolution /typecheck signalerror
+ } if
+ dup 2 array astore /HWResolution .dict1 { setpagedevice } stopped {
+ pop /setresolution $error /errorname get signalerror
+ } if
} bind def
%END PAGEDEVICE
--
2.20.1


From fe4c47d8e25d6366ecbb5ff487348148b908a89e Mon Sep 17 00:00:00 2001
From: Nancy Durgin <nancy.durgin@artifex.com>
Date: Tue, 13 Nov 2018 14:23:41 -0800
Subject: [PATCH 3/6] Undefine some level2-related operators

These are only a partial set. Undefine them in both the level2dict and
systemdict. They are undef'd in gs_init.ps because they are used outside
the scope of just gs_lev2.ps

/.execform1
/.getdevparams
/.setuserparams2
/.startjob
/.checkFilePermitparams
/.checksetparams
/.copyparam
/.setpagesize

Rename .dict1 to .pair2dict and use immediate reference.

Undef these at end of gs_lev2.ps (should never make it into systemdict):
/.pair2dict
/.checkprocesscomment
---
Resource/Init/gs_init.ps | 18 ++++++++++++++++++
Resource/Init/gs_lev2.ps | 34 +++++++++++++++++++++-------------
2 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 48bb96d..e915f11 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2271,6 +2271,24 @@ SAFER { .setsafeglobal } if
]
{systemdict exch .forceundef} forall
+ % level 2 operators, undefine from both systemdict and level2dict
+ [
+ /.execform1
+ /.getdevparams
+ /.setuserparams2
+ /.startjob
+ /.checkFilePermitparams
+ /.checksetparams
+ /.copyparam
+ /.setpagesize
+
+% Couldn't figure out how to do these yet
+% /.checkparamtype
+% /.startnewjob
+ ]
+ dup {level2dict exch .forceundef} forall
+ {systemdict exch .forceundef} forall
+
//systemdict /UndefinePostScriptOperators .forceundef
} .bind executeonly def % must be bound and hidden for .forceundef
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 0f0d573..e6f0645 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -64,7 +64,7 @@ level2dict begin
pop
} ifelse pop pop
} forall pop pop
-} .bind def % not odef, shouldn't reset stacks
+} .bind odef
% currentuser/systemparams creates and returns a dictionary in the
% current VM. The easiest way to make this work is to copy any composite
@@ -101,7 +101,7 @@ level2dict begin
1 index length string exch .setglobal
copy exch not { readonly } if
} if
-} .bind def
+} .bind odef
% Some user parameters are managed entirely at the PostScript level.
% We take care of that here.
@@ -345,13 +345,13 @@ end
} ifelse
} .bind def
/ProcessComment //null .definepsuserparam
-psuserparams /ProcessComment {.checkprocesscomment} put
+psuserparams /ProcessComment {//.checkprocesscomment exec} put
(%ProcessComment) cvn {
/ProcessComment getuserparam
dup //null eq { pop pop pop } { exec } ifelse
} bind def
/ProcessDSCComment //null .definepsuserparam
-psuserparams /ProcessDSCComment {.checkprocesscomment} put
+psuserparams /ProcessDSCComment {//.checkprocesscomment exec} put
/.loadingfont //false def
(%ProcessDSCComment) cvn {
/ProcessDSCComment getuserparam
@@ -556,7 +556,8 @@ end % serverdict
% Note that statusdict must be allocated in local VM.
% We don't bother with many of these yet.
-/.dict1 { exch mark 3 1 roll .dicttomark } bind def
+% convenience function to make a dictionary from an object and a key
+/.pair2dict { exch mark 3 1 roll .dicttomark } bind def
currentglobal //false setglobal 25 dict exch setglobal begin
currentsystemparams
@@ -569,11 +570,11 @@ systemdict /buildtime dup load put
/checkpassword { .checkpassword 0 gt } bind def
dup /DoStartPage known
{ /dostartpage { /DoStartPage getsystemparam } bind def
- /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def
+ /setdostartpage { /DoStartPage //.pair2dict exec setsystemparams } bind def
} if
dup /StartupMode known
{ /dosysstart { /StartupMode getsystemparam 0 ne } bind def
- /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def
+ /setdosysstart { { 1 } { 0 } ifelse /StartupMode //.pair2dict exec setsystemparams } bind def
} if
%****** Setting jobname is supposed to set userparams.JobName, too.
/jobname { /JobName getuserparam } bind def
@@ -581,7 +582,7 @@ dup /StartupMode known
/ramsize { /RamSize getsystemparam } bind def
/realformat 1 index /RealFormat get def
dup /PrinterName known
- { /setprintername { /PrinterName .dict1 setsystemparams } bind def
+ { /setprintername { /PrinterName //.pair2dict exec setsystemparams } bind def
} if
/printername
{ currentsystemparams /PrinterName .knownget not { () } if exch copy
@@ -617,18 +618,18 @@ currentuserparams /WaitTimeout known
/WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
} bind def
/.setpagesize
- { 2 copy 2 array astore /PageSize .dict1 { setpagedevice } stopped {
+ { 2 copy 2 array astore /PageSize //.pair2dict exec { setpagedevice } stopped {
pop % the setpagedevice dict
/setpagesize $error /errorname get signalerror
} {
pop pop % success -- pop the arguments
} ifelse
} bind def
-/setduplexmode { /Duplex .dict1 setpagedevice } bind def
+/setduplexmode { /Duplex //.pair2dict exec setpagedevice } bind def
/setmargins
- { exch 2 array astore /Margins .dict1 setpagedevice
+ { exch 2 array astore /Margins //.pair2dict exec setpagedevice
} bind def
-/setpagemargin { 0 2 array astore /PageOffset .dict1 setpagedevice } bind def
+/setpagemargin { 0 2 array astore /PageOffset //.pair2dict exec setpagedevice } bind def
/setpageparams
{ mark /PageSize 6 -2 roll
4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore
@@ -642,7 +643,7 @@ currentuserparams /WaitTimeout known
{
/setresolution /typecheck signalerror
} if
- dup 2 array astore /HWResolution .dict1 { setpagedevice } stopped {
+ dup 2 array astore /HWResolution //.pair2dict exec { setpagedevice } stopped {
pop /setresolution $error /errorname get signalerror
} if
} bind def
@@ -1254,3 +1255,10 @@ def
%END TN 5044 psuedo-ops
end % level2dict
+
+% undefine things defined in this file and not referenced elsewhere
+[
+ /.checkprocesscomment
+ /.pair2dict
+]
+{level2dict exch .forceundef} forall
--
2.20.1


From 932f4106a00e99e4ee32dcc02e57d3636f383ea1 Mon Sep 17 00:00:00 2001
From: Nancy Durgin <nancy.durgin@artifex.com>
Date: Wed, 28 Nov 2018 10:09:01 -0800
Subject: [PATCH 4/6] Undef internal functions from level2dict

---
Resource/Init/gs_lev2.ps | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index e6f0645..7638f2a 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -117,7 +117,7 @@ counttomark 2 idiv {
} repeat pop
/.definepsuserparam { % <name> <value> .definepsuserparam -
psuserparams 3 copy pop
- type cvlit /.checkparamtype cvx 2 packedarray cvx put
+ type cvlit //.checkparamtype /exec load 3 packedarray cvx put
userparams 3 1 roll put
} .bind def
end
@@ -211,7 +211,7 @@ end
} forall
} if
/setsystemparams //pssystemparams mark exch {
- type cvlit /.checkparamtype cvx 2 packedarray cvx
+ type cvlit //.checkparamtype /exec load 3 packedarray cvx
} forall .dicttomark .checksetparams
% Set the C-level system params. If this succeeds, we know that
% the password check succeeded.
@@ -1260,5 +1260,7 @@ end % level2dict
[
/.checkprocesscomment
/.pair2dict
+ /.setcolorrendering1
+ /.checkparamtype
]
{level2dict exch .forceundef} forall
--
2.20.1


From e7ff64cf9b756278f19c87d295ee0fd95c955c05 Mon Sep 17 00:00:00 2001
From: Nancy Durgin <nancy.durgin@artifex.com>
Date: Wed, 23 Jan 2019 12:00:30 -0800
Subject: [PATCH 5/6] Fixed bug caused by the way .checksetparams was undef'd

Previously, had undef'd it by making it an operator.
Now just use an immediate reference and undef it in the gs_lev2.ps file.

This fixes bug introduced in commit fe4c47d8e25d6366ecbb5ff487348148b908a89e.

Undef'ing .checksetparams by making it an operator doesn't work right because
errors report .checksetparams as the offending function instead of
the operator that uses it (setsystemparams in this case).

This caused an error in file /tests_private/ps/ps3cet/27-09.PS on page 3,
where it reports the offending function of some error-handling tests.
Reporting function should be 'setsystemparams', not '.checksetparams' on
this page.
---
Resource/Init/gs_init.ps | 1 -
Resource/Init/gs_lev2.ps | 7 ++++---
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index e915f11..a2503f1 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2278,7 +2278,6 @@ SAFER { .setsafeglobal } if
/.setuserparams2
/.startjob
/.checkFilePermitparams
- /.checksetparams
/.copyparam
/.setpagesize
diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 7638f2a..de1cc94 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -64,7 +64,7 @@ level2dict begin
pop
} ifelse pop pop
} forall pop pop
-} .bind odef
+} .bind def
% currentuser/systemparams creates and returns a dictionary in the
% current VM. The easiest way to make this work is to copy any composite
@@ -129,7 +129,7 @@ end
/.setuserparams2 {
% Check that we will be able to set the PostScript-level
% user parameters.
- /setuserparams /psuserparams .systemvar .checksetparams
+ /setuserparams /psuserparams .systemvar //.checksetparams exec
% Set the C-level user params. If this succeeds, we know that
% the password check succeeded.
dup .setuserparams
@@ -212,7 +212,7 @@ end
} if
/setsystemparams //pssystemparams mark exch {
type cvlit //.checkparamtype /exec load 3 packedarray cvx
- } forall .dicttomark .checksetparams
+ } forall .dicttomark //.checksetparams exec
% Set the C-level system params. If this succeeds, we know that
% the password check succeeded.
dup .setsystemparams
@@ -1262,5 +1262,6 @@ end % level2dict
/.pair2dict
/.setcolorrendering1
/.checkparamtype
+ /.checksetparams
]
{level2dict exch .forceundef} forall
--
2.20.1


From 4ec9ca74bed49f2a82acb4bf430eae0d8b3b75c9 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Thu, 31 Jan 2019 11:31:30 -0800
Subject: [PATCH 6/6] Hide pdfdict and GS_PDF_ProcSet (internal stuff for the
PDF interp).

We now keep GS_PDF_ProcSet in pdfdict, and immediately bind pdfdict
where needed so we can undef it after the last PDF interp file has
run (pdf_sec.ps).
---
Resource/Init/pdf_base.ps | 11 ++++----
Resource/Init/pdf_draw.ps | 59 +++++++++++++++++++--------------------
Resource/Init/pdf_font.ps | 9 +++---
Resource/Init/pdf_main.ps | 25 +++++++++--------
Resource/Init/pdf_ops.ps | 11 ++++----
Resource/Init/pdf_sec.ps | 4 ++-
6 files changed, 60 insertions(+), 59 deletions(-)

diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
index c62ac0e..d3c3a5f 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -23,7 +23,6 @@
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
-/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
pdfdict begin
% Define the name interpretation dictionary for reading values.
@@ -130,11 +129,11 @@ currentdict /num-chars-dict .undef
/.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ?
PDFDEBUG {
- pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if
+ //pdfdict /PDFSTEPcount known not { //pdfdict /PDFSTEPcount 1 .forceput } executeonly if
PDFSTEP {
- pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
+ //pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput
PDFSTEPcount 1 gt {
- pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
+ //pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput
} executeonly
{
dup ==only
@@ -142,10 +141,10 @@ currentdict /num-chars-dict .undef
( ? ) print flush 1 //false .outputpage
(%stdin) (r) file 255 string readline {
token {
- exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput
+ exch pop //pdfdict /PDFSTEPcount 3 -1 roll .forceput
} executeonly
{
- pdfdict /PDFSTEPcount 1 .forceput
+ //pdfdict /PDFSTEPcount 1 .forceput
} executeonly ifelse % token
} {
pop /PDFSTEP //false def % EOF on stdin
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index d743ae1..1add3f7 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -18,8 +18,7 @@
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
-/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
-GS_PDF_ProcSet begin
+/GS_PDF_ProcSet load begin
pdfdict begin
% For simplicity, we use a single interpretation dictionary for all
@@ -113,7 +112,7 @@ pdfdict begin
/resolvefunction { % <fndict> resolvefunction <function>
.resolvefn
- PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Function: ) print dup === flush } if } if
+ PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Function: ) print dup === flush } if } if
} bind executeonly def
/resolvefnproc { % <fndict> resolvefnproc <proc>
@@ -1073,7 +1072,7 @@ currentdict end readonly def
%% finished running the PaintProc.
/.actual_pdfpaintproc { % <patdict> <resdict> .pdfpaintproc -
- PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Begin PaintProc) print dup === flush } if } if
+ PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Begin PaintProc) print dup === flush } if } if
PDFfile fileposition 3 1 roll
q
1 index /PaintType oget 1 eq {
@@ -1108,21 +1107,21 @@ currentdict end readonly def
Q
}{
(\n **** Error: File has unbalanced q/Q operators \(too many Q's\)\n Output may be incorrect.\n)
- pdfdict /.Qqwarning_issued .knownget
+ //pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
@@ -1131,21 +1130,21 @@ currentdict end readonly def
} loop
{
(\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n)
- pdfdict /.Qqwarning_issued .knownget
+ //pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
@@ -1156,7 +1155,7 @@ currentdict end readonly def
/pdfemptycount exch def
Q
- PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if
+ PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if
PDFfile exch setfileposition
} bind executeonly odef
@@ -1227,7 +1226,7 @@ currentdict end readonly def
] cvx put
dup /BBox 2 copy knownoget { normrect FixPatternBBox put } { pop pop } ifelse
dup /.pattern_uses_transparency 1 index patternusestransparency put
- PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Pattern: ) print dup === flush } if } if
+ PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Pattern: ) print dup === flush } if } if
} bind executeonly def
/ignore_color_op ( **** Error: Ignoring a color operation in a cached context.\n Output may be incorrect.\n) readonly def
@@ -2348,16 +2347,16 @@ currentdict /last-ditch-bpc-csp undef
} bind executeonly def
/IncrementAppearanceNumber {
- pdfdict /AppearanceNumber .knownget {
- 1 add pdfdict /AppearanceNumber 3 -1 roll .forceput
+ //pdfdict /AppearanceNumber .knownget {
+ 1 add //pdfdict /AppearanceNumber 3 -1 roll .forceput
} executeonly
{
- pdfdict /AppearanceNumber 0 .forceput
+ //pdfdict /AppearanceNumber 0 .forceput
} executeonly ifelse
}bind executeonly odef
/MakeAppearanceName {
- pdfdict /AppearanceNumber get
+ //pdfdict /AppearanceNumber get
10 string cvs
dup length 10 add string dup 0 (\{FormName) putinterval
dup 3 -1 roll
@@ -2378,17 +2377,17 @@ currentdict /last-ditch-bpc-csp undef
gsave initclip
MakeNewAppearanceName
.pdfFormName
- pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get} {//false}ifelse exch
- pdfdict /.PreservePDFForm true .forceput
+ //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch
+ //pdfdict /.PreservePDFForm true .forceput
DoForm
- pdfdict /.PreservePDFForm 3 -1 roll .forceput
+ //pdfdict /.PreservePDFForm 3 -1 roll .forceput
grestore
} bind executeonly odef
/DoForm {
%% save the current value, if its true we will set it to false later, in order
%% to prevent us preserving Forms which are used *from* an annotation /Appearance.
- pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get} {//false}ifelse exch
+ //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch
%% We may alter the Default* colour spaces, if the Resources
%% ColorSpace entry contains one of them. But we don't want that
@@ -2503,13 +2502,13 @@ currentdict /last-ditch-bpc-csp undef
pdfemptycount countdictstack 3 -1 roll
/pdfemptycount count 4 sub store
- pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get}{//false} ifelse
+ //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get}{//false} ifelse
{
%% We must *not* preserve any subsidiary forms (curently at least) as PDF
%% form preservation doesn't really work. This is used just for Annotation
%% Appearances currently, and if they should happen to use a form, we do not
%% want to preserve it.
- pdfdict /.PreservePDFForm false .forceput
+ //pdfdict /.PreservePDFForm false .forceput
/q cvx /execform cvx 5 -2 roll
} executeonly
{
@@ -2542,7 +2541,7 @@ currentdict /last-ditch-bpc-csp undef
saved_DCMYK /DefaultCMYK exch /ColorSpace defineresource pop
end
} if
- pdfdict /.PreservePDFForm 3 -1 roll .forceput
+ //pdfdict /.PreservePDFForm 3 -1 roll .forceput
} bind executeonly odef
/_dops_save 1 array def
@@ -2701,13 +2700,13 @@ drawopdict begin
% Start by getting the object number for a Form XObject
dup Page /XObject obj_get dup 0 eq not {
% Now get the recording dictionary and see if that object number has been seen
- pdfdict /Recursive_XObject_D get 1 index known {
+ //pdfdict /Recursive_XObject_D get 1 index known {
( **** Error: Recursive XObject detected, ignoring ") print 1 index 256 string cvs print (", object number ) print 256 string cvs print (\n) print
( Output may be incorrect.\n) pdfformaterror
//false
}{
% We haven't seen it yet, so record it.
- pdfdict /Recursive_XObject_D get 1 index null put
+ //pdfdict /Recursive_XObject_D get 1 index null put
3 1 roll
//true
}ifelse
@@ -2745,7 +2744,7 @@ drawopdict begin
( Output may be incorrect.\n) pdfformaterror
} ifelse
PDFfile exch setfileposition
- pdfdict /Recursive_XObject_D get exch undef
+ //pdfdict /Recursive_XObject_D get exch undef
}{
% Otherwise ignore it and tidy up the stacks
pop pop
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index 46408f9..275b659 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -37,8 +37,7 @@
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
-/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
-GS_PDF_ProcSet begin
+/GS_PDF_ProcSet load begin % from userdict at this point
pdfdict begin
% We cache the PostScript font in an additional element of the
@@ -1219,11 +1218,11 @@ currentdict /eexec_pdf_param_dict .undef
.pdfruncontext
countdictstack BuildCharDictDepth sub
{
- pdfdict /.Qqwarning_issued .knownget {not}{//true} ifelse
+ //pdfdict /.Qqwarning_issued .knownget {not}{//true} ifelse
{
(\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
+ //pdfdict /.Qqwarning_issued //true .forceput
} executeonly if
Q
} repeat
@@ -2334,7 +2333,7 @@ currentdict /bndef undef
dup //null eq
{pop}
{
- pdfdict /InputPDFFileName .knownget {.CRCHashFilenameAndObject} if
+ //pdfdict /InputPDFFileName .knownget {.CRCHashFilenameAndObject} if
exch dup /.OrigUniqueIDXUID .knownget not
{
dup /XUID .knownget not
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index dd1480b..e44288e 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -18,8 +18,9 @@
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
-/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
pdfdict begin
+/GS_PDF_ProcSet dup load def % keep in pdfdict to hide it
+userdict /GS_PDF_ProcSet undef
% Patch in an obsolete variable used by some third-party software.
/#? //false def
@@ -304,8 +305,8 @@ currentdict /runpdfstring .undef
/Page //null def
/DSCPageCount 0 def
/PDFSave //null def
- GS_PDF_ProcSet begin
- pdfdict begin
+ //pdfdict /GS_PDF_ProcSet get begin
+ //pdfdict begin
pdfopen begin
/CumulativePageCount currentpagedevice /PageCount get def
} bind executeonly def
@@ -624,7 +625,7 @@ currentdict /runpdfstring .undef
%% copied to a temporary file) and store it in pdfdict. We will use this for
%% hashing fonts to detect if fonts with the same name are from different files.
%%
- dup currentglobal exch true setglobal .getfilename exch setglobal /InputPDFFileName exch pdfdict 3 1 roll .forceput
+ dup currentglobal exch true setglobal .getfilename exch setglobal /InputPDFFileName exch //pdfdict 3 1 roll .forceput
//runpdfbegin exec
//pdf_collection_files exec
@@ -1390,7 +1391,7 @@ currentdict /xref-char-dict undef
} bind executeonly def
/pdfopenfile { % <file> pdfopenfile <dict>
- pdfdict readonly pop % can't do it any earlier than this
+ //pdfdict readonly pop % can't do it any earlier than this
32 dict begin
/LocalResources 0 dict def
/DefaultQstate //null def % establish binding
@@ -2684,21 +2685,21 @@ currentdict /PDF2PS_matrix_key undef
StreamRunAborted not {
(\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n)
- pdfdict /.Qqwarning_issued .knownget
+ //pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
@@ -2710,8 +2711,8 @@ currentdict /PDF2PS_matrix_key undef
Repaired % pass Repaired state around the restore
RepairedAnError
PDFSave restore
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //false .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //false .forceput
.setglobal
/RepairedAnError exch def
/Repaired exch def
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index aa09641..c2e7461 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -24,6 +24,7 @@
systemdict /pdfmark known not
{ userdict /pdfmark { cleartomark } bind executeonly put } if
+systemdict /pdfdict where { pop } { /pdfdict 100 dict put } ifelse
userdict /GS_PDF_ProcSet 256 dict dup begin
% ---------------- Abbreviations ---------------- %
@@ -174,21 +175,21 @@ currentdict /gput_always_allow .undef
{
(\n **** Error: File has unbalanced q/Q operators \(too many Q's\)\n Output may be incorrect.\n)
- pdfdict /.Qqwarning_issued .knownget
+ //pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
}
{
- currentglobal pdfdict gcheck .setglobal
- pdfdict /.Qqwarning_issued //true .forceput
+ currentglobal //pdfdict gcheck .setglobal
+ //pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
diff --git a/Resource/Init/pdf_sec.ps b/Resource/Init/pdf_sec.ps
index 143efb7..a8e3d2e 100644
--- a/Resource/Init/pdf_sec.ps
+++ b/Resource/Init/pdf_sec.ps
@@ -39,7 +39,6 @@
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
-/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
pdfdict begin
% Older ghostscript versions do not have .pdftoken, so we use 'token' instead.
@@ -748,4 +747,7 @@ currentdict /PDFScanRules_null undef
} bind executeonly def
end % pdfdict
+
+systemdict /pdfdict .forceundef % hide pdfdict
+
.setglobal
--
2.20.1

39
SOURCES/ghostscript-cve-2019-6116-downstream.patch

@ -0,0 +1,39 @@
diff --git a/Resource/Init/gs_dps.ps b/Resource/Init/gs_dps.ps
index 00c14d5..2a6f4f3 100644
--- a/Resource/Init/gs_dps.ps
+++ b/Resource/Init/gs_dps.ps
@@ -117,7 +117,7 @@
.dicttomark readonly /localdicts exch put
% localdicts is now defined in userdict.
% Copy the definitions into systemdict.
- localdicts { .forcedef } forall
+ localdicts { .forcedef } executeonly forall
% Set the user parameters.
userparams readonly .setuserparams
% Establish the initial gstate(s).
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 4807f81..01eca35 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -1136,7 +1136,7 @@ $error /SubstituteFont { } put
% Stack: fontdict
} executeonly
if pop % Stack: origfontname fontdirectory path
- }
+ } executeonly
if pop pop % Stack: origfontname
% The font definitely did not load correctly.
diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index f1d1728..46408f9 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -692,7 +692,7 @@ currentdict end readonly def
currentglobal exch dup gcheck setglobal
dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput
3 2 roll setglobal
- } if % font-res font-dict encoding|null font-info g2u
+ } executeonly if % font-res font-dict encoding|null font-info g2u
exch pop exch % font-res font-dict g2u encoding|null
userdict /.lastToUnicode get % font-res font-dict g2u Encoding|null CMap
.convert_ToUnicode-into-g2u % font-res font-dict

1178
SOURCES/ghostscript-cve-2019-6116.patch

File diff suppressed because it is too large Load Diff

201
SOURCES/ghostscript-fix-DSC-comment-parsing.patch

@ -0,0 +1,201 @@
From f31702b38fba21153e26c3417c838618e7cfd16f Mon Sep 17 00:00:00 2001
From: Ken Sharp <ken.sharp@artifex.com>
Date: Fri, 21 Sep 2018 15:28:15 +0100
Subject: [PATCH] pdfwrite - fix DSC comment parsing

This may affect other DSC parsing utilities. For some reason double
comment (%%) marks are being interpreted 'sometimes' in gs_init.ps
as DSC comments. This only happens when reading the init files from disk
becuase the ROM file system strips comments.

Passing these to pdfwrite causes it to drop later DSC comments, such
as %%Title: and %%Creator: which meant the information wasn't being
embedded in the document information dictionary.

Fix by converting double %% to single % comments, document this in the
header of gs_init.ps.
---
Resource/Init/gs_init.ps | 93 +++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 44 deletions(-)

diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index ca20f12..d1278ea 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -20,6 +20,11 @@
% %% Replace <n> <file(s)>
% indicate places where the next <n> lines should be replaced by
% the contents of <file(s)>, when creating a single merged init file.
+%
+% For reasons not clear to me, some cases of %% are being treated as
+% DSC comments when (and only when) the resource files are disk based
+% This can kill DSC parsing for pdfwrite at least, so avoid using
+% double % comments in this file.
% The interpreter can call out to PostScript code. All procedures
% called in this way, and no other procedures defined in these
@@ -136,12 +141,12 @@ currentdict /PDFNOCIDFALLBACK known /PDFNOCIDFALLBACK exch def
ifelse
.bind def
-%% This was a debugging switch removed in 9.22, no other software
-%% should have had any regard for it, and even if testing its value
-%% should have checked its existence first. However pstotext, an
-%% ancient and no longer maintained piece of softare, did check
-%% its value unconditionally. So we retain this key in the dictionary
-%% purely for backward compatibility.
+% This was a debugging switch removed in 9.22, no other software
+% should have had any regard for it, and even if testing its value
+% should have checked its existence first. However pstotext, an
+% ancient and no longer maintained piece of softare, did check
+% its value unconditionally. So we retain this key in the dictionary
+% purely for backward compatibility.
/NOBIND false def
currentdict /BATCH known /BATCH exch def
@@ -2123,12 +2128,12 @@ currentdict /tempfilepaths undef
//SAFETY /safe //true .forceput % overrides readonly
} .bind executeonly odef
-%% This is only used during startup. Its required so that
-%% we can detect in setpagdevice that we are in fact in startup
-%% and allocate a *global* instead of local VM. We need it to be
-%% global to satisfy Display PostScript (see start of /setpagdevice
-%% in gs_setpd.ps)
-%%
+% This is only used during startup. Its required so that
+% we can detect in setpagdevice that we are in fact in startup
+% and allocate a *global* instead of local VM. We need it to be
+% global to satisfy Display PostScript (see start of /setpagdevice
+% in gs_setpd.ps)
+%
/.locksafeglobal {
.locksafe_userparams
systemdict /getenv {pop //false} put
@@ -2157,8 +2162,8 @@ currentdict /tempfilepaths undef
.locksafe
} .bind executeonly odef
-%% See /.locksafeglobal above.
-%%
+% See /.locksafeglobal above.
+%
/.setsafeglobal {
SAFETY /safe get not {
<<
@@ -2193,22 +2198,22 @@ SAFER { .setsafeglobal } if
/UndefinePostScriptOperators {
- %% This list is of Display PostScript operators. We believe that Display PostScript
- %% was never fully implemented and the only known user, GNUStep, is no longer
- %% using it. So lets remove it.
+ % This list is of Display PostScript operators. We believe that Display PostScript
+ % was never fully implemented and the only known user, GNUStep, is no longer
+ % using it. So lets remove it.
[
/condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify
/wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip
/viewclip /viewclippath /defineusername
- %% NeXT DPS extensions
+ % NeXT DPS extensions
/currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams
]
{systemdict exch .forceundef} forall
- %% This list is of operators which no longer appear to be used, and which we do not believe
- %% to have any real use. For now we will undefine the operstors so they cannot easily be used
- %% but can be easily restored (just delete the name from the list in the array). In future
- %% we may remove the operator and the code implementation entirely.
+ % This list is of operators which no longer appear to be used, and which we do not believe
+ % to have any real use. For now we will undefine the operstors so they cannot easily be used
+ % but can be easily restored (just delete the name from the list in the array). In future
+ % we may remove the operator and the code implementation entirely.
[
/.bitadd /.charboxpath /.cond /.runandhide /.popdevicefilter
/.execfile /.filenamesplit /.file_name_parent
@@ -2217,15 +2222,15 @@ SAFER { .setsafeglobal } if
/.currentlimitclamp /.dotorientation /.setaccuratecurves /.setcurvejoin /.setdashadapt /.setdotorientation
/.setlimitclamp /.currentscreenlevels /.dashpath /.pathbbox /.identeq /.identne /.tokenexec /.forgetsave /.pantonecallback
- %% Used by our own test suite files
- %%/.setdotlength % Bug687720.ps
+ % Used by our own test suite files
+ %/.setdotlength % Bug687720.ps
]
{systemdict exch .forceundef} forall
- %% This list of operators are used internally by various parts of the Ghostscript startup code.
- %% Since each operator is a potential security vulnerability, and any operator listed here
- %% is not required once the initialisation is complete and functions are bound, we undefine
- %% the ones that aren't needed at runtime.
+ % This list of operators are used internally by various parts of the Ghostscript startup code.
+ % Since each operator is a potential security vulnerability, and any operator listed here
+ % is not required once the initialisation is complete and functions are bound, we undefine
+ % the ones that aren't needed at runtime.
[
/.callinstall /.callbeginpage /.callendpage
/.currentstackprotect /.setstackprotect /.errorexec /.finderrorobject /.installsystemnames /.bosobject /.fontbbox
@@ -2297,12 +2302,12 @@ SAFER { .setsafeglobal } if
} .bind executeonly def % must be bound and hidden for .forceundef
/UndefinePDFOperators {
- %% This list of operators are used internally by various parts of the Ghostscript PDF interpreter.
- %% Since each operator is a potential security vulnerability, and any operator listed here
- %% is not required once the initislisation is complete and functions are bound, we undefine
- %% the ones that aren't needed at runtime.
- %% This function is only called if DELAYBIND is true. It is a copy of the code at the end of pdf_main.ps
- %% and must be maintained in parallel with it.
+ % This list of operators are used internally by various parts of the Ghostscript PDF interpreter.
+ % Since each operator is a potential security vulnerability, and any operator listed here
+ % is not required once the initislisation is complete and functions are bound, we undefine
+ % the ones that aren't needed at runtime.
+ % This function is only called if DELAYBIND is true. It is a copy of the code at the end of pdf_main.ps
+ % and must be maintained in parallel with it.
[
/.pdfawidthshow /.pdfwidthshow /.currentblackptcomp /.setblackptcomp
/.setfillcolor /.setfillcolorspace /.setstrokecolor /.setstrokecolorspace /.currentrenderingintent /.setrenderingintent
@@ -2411,13 +2416,13 @@ $error /.nosetlocal //false put
(END GLOBAL) VMDEBUG
-%% .savelocalstate is part of Display PostScript (if included). Part of the function of
-%% the .savelocalstate routine is to store the 'initial saved gstate' (savedinitialgstate)
-%% in systemdict. The code in dps1.c, gstate_check_space, disallows writing or creating
-%% gstates in global VM in certain conditions. If we execute setpagedevice before we
-%% reach this point, we must ensure that we do so using /..StartupGlobal so that
-%% the dictionary is defined in global VM, because the gstate contains a pointer to the
-%% device dictionary, and if that is allocated in local VM we will fail the gstate check.
+% .savelocalstate is part of Display PostScript (if included). Part of the function of
+% the .savelocalstate routine is to store the 'initial saved gstate' (savedinitialgstate)
+% in systemdict. The code in dps1.c, gstate_check_space, disallows writing or creating
+% gstates in global VM in certain conditions. If we execute setpagedevice before we
+% reach this point, we must ensure that we do so using /..StartupGlobal so that
+% the dictionary is defined in global VM, because the gstate contains a pointer to the
+% device dictionary, and if that is allocated in local VM we will fail the gstate check.
/.savelocalstate where {
% If we might create new contexts, save away copies of all dictionaries
% referenced from systemdict that are stored in local VM,
@@ -2452,8 +2457,8 @@ currentdict /.shadingtypes .undef
currentdict /.wheredict .undef
currentdict /.renderingintentdict .undef
-%% If we are using DELAYBIND we have to defer the undefinition
-%% until .bindnow.
+% If we are using DELAYBIND we have to defer the undefinition
+% until .bindnow.
DELAYBIND not {
SAFER {
//systemdict /SAFERUndefinePostScriptOperators get exec
@@ -2485,7 +2490,7 @@ DELAYBIND not {
systemdict /.forceundef .undef % ditto
} if
-%% Can't remove this one until the last minute :-)
+% Can't remove this one until the last minute :-)
DELAYBIND not {
systemdict /.undef .undef
} if
--
2.20.1

56
SOURCES/ghostscript-pdf2dsc-regression.patch

@ -0,0 +1,56 @@
From db24f253409d5d085c2760c814c3e1d3fa2dac59 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Tue, 19 Mar 2019 09:25:48 -0700
Subject: Fix lib/pdf2dsc.ps to use documented Ghostscript pdf procedures.

We eliminated GS_PDF_ProcSet and pdfdict, but runpdfbegin, dopdfpages,
and runpdfend are still available.

diff --git a/lib/pdf2dsc.ps b/lib/pdf2dsc.ps
index 4547849c2..d836bf320 100644
--- a/lib/pdf2dsc.ps
+++ b/lib/pdf2dsc.ps
@@ -52,10 +52,7 @@ systemdict /.setsafe known { .setsafe } if
/DSCstring 255 string def
/MediaTypes 10 dict def
- GS_PDF_ProcSet begin
- pdfdict begin
- PDFfile
- pdfopen begin
+ PDFfile runpdfbegin
/FirstPage where { pop } { /FirstPage 1 def } ifelse
/LastPage where { pop } { /LastPage pdfpagecount def } ifelse
@@ -108,13 +105,12 @@ systemdict /.setsafe known { .setsafe } if
(%%BeginProlog\n) puts
(/Page null def\n/Page# 0 def\n/PDFSave null def\n) puts
(/DSCPageCount 0 def\n) puts
- (/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def\n) puts
- (GS_PDF_ProcSet begin\npdfdict begin\n) puts
+ (/DoPDFPage {dup /Page# exch store dup dopdfpages } def\n) puts
(%%EndProlog\n) puts
(%%BeginSetup\n) puts
DSCfile PDFname write==only
( \(r\) file { DELAYSAFER { .setsafe } if } stopped pop\n) puts
- ( pdfopen begin\n) puts
+ ( runpdfbegin\n) puts
( process_trailer_attrs\n) puts
(%%EndSetup\n) puts
@@ -239,13 +235,10 @@ systemdict /.setsafe known { .setsafe } if
DSCfile exch DSCstring cvs writestring
( DoPDFPage\n) puts
} for
- currentdict pdfclose
- end
- end
- end
+ runpdfend
% write trailer
(%%Trailer\n) puts
-(currentdict pdfclose\nend\nend\nend\n) puts
+(runpdfend\n) puts
(%%EOF\n) puts
% close output file and exit
DSCfile closefile

1712
SPECS/ghostscript.spec

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save