import ghostscript-9.27-1.el8
This commit is contained in:
		
							parent
							
								
									f0c566a54f
								
							
						
					
					
						commit
						57818b4e3d
					
				| @ -1 +1 @@ | ||||
| 9d8ddff3382113bf4a1640368350e05652c93613 SOURCES/ghostscript-9.25.tar.xz | ||||
| f926d2cfb418a7c5d92dce0a9843fa01ee62fe2c SOURCES/ghostscript-9.27.tar.xz | ||||
|  | ||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| SOURCES/ghostscript-9.25.tar.xz | ||||
| SOURCES/ghostscript-9.27.tar.xz | ||||
|  | ||||
| @ -1,842 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,289 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,240 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,153 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,322 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,29 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,666 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,32 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,74 +1,8 @@ | ||||
| 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
 | ||||
| index 1a218f4..cffde5c 100644
 | ||||
| --- a/Resource/Init/pdf_base.ps
 | ||||
| +++ b/Resource/Init/pdf_base.ps
 | ||||
| @@ -154,7 +154,7 @@ currentdict /num-chars-dict .undef
 | ||||
| @@ -157,7 +157,7 @@ currentdict /num-chars-dict .undef
 | ||||
|      { | ||||
|        dup ==only () = flush | ||||
|      } ifelse % PDFSTEP | ||||
| @ -78,7 +12,7 @@ index d3c3a5f..5dabe4d 100644 | ||||
|      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
 | ||||
| index e18a7c2..0a3924c 100644
 | ||||
| --- a/Resource/Init/pdf_draw.ps
 | ||||
| +++ b/Resource/Init/pdf_draw.ps
 | ||||
| @@ -501,8 +501,8 @@ end
 | ||||
| @ -92,7 +26,7 @@ index 6a2773a..068ba7c 100644 | ||||
|    ifelse | ||||
|  } bind executeonly def | ||||
|   | ||||
| @@ -1127,7 +1127,7 @@ currentdict end readonly def
 | ||||
| @@ -1142,7 +1142,7 @@ currentdict end readonly def
 | ||||
|            .setglobal | ||||
|            pdfformaterror | ||||
|          } executeonly ifelse | ||||
| @ -101,7 +35,7 @@ index 6a2773a..068ba7c 100644 | ||||
|        { | ||||
|          currentglobal //pdfdict gcheck .setglobal | ||||
|          //pdfdict /.Qqwarning_issued //true .forceput | ||||
| @@ -1135,8 +1135,8 @@ currentdict end readonly def
 | ||||
| @@ -1150,8 +1150,8 @@ currentdict end readonly def
 | ||||
|          pdfformaterror | ||||
|        } executeonly ifelse | ||||
|        end | ||||
| @ -112,7 +46,7 @@ index 6a2773a..068ba7c 100644 | ||||
|    { | ||||
|      (\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
 | ||||
| @@ -1165,14 +1165,14 @@ currentdict end readonly def
 | ||||
|          .setglobal | ||||
|          pdfformaterror | ||||
|        } executeonly ifelse | ||||
| @ -130,7 +64,7 @@ index 6a2773a..068ba7c 100644 | ||||
|   | ||||
|    % restore pdfemptycount | ||||
| diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
 | ||||
| index 8b8fef8..86b1870 100644
 | ||||
| index 9fb85f6..357ba30 100644
 | ||||
| --- a/Resource/Init/pdf_font.ps
 | ||||
| +++ b/Resource/Init/pdf_font.ps
 | ||||
| @@ -677,7 +677,7 @@ currentdict end readonly def
 | ||||
| @ -155,7 +89,7 @@ index 8b8fef8..86b1870 100644 | ||||
|      { | ||||
|        .dstackdepth 1 countdictstack 1 sub | ||||
|        {pop end} for | ||||
| @@ -1225,19 +1225,20 @@ currentdict /eexec_pdf_param_dict .undef
 | ||||
| @@ -1233,19 +1233,20 @@ currentdict /eexec_pdf_param_dict .undef
 | ||||
|                  //pdfdict /.Qqwarning_issued //true .forceput | ||||
|                } executeonly if | ||||
|                Q | ||||
| @ -181,7 +115,7 @@ index 8b8fef8..86b1870 100644 | ||||
|      dup currentdict Encoding .processToUnicode | ||||
|      currentdict end .completefont exch pop | ||||
|  } bind executeonly odef | ||||
| @@ -2022,9 +2023,9 @@ currentdict /CMap_read_dict undef
 | ||||
| @@ -2045,9 +2046,9 @@ currentdict /CMap_read_dict undef
 | ||||
|            (Will continue, but content may be missing.) = flush | ||||
|          } ifelse | ||||
|        } if | ||||
| @ -194,10 +128,10 @@ index 8b8fef8..86b1870 100644 | ||||
|   | ||||
|  /buildCIDType0 {	% <CIDFontType0-font-resource> buildCIDType0 <font> | ||||
| diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
 | ||||
| index e44288e..ecde3d4 100644
 | ||||
| index 5305ea6..a59e63c 100644
 | ||||
| --- a/Resource/Init/pdf_main.ps
 | ||||
| +++ b/Resource/Init/pdf_main.ps
 | ||||
| @@ -2696,15 +2696,15 @@ currentdict /PDF2PS_matrix_key undef
 | ||||
| @@ -2749,15 +2749,15 @@ currentdict /PDF2PS_matrix_key undef
 | ||||
|            .setglobal | ||||
|            pdfformaterror | ||||
|          } executeonly ifelse | ||||
| @ -217,7 +151,7 @@ index e44288e..ecde3d4 100644 | ||||
|    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
 | ||||
| index 285e582..6c1f100 100644
 | ||||
| --- a/Resource/Init/pdf_ops.ps
 | ||||
| +++ b/Resource/Init/pdf_ops.ps
 | ||||
| @@ -186,14 +186,14 @@ currentdict /gput_always_allow .undef
 | ||||
| @ -253,6 +187,3 @@ index c2e7461..12d5a66 100644 | ||||
|    .setSMask | ||||
|    }ifelse | ||||
|   | ||||
| -- 
 | ||||
| 2.20.1 | ||||
| 
 | ||||
|  | ||||
| @ -1,40 +0,0 @@ | ||||
| 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 | ||||
| @ -1,615 +0,0 @@ | ||||
| From 779664d79f0dca77dbdd66b753679bfd12dcbbad Mon Sep 17 00:00:00 2001 | ||||
| From: Chris Liddell <chris.liddell@artifex.com> | ||||
| Date: Mon, 26 Nov 2018 18:01:25 +0000 | ||||
| Subject: [PATCH 1/4] Have gs_cet.ps run from gs_init.ps | ||||
| 
 | ||||
| Previously gs_cet.ps was run on the command line, to set up the interpreter | ||||
| state so our output more closely matches the example output for the QL CET | ||||
| tests. | ||||
| 
 | ||||
| Allow a -dCETMODE command line switch, which will cause gs_init.ps to run the | ||||
| file directly. | ||||
| 
 | ||||
| This works better for gpdl as it means the changes are made in the intial | ||||
| interpreter state, rather than after initialisation is complete. | ||||
| 
 | ||||
| This also means adding a definition of the default procedure for black | ||||
| generation and under color removal (rather it being defined in-line in | ||||
| .setdefaultbgucr | ||||
| 
 | ||||
| Also, add a check so gs_cet.ps only runs once - if we try to run it a second | ||||
| time, we'll just skip over the file, flushing through to the end. | ||||
| ---
 | ||||
|  Resource/Init/gs_cet.ps  | 11 ++++++++++- | ||||
|  Resource/Init/gs_init.ps | 13 ++++++++++++- | ||||
|  2 files changed, 22 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/Resource/Init/gs_cet.ps b/Resource/Init/gs_cet.ps
 | ||||
| index d3e1686..75534bb 100644
 | ||||
| --- a/Resource/Init/gs_cet.ps
 | ||||
| +++ b/Resource/Init/gs_cet.ps
 | ||||
| @@ -1,6 +1,11 @@
 | ||||
|  %!PS | ||||
|  % Set defaults for Ghostscript to match Adobe CPSI behaviour for CET | ||||
|   | ||||
| +systemdict /product get (PhotoPRINT SE 5.0v2) readonly eq
 | ||||
| +{
 | ||||
| +  (%END GS_CET) .skipeof
 | ||||
| +} if
 | ||||
| +
 | ||||
|  % do this in the server level so it is persistent across jobs | ||||
|  //true 0 startjob not { | ||||
|    (*** Warning: CET startup is not in server default) = flush | ||||
| @@ -25,7 +30,9 @@ currentglobal //true setglobal
 | ||||
|   | ||||
|  /UNROLLFORMS true def | ||||
|   | ||||
| -{ } bind dup
 | ||||
| +(%.defaultbgrucrproc) cvn { } bind def
 | ||||
| +
 | ||||
| +(%.defaultbgrucrproc) cvn load dup
 | ||||
|  setblackgeneration | ||||
|  setundercolorremoval | ||||
|  0 array cvx readonly dup dup dup setcolortransfer | ||||
| @@ -109,3 +116,5 @@ userdict /.smoothness currentsmoothness put
 | ||||
|  % end of slightly nasty hack to give consistent cluster results | ||||
|   | ||||
|  //false 0 startjob pop		% re-enter encapsulated mode | ||||
| +
 | ||||
| +%END GS_CET
 | ||||
| diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
 | ||||
| index 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 | ||||
| 
 | ||||
| @ -1,56 +0,0 @@ | ||||
| From ed9fcd95bb01f0768bf273b2526732e381202319 Mon Sep 17 00:00:00 2001 | ||||
| From: Chris Liddell <chris.liddell@artifex.com> | ||||
| Date: Wed, 20 Feb 2019 09:54:28 +0000 | ||||
| Subject: [PATCH 1/2] Bug 700576: Make a transient proc executeonly (in | ||||
|  DefineResource). | ||||
| 
 | ||||
| This prevents access to .forceput | ||||
| 
 | ||||
| Solution originally suggested by cbuissar@redhat.com. | ||||
| ---
 | ||||
|  Resource/Init/gs_res.ps | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
 | ||||
| index d9b3459..b646329 100644
 | ||||
| --- a/Resource/Init/gs_res.ps
 | ||||
| +++ b/Resource/Init/gs_res.ps
 | ||||
| @@ -425,7 +425,7 @@ status {
 | ||||
|                          % so we have to use .forcedef here. | ||||
|                    /.Instances 1 index .forcedef	% Category dict is read-only | ||||
|                  } executeonly if | ||||
| -              }
 | ||||
| +              } executeonly
 | ||||
|                { .LocalInstances dup //.emptydict eq | ||||
|                   { pop 3 dict localinstancedict Category 2 index put | ||||
|                   } | ||||
| -- 
 | ||||
| 2.20.1 | ||||
| 
 | ||||
| 
 | ||||
| From a82601e8f95a2f2147f3b3b9e44ec2b8f3a6be8b Mon Sep 17 00:00:00 2001 | ||||
| From: Chris Liddell <chris.liddell@artifex.com> | ||||
| Date: Fri, 22 Feb 2019 12:28:23 +0000 | ||||
| Subject: [PATCH 2/2] Bug 700576(redux): an extra transient proc needs | ||||
|  executeonly'ed. | ||||
| 
 | ||||
| ---
 | ||||
|  Resource/Init/gs_res.ps | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
 | ||||
| index b646329..8c1f29f 100644
 | ||||
| --- a/Resource/Init/gs_res.ps
 | ||||
| +++ b/Resource/Init/gs_res.ps
 | ||||
| @@ -437,7 +437,7 @@ status {
 | ||||
|                          % Now make the resource value read-only. | ||||
|               0 2 copy get { readonly } .internalstopped pop | ||||
|               dup 4 1 roll put exch pop exch pop | ||||
| -           }
 | ||||
| +           } executeonly
 | ||||
|             { /defineresource cvx /typecheck signaloperror | ||||
|             } | ||||
|          ifelse | ||||
| -- 
 | ||||
| 2.20.1 | ||||
| 
 | ||||
| @ -1,866 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,39 +0,0 @@ | ||||
| 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 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										18
									
								
								SOURCES/ghostscript-cve-2020-16290.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								SOURCES/ghostscript-cve-2020-16290.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| diff --git a/devices/gdev3852.c b/devices/gdev3852.c
 | ||||
| index e21b403..2bee8ec 100644
 | ||||
| --- a/devices/gdev3852.c
 | ||||
| +++ b/devices/gdev3852.c
 | ||||
| @@ -76,6 +76,13 @@ jetp3852_print_page(gx_device_printer *pdev, FILE *prn_stream)
 | ||||
|             {	int lnum; | ||||
|                  int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); | ||||
|                  int num_blank_lines = 0; | ||||
| +
 | ||||
| +                if (line_size > DATA_SIZE) {
 | ||||
| +                  emprintf2(pdev->memory, "invalid resolution and/or width gives line_size = %d, max. is %d\n",
 | ||||
| +                            line_size, DATA_SIZE);
 | ||||
| +                  return_error(gs_error_rangecheck);
 | ||||
| +               }
 | ||||
| +                
 | ||||
|                  for ( lnum = 0; lnum < pdev->height; lnum++ ) | ||||
|                     {	byte *end_data = data + line_size; | ||||
|                          gdev_prn_copy_scan_lines(pdev, lnum, | ||||
							
								
								
									
										257
									
								
								SOURCES/ghostscript-cve-2020-16291.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								SOURCES/ghostscript-cve-2020-16291.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,257 @@ | ||||
| diff --git a/contrib/gdevdj9.c b/contrib/gdevdj9.c
 | ||||
| index eec1c77..a4e8e9c 100644
 | ||||
| --- a/contrib/gdevdj9.c
 | ||||
| +++ b/contrib/gdevdj9.c
 | ||||
| @@ -575,26 +575,55 @@ static int cdj_set_bpp(gx_device *, int, int);
 | ||||
|  static int | ||||
|  hp_colour_open(gx_device * pdev) | ||||
|  { | ||||
| -    int retCode;
 | ||||
| +    int retCode = 0;
 | ||||
| +
 | ||||
| +    /* Change the margins if necessary. */
 | ||||
| +    static const float dj_a4[4] = {
 | ||||
| +        DESKJET_MARGINS_A4
 | ||||
| +    };
 | ||||
| +
 | ||||
| +    static const float dj_letter[4] = {
 | ||||
| +        DESKJET_MARGINS_LETTER
 | ||||
| +    };
 | ||||
| +    const float *m = (float *)0;
 | ||||
|   | ||||
|      cdj970->PageCtr = 0; | ||||
|   | ||||
| +    /* quality setup */
 | ||||
| +    if (cdj970->quality == DRAFT) {
 | ||||
| +        gx_device_set_resolution((gx_device *) pdev, 300.0, 300.0);
 | ||||
| +        cdj970->xscal = 0;
 | ||||
| +        cdj970->yscal = 0;
 | ||||
| +        cdj970->intensities = 2;
 | ||||
| +    } else if (cdj970->quality == NORMAL) {
 | ||||
| +        gx_device_set_resolution((gx_device *) pdev, 600.0, 600.0);
 | ||||
| +        cdj970->xscal = 1;
 | ||||
| +        cdj970->yscal = 1;
 | ||||
| +        /* intensities = 4 from initialization */
 | ||||
| +    } else {                    /* quality == PRESENTATION */
 | ||||
| +        gx_device_set_resolution((gx_device *) pdev, 600.0, 600.0);
 | ||||
| +        cdj970->xscal = 0;
 | ||||
| +        cdj970->yscal = 0;
 | ||||
| +        /* intensities = 4 from initialization */
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    m = (gdev_pcl_paper_size((gx_device *) pdev) ==
 | ||||
| +         PAPER_SIZE_A4 ? dj_a4 : dj_letter);
 | ||||
| +
 | ||||
| +    gx_device_set_margins((gx_device *) pdev, m, true);
 | ||||
| +
 | ||||
|      /* Set up colour params if put_params has not already done so */ | ||||
|      if (pdev->color_info.num_components == 0) { | ||||
| -        int code = cdj_set_bpp(pdev, pdev->color_info.depth,
 | ||||
| +        retCode = cdj_set_bpp(pdev, pdev->color_info.depth,
 | ||||
|                                 pdev->color_info.num_components); | ||||
|   | ||||
| -        if (code < 0)
 | ||||
| -            return code;
 | ||||
| +        if (retCode < 0)
 | ||||
| +            return retCode;
 | ||||
|      } | ||||
|   | ||||
|      retCode = gdev_prn_open(pdev); | ||||
| -    if (retCode < 0)
 | ||||
| -        return (retCode);
 | ||||
| -    else {
 | ||||
| +    if (retCode >= 0) {
 | ||||
|          retCode = gdev_prn_open_printer(pdev, true); | ||||
| -        if (retCode < 0)
 | ||||
| -            return (retCode);
 | ||||
|      } | ||||
|   | ||||
|      return 0; | ||||
| @@ -648,26 +677,25 @@ cdj970_put_params(gx_device * pdev, gs_param_list * plist)
 | ||||
|      int bpp = 0; | ||||
|      int code = 0; | ||||
|   | ||||
| -    code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
 | ||||
| -    code = cdj_put_param_int(plist, "Quality", &quality, 0, 2, code);
 | ||||
| -    code = cdj_put_param_int(plist, "Papertype", &papertype, 0, 4, code);
 | ||||
| -    code = cdj_put_param_int(plist, "Duplex", &duplex, 0, 2, code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "MasterGamma", &mastergamma, 0.1, 9.0,
 | ||||
| -                            code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "GammaValC", &gammavalc, 0.0, 9.0, code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "GammaValM", &gammavalm, 0.0, 9.0, code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "GammaValY", &gammavaly, 0.0, 9.0, code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "GammaValK", &gammavalk, 0.0, 9.0, code);
 | ||||
| -    code =
 | ||||
| -        cdj_put_param_float(plist, "BlackCorrect", &blackcorrect, 0.0, 9.0,
 | ||||
| -                            code);
 | ||||
| -
 | ||||
| -    if (code < 0)
 | ||||
| +    if ((code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_int(plist, "Quality", &quality, 0, 2, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_int(plist, "Papertype", &papertype, 0, 4, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_int(plist, "Duplex", &duplex, 0, 2, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "MasterGamma", &mastergamma, 0.1, 9.0, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "GammaValC", &gammavalc, 0.0, 9.0, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "GammaValM", &gammavalm, 0.0, 9.0, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "GammaValY", &gammavaly, 0.0, 9.0, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "GammaValK", &gammavalk, 0.0, 9.0, code)) < 0)
 | ||||
| +        return code;
 | ||||
| +    if ((code = cdj_put_param_float(plist, "BlackCorrect", &blackcorrect, 0.0, 9.0, code)) < 0)
 | ||||
|          return code; | ||||
|   | ||||
|      code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0); | ||||
| @@ -676,6 +704,12 @@ cdj970_put_params(gx_device * pdev, gs_param_list * plist)
 | ||||
|          return code; | ||||
|   | ||||
|      cdj970->quality = quality; | ||||
| +    if (cdj970->quality != quality) {
 | ||||
| +        if (pdev->is_open)
 | ||||
| +            gs_closedevice(pdev);      /* quality can change resolution, force re-open */
 | ||||
| +        cdj970->quality = quality;
 | ||||
| +    }
 | ||||
| +
 | ||||
|      cdj970->papertype = papertype; | ||||
|      cdj970->duplex = duplex; | ||||
|      cdj970->mastergamma = mastergamma; | ||||
| @@ -685,7 +719,7 @@ cdj970_put_params(gx_device * pdev, gs_param_list * plist)
 | ||||
|      cdj970->gammavalk = gammavalk; | ||||
|      cdj970->blackcorrect = blackcorrect; | ||||
|   | ||||
| -    return 0;
 | ||||
| +    return code;
 | ||||
|  } | ||||
|   | ||||
|  /**********************************************************************************/ | ||||
| @@ -784,47 +818,6 @@ cdj970_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
 | ||||
|      fputs("\033*rC\f\033&l-2H", prn_stream);    /* End Graphics, Reset */ | ||||
|  } | ||||
|   | ||||
| -/* cdj970_one_time_initialisation:
 | ||||
| -----------------------------------------------------------------------------------*/
 | ||||
| -static void
 | ||||
| -cdj970_one_time_initialisation(gx_device_printer * pdev)
 | ||||
| -{
 | ||||
| -    /* Change the margins if necessary. */
 | ||||
| -    static const float dj_a4[4] = {
 | ||||
| -        DESKJET_MARGINS_A4
 | ||||
| -    };
 | ||||
| -
 | ||||
| -    static const float dj_letter[4] = {
 | ||||
| -        DESKJET_MARGINS_LETTER
 | ||||
| -    };
 | ||||
| -    const float *m = (float *)0;
 | ||||
| -
 | ||||
| -    /* quality setup */
 | ||||
| -    if (cdj970->quality == DRAFT) {
 | ||||
| -        gx_device_set_resolution((gx_device *) pdev, 300.0, 300.0);
 | ||||
| -        cdj970->xscal = 0;
 | ||||
| -        cdj970->yscal = 0;
 | ||||
| -        cdj970->intensities = 2;
 | ||||
| -    } else if (cdj970->quality == NORMAL) {
 | ||||
| -        gx_device_set_resolution((gx_device *) pdev, 600.0, 600.0);
 | ||||
| -        cdj970->xscal = 1;
 | ||||
| -        cdj970->yscal = 1;
 | ||||
| -        /* intensities = 4 from initialization */
 | ||||
| -    } else {                    /* quality == PRESENTATION */
 | ||||
| -        gx_device_set_resolution((gx_device *) pdev, 600.0, 600.0);
 | ||||
| -        cdj970->xscal = 0;
 | ||||
| -        cdj970->yscal = 0;
 | ||||
| -        /* intensities = 4 from initialization */
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    m = (gdev_pcl_paper_size((gx_device *) pdev) ==
 | ||||
| -         PAPER_SIZE_A4 ? dj_a4 : dj_letter);
 | ||||
| -
 | ||||
| -    gx_device_set_margins((gx_device *) pdev, m, true);
 | ||||
| -
 | ||||
| -    cdj970_write_header((gx_device *) pdev, pdev->file);
 | ||||
| -}
 | ||||
| -
 | ||||
|  /* cdj970_print_page: Here comes the hp970 output routine | ||||
|  ----------------------------------------------------------------------------------*/ | ||||
|  static int | ||||
| @@ -837,7 +830,7 @@ cdj970_print_page(gx_device_printer * pdev, FILE * prn_stream)
 | ||||
|      Gamma gamma; | ||||
|   | ||||
|      if (cdj970->PageCtr == 0 && cdj970->ptype == DJ970C) { | ||||
| -        cdj970_one_time_initialisation(pdev);
 | ||||
| +        cdj970_write_header((gx_device *)pdev, prn_stream);
 | ||||
|      } | ||||
|   | ||||
|      /* make a local writable copy of the Gamma tables */ | ||||
| @@ -2280,6 +2273,11 @@ cdj_set_bpp(gx_device * pdev, int bpp, int ccomps)
 | ||||
|          ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0); | ||||
|      } | ||||
|   | ||||
| +    if (ci->depth != ((bpp > 1) && (bpp < 8) ? 8 : bpp)) {
 | ||||
| +        if (pdev->is_open)
 | ||||
| +            gs_closedevice(pdev);  /* depth changed, make sure we re-open */
 | ||||
| +    }
 | ||||
| +
 | ||||
|      ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp); | ||||
|   | ||||
|      return (0); | ||||
| @@ -2598,16 +2596,15 @@ cdj_put_param_bpp(gx_device * pdev,
 | ||||
|                    gs_param_list * plist, | ||||
|                    int new_bpp, int real_bpp, int ccomps) | ||||
|  { | ||||
| -    if (new_bpp == 0 && ccomps == 0)
 | ||||
| -        return gdev_prn_put_params(pdev, plist);
 | ||||
| -    else {
 | ||||
| -        gx_device_color_info save_info;
 | ||||
| -        int save_bpp;
 | ||||
| -        int code;
 | ||||
| -
 | ||||
| -        save_info = pdev->color_info;
 | ||||
| -        save_bpp = save_info.depth;
 | ||||
| +    int code = 0;
 | ||||
| +    int save_bpp;
 | ||||
| +    gx_device_color_info save_info;
 | ||||
| +    save_info = pdev->color_info;
 | ||||
| +    save_bpp = save_info.depth;
 | ||||
|   | ||||
| +    if (new_bpp == 0 && ccomps == 0) {
 | ||||
| +       code = gdev_prn_put_params(pdev, plist);
 | ||||
| +    } else {
 | ||||
|          if (save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk) | ||||
|              save_bpp = 3; | ||||
|   | ||||
| @@ -2631,12 +2628,22 @@ cdj_put_param_bpp(gx_device * pdev,
 | ||||
|          if ((cdj970->color_info.depth != save_bpp | ||||
|               || (ccomps != 0 && ccomps != save_ccomps)) | ||||
|              && pdev->is_open) | ||||
| -            return (gs_closedevice(pdev));
 | ||||
| +            gs_closedevice(pdev);
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    /* check for valid resolutions */
 | ||||
| +    if (pdev->HWResolution[0] != pdev->HWResolution[1] ||
 | ||||
| +        (pdev->HWResolution[0] != 300.0 && pdev->HWResolution[0] != 600.0) ) {
 | ||||
| +        param_signal_error(plist, "HWResolution", gs_error_rangecheck);
 | ||||
| +        emprintf1(pdev->memory, "\ncdj970: Invalid resolution: '%f'. Only 300 or 600 supported.\n\n",
 | ||||
| +                  pdev->HWResolution[0]);
 | ||||
| +        cdj_set_bpp(pdev, save_bpp, save_ccomps);
 | ||||
| +        return gs_error_rangecheck;
 | ||||
| +    }
 | ||||
| +    return code;
 | ||||
|   | ||||
| -        return (0);
 | ||||
|   | ||||
|  #undef save_ccomps | ||||
| -    }
 | ||||
|  } | ||||
|   | ||||
|  /* cdj970_write_header: | ||||
							
								
								
									
										13
									
								
								SOURCES/ghostscript-cve-2020-16293.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								SOURCES/ghostscript-cve-2020-16293.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| diff --git a/base/gxblend.c b/base/gxblend.c
 | ||||
| index 7c3d55b..55215d6 100644
 | ||||
| --- a/base/gxblend.c
 | ||||
| +++ b/base/gxblend.c
 | ||||
| @@ -2174,7 +2174,7 @@ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
 | ||||
|               overprint == 0) { | ||||
|               /* Additive vs Subtractive makes no difference in normal blend mode with no spots */ | ||||
|          if (tos_isolated) { | ||||
| -            if (has_mask || maskbuf) {/* 7% */
 | ||||
| +            if (has_mask && maskbuf) {/* 7% */
 | ||||
|                  /* AirPrint test case hits this */ | ||||
|                  if (maskbuf && maskbuf->rect.p.x <= x0 && maskbuf->rect.p.y <= y0 && | ||||
|                      maskbuf->rect.q.x >= x1 && maskbuf->rect.q.y >= y1) | ||||
							
								
								
									
										13
									
								
								SOURCES/ghostscript-cve-2020-16295.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								SOURCES/ghostscript-cve-2020-16295.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| diff --git a/devices/gdevclj.c b/devices/gdevclj.c
 | ||||
| index bed13bc..fe17ece 100644
 | ||||
| --- a/devices/gdevclj.c
 | ||||
| +++ b/devices/gdevclj.c
 | ||||
| @@ -254,7 +254,7 @@ clj_media_size(float mediasize[2], gs_param_list *plist)
 | ||||
|      gs_param_int_array hwsize; | ||||
|      int have_pagesize = 0; | ||||
|   | ||||
| -    if ( (param_read_float_array(plist, "HWResolution", &fres) == 0) &&
 | ||||
| +    if ( param_read_float_array(plist, "HWResolution", &fres) != 0 ||
 | ||||
|            !is_supported_resolution(fres.data) ) | ||||
|          return_error(gs_error_rangecheck); | ||||
|   | ||||
							
								
								
									
										58
									
								
								SOURCES/ghostscript-cve-2020-16299.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								SOURCES/ghostscript-cve-2020-16299.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| diff --git a/contrib/japanese/gdev10v.c b/contrib/japanese/gdev10v.c
 | ||||
| index 5c8b7fb..53da0ec 100644
 | ||||
| --- a/contrib/japanese/gdev10v.c
 | ||||
| +++ b/contrib/japanese/gdev10v.c
 | ||||
| @@ -73,8 +73,20 @@ gx_device_procs prn_bj10v_procs =
 | ||||
|    prn_matrix_procs(gdev_prn_open, bj10v_get_initial_matrix, | ||||
|      gdev_prn_output_page, gdev_prn_close); | ||||
|  #endif | ||||
| +
 | ||||
| +static int
 | ||||
| +bj10v_open(gx_device * pdev)
 | ||||
| +{
 | ||||
| +    if (pdev->HWResolution[0] < 180 ||
 | ||||
| +        pdev->HWResolution[1] < 180)
 | ||||
| +    {
 | ||||
| +        emprintf(pdev->memory, "device requires a resolution of at least 180dpi\n");
 | ||||
| +        return_error(gs_error_rangecheck);
 | ||||
| +    }
 | ||||
| +    return gdev_prn_open(pdev);
 | ||||
| +}
 | ||||
|  gx_device_procs prn_bj10v_procs = | ||||
| -  prn_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close);
 | ||||
| +  prn_procs(bj10v_open, gdev_prn_output_page, gdev_prn_close);
 | ||||
|   | ||||
|  gx_device_printer gs_bj10v_device = | ||||
|    prn_device(prn_bj10v_procs, "bj10v", | ||||
| diff --git a/contrib/japanese/gdevalps.c b/contrib/japanese/gdevalps.c
 | ||||
| index f29aeb1..d4de619 100644
 | ||||
| --- a/contrib/japanese/gdevalps.c
 | ||||
| +++ b/contrib/japanese/gdevalps.c
 | ||||
| @@ -155,13 +155,20 @@ static const char end_md[] = {
 | ||||
|  static int | ||||
|  md_open(gx_device *pdev) | ||||
|  { | ||||
| -        static const float md_margins[4] =
 | ||||
| -         {	MD_SIDE_MARGIN, MD_BOTTOM_MARGIN,
 | ||||
| -                MD_SIDE_MARGIN, MD_TOP_MARGIN
 | ||||
| -         };
 | ||||
| -
 | ||||
| -        gx_device_set_margins(pdev, md_margins, true);
 | ||||
| -        return gdev_prn_open(pdev);
 | ||||
| +  static const float md_margins[4] =
 | ||||
| +    {
 | ||||
| +        MD_SIDE_MARGIN, MD_BOTTOM_MARGIN,
 | ||||
| +        MD_SIDE_MARGIN, MD_TOP_MARGIN
 | ||||
| +    };
 | ||||
| +
 | ||||
| +    if (pdev->HWResolution[0] != 600)
 | ||||
| +    {
 | ||||
| +        emprintf(pdev->memory, "device must have an X resolution of 600dpi\n");
 | ||||
| +        return_error(gs_error_rangecheck);
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    gx_device_set_margins(pdev, md_margins, true);
 | ||||
| +    return gdev_prn_open(pdev);
 | ||||
|  } | ||||
|   | ||||
|  /* MD5000 monochrome mode entrance. */ | ||||
							
								
								
									
										228
									
								
								SOURCES/ghostscript-cve-2020-16302.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								SOURCES/ghostscript-cve-2020-16302.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,228 @@ | ||||
| diff --git a/devices/gdev3852.c b/devices/gdev3852.c
 | ||||
| index 2bee8ec..9d99068 100644
 | ||||
| --- a/devices/gdev3852.c
 | ||||
| +++ b/devices/gdev3852.c
 | ||||
| @@ -62,116 +62,117 @@ jetp3852_print_page(gx_device_printer *pdev, FILE *prn_stream)
 | ||||
|  #define DATA_SIZE (LINE_SIZE * 8) | ||||
|   | ||||
|     unsigned int cnt_2prn; | ||||
| -        unsigned int count,tempcnt;
 | ||||
| -        unsigned char vtp,cntc1,cntc2;
 | ||||
| -        int line_size_color_plane;
 | ||||
| -
 | ||||
| -        byte data[DATA_SIZE];
 | ||||
| -        byte plane_data[LINE_SIZE * 3];
 | ||||
| -
 | ||||
| -        /* Set initial condition for printer */
 | ||||
| -        fputs("\033@",prn_stream);
 | ||||
| -
 | ||||
| -        /* Send each scan line in turn */
 | ||||
| -           {	int lnum;
 | ||||
| -                int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
 | ||||
| -                int num_blank_lines = 0;
 | ||||
| -
 | ||||
| -                if (line_size > DATA_SIZE) {
 | ||||
| -                  emprintf2(pdev->memory, "invalid resolution and/or width gives line_size = %d, max. is %d\n",
 | ||||
| -                            line_size, DATA_SIZE);
 | ||||
| -                  return_error(gs_error_rangecheck);
 | ||||
| -               }
 | ||||
| -                
 | ||||
| -                for ( lnum = 0; lnum < pdev->height; lnum++ )
 | ||||
| -                   {	byte *end_data = data + line_size;
 | ||||
| -                        gdev_prn_copy_scan_lines(pdev, lnum,
 | ||||
| -                                                 (byte *)data, line_size);
 | ||||
| -                        /* Remove trailing 0s. */
 | ||||
| -                        while ( end_data > data && end_data[-1] == 0 )
 | ||||
| -                                end_data--;
 | ||||
| -                        if ( end_data == data )
 | ||||
| -                           {	/* Blank line */
 | ||||
| -                                num_blank_lines++;
 | ||||
| -                           }
 | ||||
| -                        else
 | ||||
| -                           {	int i;
 | ||||
| -                                byte *odp;
 | ||||
| -                                byte *row;
 | ||||
| -
 | ||||
| -                                /* Pad with 0s to fill out the last */
 | ||||
| -                                /* block of 8 bytes. */
 | ||||
| -                                memset(end_data, 0, 7);
 | ||||
| -
 | ||||
| -                                /* Transpose the data to get pixel planes. */
 | ||||
| -                                for ( i = 0, odp = plane_data; i < DATA_SIZE;
 | ||||
| -                                      i += 8, odp++
 | ||||
| -                                    )
 | ||||
| -                                 { /* The following is for 16-bit machines */
 | ||||
| +   unsigned int count,tempcnt;
 | ||||
| +   unsigned char vtp,cntc1,cntc2;
 | ||||
| +   int line_size_color_plane;
 | ||||
| +
 | ||||
| +   byte data[DATA_SIZE];
 | ||||
| +   byte plane_data[LINE_SIZE * 3];
 | ||||
| +
 | ||||
| +   /* Initialise data to zeros, otherwise later on, uninitialised bytes in
 | ||||
| +   dp[] can be greater than 7, which breaks spr8[dp[]]. */
 | ||||
| +   memset(data, 0x00, DATA_SIZE);
 | ||||
| +
 | ||||
| +
 | ||||
| +   /* Set initial condition for printer */
 | ||||
| +   fputs("\033@",prn_stream);
 | ||||
| +
 | ||||
| +   /* Send each scan line in turn */
 | ||||
| +   {	int lnum;
 | ||||
| +        int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
 | ||||
| +        int num_blank_lines = 0;
 | ||||
| +
 | ||||
| +        if (line_size > DATA_SIZE) {
 | ||||
| +          emprintf2(pdev->memory, "invalid resolution and/or width gives line_size = %d, max. is %d\n",
 | ||||
| +                    line_size, DATA_SIZE);
 | ||||
| +          return_error(gs_error_rangecheck);
 | ||||
| +       }
 | ||||
| +
 | ||||
| +        for ( lnum = 0; lnum < pdev->height; lnum++ )
 | ||||
| +           {	byte *end_data = data + line_size;
 | ||||
| +                gdev_prn_copy_scan_lines(pdev, lnum,
 | ||||
| +                                         (byte *)data, line_size);
 | ||||
| +                /* Remove trailing 0s. */
 | ||||
| +                while ( end_data > data && end_data[-1] == 0 )
 | ||||
| +                        end_data--;
 | ||||
| +                if ( end_data == data )
 | ||||
| +                   {	/* Blank line */
 | ||||
| +                        num_blank_lines++;
 | ||||
| +                   }
 | ||||
| +                else
 | ||||
| +                   {	int i;
 | ||||
| +                        byte *odp;
 | ||||
| +                        byte *row;
 | ||||
| +
 | ||||
| +                        /* Transpose the data to get pixel planes. */
 | ||||
| +                        for ( i = 0, odp = plane_data; i < DATA_SIZE;
 | ||||
| +                              i += 8, odp++
 | ||||
| +                            )
 | ||||
| +                        { /* The following is for 16-bit machines */
 | ||||
|  #define spread3(c)\ | ||||
|   { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L } | ||||
| -                                   static ulong spr40[8] = spread3(0x40);
 | ||||
| -                                   static ulong spr8[8] = spread3(8);
 | ||||
| -                                   static ulong spr2[8] = spread3(2);
 | ||||
| -                                   register byte *dp = data + i;
 | ||||
| -                                   register ulong pword =
 | ||||
| -                                     (spr40[dp[0]] << 1) +
 | ||||
| -                                     (spr40[dp[1]]) +
 | ||||
| -                                     (spr40[dp[2]] >> 1) +
 | ||||
| -                                     (spr8[dp[3]] << 1) +
 | ||||
| -                                     (spr8[dp[4]]) +
 | ||||
| -                                     (spr8[dp[5]] >> 1) +
 | ||||
| -                                     (spr2[dp[6]]) +
 | ||||
| -                                     (spr2[dp[7]] >> 1);
 | ||||
| -                                   odp[0] = (byte)(pword >> 16);
 | ||||
| -                                   odp[LINE_SIZE] = (byte)(pword >> 8);
 | ||||
| -                                   odp[LINE_SIZE*2] = (byte)(pword);
 | ||||
| -                                 }
 | ||||
| -                                /* Skip blank lines if any */
 | ||||
| -                                if ( num_blank_lines > 0 )
 | ||||
| -                                   {
 | ||||
| -                                        /* Do "dot skips" */
 | ||||
| -                                        while(num_blank_lines > 255)
 | ||||
| -                                          {
 | ||||
| -                                          fputs("\033e\377",prn_stream);
 | ||||
| -                                          num_blank_lines -= 255;
 | ||||
| -                                          }
 | ||||
| -                                        vtp = num_blank_lines;
 | ||||
| -                                        fprintf(prn_stream,"\033e%c",vtp);
 | ||||
| -                                        num_blank_lines = 0;
 | ||||
| -                                   }
 | ||||
| -
 | ||||
| -                                /* Transfer raster graphics in the order R, G, B. */
 | ||||
| -                                /* Apparently it is stored in B, G, R */
 | ||||
| -                                /* Calculate the amount of data to send by what */
 | ||||
| -                                /* Ghostscript tells us the scan line_size in (bytes) */
 | ||||
| -
 | ||||
| -                                count = line_size / 3;
 | ||||
| -                                line_size_color_plane = count / 3;
 | ||||
| -                           cnt_2prn = line_size_color_plane * 3 + 5;
 | ||||
| -                                tempcnt = cnt_2prn;
 | ||||
| -                                cntc1 = (tempcnt & 0xFF00) >> 8;
 | ||||
| -                                cntc2 = (tempcnt & 0x00FF);
 | ||||
| -                                fprintf(prn_stream, "\033[O%c%c\200\037",cntc2,cntc1);
 | ||||
| -                                fputc('\000',prn_stream);
 | ||||
| +                           static ulong spr40[8] = spread3(0x40);
 | ||||
| +                           static ulong spr8[8] = spread3(8);
 | ||||
| +                           static ulong spr2[8] = spread3(2);
 | ||||
| +                           register byte *dp = data + i;
 | ||||
| +                           register ulong pword =
 | ||||
| +                             (spr40[dp[0]] << 1) +
 | ||||
| +                             (spr40[dp[1]]) +
 | ||||
| +                             (spr40[dp[2]] >> 1) +
 | ||||
| +                             (spr8[dp[3]] << 1) +
 | ||||
| +                             (spr8[dp[4]]) +
 | ||||
| +                             (spr8[dp[5]] >> 1) +
 | ||||
| +                             (spr2[dp[6]]) +
 | ||||
| +                             (spr2[dp[7]] >> 1);
 | ||||
| +                           odp[0] = (byte)(pword >> 16);
 | ||||
| +                           odp[LINE_SIZE] = (byte)(pword >> 8);
 | ||||
| +                           odp[LINE_SIZE*2] = (byte)(pword);
 | ||||
| +                        }
 | ||||
| +                        /* Skip blank lines if any */
 | ||||
| +                        if ( num_blank_lines > 0 )
 | ||||
| +                           {
 | ||||
| +                                /* Do "dot skips" */
 | ||||
| +                                while(num_blank_lines > 255)
 | ||||
| +                                  {
 | ||||
| +                                  fputs("\033e\377",prn_stream);
 | ||||
| +                                  num_blank_lines -= 255;
 | ||||
| +                                  }
 | ||||
| +                                vtp = num_blank_lines;
 | ||||
| +                                fprintf(prn_stream,"\033e%c",vtp);
 | ||||
| +                                num_blank_lines = 0;
 | ||||
| +                           }
 | ||||
| +
 | ||||
| +                        /* Transfer raster graphics in the order R, G, B. */
 | ||||
| +                        /* Apparently it is stored in B, G, R */
 | ||||
| +                        /* Calculate the amount of data to send by what */
 | ||||
| +                        /* Ghostscript tells us the scan line_size in (bytes) */
 | ||||
| +
 | ||||
| +                        count = line_size / 3;
 | ||||
| +                        line_size_color_plane = count / 3;
 | ||||
| +                        cnt_2prn = line_size_color_plane * 3 + 5;
 | ||||
| +                        tempcnt = cnt_2prn;
 | ||||
| +                        cntc1 = (tempcnt & 0xFF00) >> 8;
 | ||||
| +                        cntc2 = (tempcnt & 0x00FF);
 | ||||
| +                        fprintf(prn_stream, "\033[O%c%c\200\037",cntc2,cntc1);
 | ||||
| +                        fputc('\000',prn_stream);
 | ||||
|                          fputs("\124\124",prn_stream); | ||||
|   | ||||
| -                                for ( row = plane_data + LINE_SIZE * 2, i = 0;
 | ||||
| -                                      i < 3; row -= LINE_SIZE, i++ )
 | ||||
| -                                {	int jj;
 | ||||
| -                                   byte ctemp;
 | ||||
| -                                   odp = row;
 | ||||
| -                                        /* Complement bytes */
 | ||||
| -                                        for (jj=0; jj< line_size_color_plane; jj++)
 | ||||
| -                                          { ctemp = *odp;
 | ||||
| -                                            *odp++ = ~ctemp;
 | ||||
| -                                                 }
 | ||||
| -                                        fwrite(row, sizeof(byte),
 | ||||
| -                                            line_size_color_plane, prn_stream);
 | ||||
| -                                        }
 | ||||
| -                           }
 | ||||
| -                   }
 | ||||
| -           }
 | ||||
| +                        for ( row = plane_data + LINE_SIZE * 2, i = 0;
 | ||||
| +                              i < 3; row -= LINE_SIZE, i++ )
 | ||||
| +                        {  int jj;
 | ||||
| +                           byte ctemp;
 | ||||
| +                           odp = row;
 | ||||
| +                              /* Complement bytes */
 | ||||
| +                              for (jj=0; jj< line_size_color_plane; jj++)
 | ||||
| +                              { ctemp = *odp;
 | ||||
| +                                *odp++ = ~ctemp;
 | ||||
| +                              }
 | ||||
| +                           fwrite(row, sizeof(byte),
 | ||||
| +                           line_size_color_plane, prn_stream);
 | ||||
| +                        }
 | ||||
| +                  }
 | ||||
| +            }
 | ||||
| +   }
 | ||||
|   | ||||
|          /* eject page */ | ||||
|          fputs("\014", prn_stream); | ||||
							
								
								
									
										77
									
								
								SOURCES/ghostscript-cve-2020-16304.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								SOURCES/ghostscript-cve-2020-16304.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| diff --git a/base/gxicolor.c b/base/gxicolor.c
 | ||||
| index 34cfaa4..585bd81 100644
 | ||||
| --- a/base/gxicolor.c
 | ||||
| +++ b/base/gxicolor.c
 | ||||
| @@ -644,16 +644,16 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
 | ||||
|                                      *(devc_contone_gray+1) = *psrc_temp; | ||||
|                              } | ||||
|                          } else { | ||||
| -                        /* Mono case, forward */
 | ||||
| -                        psrc_temp = psrc_cm;
 | ||||
| -                        for (k=0; k<src_size; k++) {
 | ||||
| -                            dda_next(dda_ht);
 | ||||
| -                            xn = fixed2int_var_rounded(dda_current(dda_ht));
 | ||||
| -                            while (xr < xn) {
 | ||||
| -                                *devc_contone_gray++ = *psrc_temp;
 | ||||
| -                                xr++;
 | ||||
| -                            }           /* at loop exit xn will be >= xr */
 | ||||
| -                            psrc_temp++;
 | ||||
| +                            /* Mono case, forward */
 | ||||
| +                            psrc_temp = psrc_cm;
 | ||||
| +                            for (k=0; k<src_size; k++) {
 | ||||
| +                                dda_next(dda_ht);
 | ||||
| +                                xn = fixed2int_var_rounded(dda_current(dda_ht));
 | ||||
| +                                while (xr < xn) {
 | ||||
| +                                    *devc_contone_gray++ = *psrc_temp;
 | ||||
| +                                    xr++;
 | ||||
| +                                }           /* at loop exit xn will be >= xr */
 | ||||
| +                                psrc_temp++;
 | ||||
|                              } | ||||
|                          } | ||||
|                      } else { | ||||
| @@ -668,7 +668,7 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
 | ||||
|                                  xr--; | ||||
|                              }           /* at loop exit xn will be >= xr */ | ||||
|                              psrc_temp++; | ||||
| -                            }
 | ||||
| +                        }
 | ||||
|                      } | ||||
|                      break; | ||||
|                  /* Monochrome landscape */ | ||||
| @@ -811,10 +811,9 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
 | ||||
|                              dda_next(dda_ht); | ||||
|                              xn = fixed2int_var_rounded(dda_current(dda_ht)); | ||||
|                              while (xr > xn) { | ||||
| -                                for (j = 0; j < spp_out; j++) {
 | ||||
| +                                for (j = 0; j < spp_out; j++)
 | ||||
|                                      *(devc_contone[j] + position) = (psrc_plane[j])[i]; | ||||
| -                                    position -= LAND_BITS;
 | ||||
| -                                }
 | ||||
| +                                position -= LAND_BITS;
 | ||||
|                                  xr--; | ||||
|                              }           /* at loop exit xn will be <= xr */ | ||||
|                              i++; | ||||
| @@ -825,9 +824,8 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
 | ||||
|                             and 2x scaling which we will run into in 300 and | ||||
|                             600dpi devices and content */ | ||||
|                          /* Apply initial offset */ | ||||
| -                        for (k = 0; k < spp_out; k++) {
 | ||||
| +                        for (k = 0; k < spp_out; k++)
 | ||||
|                              devc_contone[k] = devc_contone[k] + position; | ||||
| -                        }
 | ||||
|                          if (src_size == dest_height) { | ||||
|                              for (k = 0; k < data_length; k++) { | ||||
|                                  /* Is it better to unwind this?  We know it is 4 */ | ||||
| @@ -853,10 +851,9 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
 | ||||
|                                  dda_next(dda_ht); | ||||
|                                  xn = fixed2int_var_rounded(dda_current(dda_ht)); | ||||
|                                  while (xr > xn) { | ||||
| -                                    for (j = 0; j < spp_out; j++) {
 | ||||
| +                                    for (j = 0; j < spp_out; j++)
 | ||||
|                                          *(devc_contone[j] + position) = (psrc_plane[j])[i]; | ||||
| -                                        position -= LAND_BITS;
 | ||||
| -                                    }
 | ||||
| +                                    position -= LAND_BITS;
 | ||||
|                                      xr--; | ||||
|                                  }           /* at loop exit xn will be <= xr */ | ||||
|                                  i++; | ||||
							
								
								
									
										20
									
								
								SOURCES/ghostscript-cve-2020-16306.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								SOURCES/ghostscript-cve-2020-16306.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c
 | ||||
| index 6a50a4a..471fcb5 100644
 | ||||
| --- a/devices/gdevtsep.c
 | ||||
| +++ b/devices/gdevtsep.c
 | ||||
| @@ -2332,6 +2332,7 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
 | ||||
|                  "\nUse of the %%d format is required to output more than one page to tiffsep.\n" | ||||
|                  "See doc/Devices.htm#TIFF for details.\n\n"); | ||||
|         code = gs_note_error(gs_error_ioerror); | ||||
| +       goto done;
 | ||||
|      } | ||||
|      /* Write the page directory for the CMYK equivalent file. */ | ||||
|      if (!tfdev->comp_file) { | ||||
| @@ -2685,6 +2686,7 @@ tiffsep1_print_page(gx_device_printer * pdev, FILE * file)
 | ||||
|                  "\nUse of the %%d format is required to output more than one page to tiffsep1.\n" | ||||
|                  "See doc/Devices.htm#TIFF for details.\n\n"); | ||||
|         code = gs_note_error(gs_error_ioerror); | ||||
| +       goto done;
 | ||||
|      } | ||||
|      /* If the output file is on disk and the name contains a page #, */ | ||||
|      /* then delete the previous file. */ | ||||
							
								
								
									
										205
									
								
								SOURCES/ghostscript-cve-2020-16307.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								SOURCES/ghostscript-cve-2020-16307.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | ||||
| diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c
 | ||||
| index b958027..7f02608 100644
 | ||||
| --- a/devices/vector/gdevtxtw.c
 | ||||
| +++ b/devices/vector/gdevtxtw.c
 | ||||
| @@ -1693,97 +1693,100 @@ static int get_unicode(textw_text_enum_t *penum, gs_font *font, gs_glyph glyph,
 | ||||
|   | ||||
|      length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0); | ||||
|      if (length == 0) { | ||||
| -        code = font->procs.glyph_name(font, glyph, &gnstr);
 | ||||
| -        if (code >= 0 && gnstr.size == 7) {
 | ||||
| -            if (!memcmp(gnstr.data, "uni", 3)) {
 | ||||
| -                static const char *hexdigits = "0123456789ABCDEF";
 | ||||
| -                char *d0 = strchr(hexdigits, gnstr.data[3]);
 | ||||
| -                char *d1 = strchr(hexdigits, gnstr.data[4]);
 | ||||
| -                char *d2 = strchr(hexdigits, gnstr.data[5]);
 | ||||
| -                char *d3 = strchr(hexdigits, gnstr.data[6]);
 | ||||
| -
 | ||||
| -                if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
 | ||||
| -                    *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits);
 | ||||
| -                    return 1;
 | ||||
| -                }
 | ||||
| -            }
 | ||||
| -        }
 | ||||
| -        if (length == 0) {
 | ||||
| -            single_glyph_list_t *sentry = (single_glyph_list_t *)&SingleGlyphList;
 | ||||
| -            double_glyph_list_t *dentry = (double_glyph_list_t *)&DoubleGlyphList;
 | ||||
| -            treble_glyph_list_t *tentry = (treble_glyph_list_t *)&TrebleGlyphList;
 | ||||
| -            quad_glyph_list_t *qentry = (quad_glyph_list_t *)&QuadGlyphList;
 | ||||
| -
 | ||||
| -            /* Search glyph to single Unicode value table */
 | ||||
| -            while (sentry->Glyph != 0) {
 | ||||
| -                if (sentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| -                    sentry++;
 | ||||
| -                    continue;
 | ||||
| -                }
 | ||||
| -                if (sentry->Glyph[0] > gnstr.data[0]){
 | ||||
| -                    break;
 | ||||
| -                }
 | ||||
| -                if (strlen(sentry->Glyph) == gnstr.size) {
 | ||||
| -                    if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) {
 | ||||
| -                        *Buffer = sentry->Unicode;
 | ||||
| +        if (glyph != GS_NO_GLYPH) {
 | ||||
| +            code = font->procs.glyph_name(font, glyph, &gnstr);
 | ||||
| +            if (code >= 0 && gnstr.size == 7) {
 | ||||
| +                if (!memcmp(gnstr.data, "uni", 3)) {
 | ||||
| +                    static const char *hexdigits = "0123456789ABCDEF";
 | ||||
| +                    char *d0 = strchr(hexdigits, gnstr.data[3]);
 | ||||
| +                    char *d1 = strchr(hexdigits, gnstr.data[4]);
 | ||||
| +                    char *d2 = strchr(hexdigits, gnstr.data[5]);
 | ||||
| +                    char *d3 = strchr(hexdigits, gnstr.data[6]);
 | ||||
| +
 | ||||
| +                    if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
 | ||||
| +                        *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits);
 | ||||
|                          return 1; | ||||
|                      } | ||||
|                  } | ||||
| -                sentry++;
 | ||||
|              } | ||||
|   | ||||
| -            /* Search glyph to double Unicode value table */
 | ||||
| -            while (dentry->Glyph != 0) {
 | ||||
| -                if (dentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| -                    dentry++;
 | ||||
| -                    continue;
 | ||||
| -                }
 | ||||
| -                if (dentry->Glyph[0] > gnstr.data[0]){
 | ||||
| -                    break;
 | ||||
| -                }
 | ||||
| -                if (strlen(dentry->Glyph) == gnstr.size) {
 | ||||
| -                    if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) {
 | ||||
| -                        memcpy(Buffer, dentry->Unicode, 2);
 | ||||
| -                        return 2;
 | ||||
| +            if (length == 0) {
 | ||||
| +                single_glyph_list_t *sentry = (single_glyph_list_t *)&SingleGlyphList;
 | ||||
| +                double_glyph_list_t *dentry = (double_glyph_list_t *)&DoubleGlyphList;
 | ||||
| +                treble_glyph_list_t *tentry = (treble_glyph_list_t *)&TrebleGlyphList;
 | ||||
| +                quad_glyph_list_t *qentry = (quad_glyph_list_t *)&QuadGlyphList;
 | ||||
| +
 | ||||
| +                /* Search glyph to single Unicode value table */
 | ||||
| +                while (sentry->Glyph != 0) {
 | ||||
| +                    if (sentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| +                        sentry++;
 | ||||
| +                        continue;
 | ||||
| +                    }
 | ||||
| +                    if (sentry->Glyph[0] > gnstr.data[0]){
 | ||||
| +                        break;
 | ||||
| +                    }
 | ||||
| +                    if (strlen(sentry->Glyph) == gnstr.size) {
 | ||||
| +                        if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) {
 | ||||
| +                            *Buffer = sentry->Unicode;
 | ||||
| +                            return 1;
 | ||||
| +                        }
 | ||||
|                      } | ||||
| +                    sentry++;
 | ||||
|                  } | ||||
| -                dentry++;
 | ||||
| -            }
 | ||||
|   | ||||
| -            /* Search glyph to triple Unicode value table */
 | ||||
| -            while (tentry->Glyph != 0) {
 | ||||
| -                if (tentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| -                    tentry++;
 | ||||
| -                    continue;
 | ||||
| -                }
 | ||||
| -                if (tentry->Glyph[0] > gnstr.data[0]){
 | ||||
| -                    break;
 | ||||
| -                }
 | ||||
| -                if (strlen(tentry->Glyph) == gnstr.size) {
 | ||||
| -                    if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) {
 | ||||
| -                        memcpy(Buffer, tentry->Unicode, 3);
 | ||||
| -                        return 3;
 | ||||
| +                /* Search glyph to double Unicode value table */
 | ||||
| +                while (dentry->Glyph != 0) {
 | ||||
| +                    if (dentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| +                        dentry++;
 | ||||
| +                        continue;
 | ||||
|                      } | ||||
| +                    if (dentry->Glyph[0] > gnstr.data[0]){
 | ||||
| +                        break;
 | ||||
| +                    }
 | ||||
| +                    if (strlen(dentry->Glyph) == gnstr.size) {
 | ||||
| +                        if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) {
 | ||||
| +                            memcpy(Buffer, dentry->Unicode, 2);
 | ||||
| +                            return 2;
 | ||||
| +                        }
 | ||||
| +                    }
 | ||||
| +                    dentry++;
 | ||||
|                  } | ||||
| -                tentry++;
 | ||||
| -            }
 | ||||
|   | ||||
| -            /* Search glyph to quadruple Unicode value table */
 | ||||
| -            while (qentry->Glyph != 0) {
 | ||||
| -                if (qentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| -                    qentry++;
 | ||||
| -                    continue;
 | ||||
| -                }
 | ||||
| -                if (qentry->Glyph[0] > gnstr.data[0]){
 | ||||
| -                    break;
 | ||||
| +                /* Search glyph to triple Unicode value table */
 | ||||
| +                while (tentry->Glyph != 0) {
 | ||||
| +                    if (tentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| +                        tentry++;
 | ||||
| +                        continue;
 | ||||
| +                    }
 | ||||
| +                    if (tentry->Glyph[0] > gnstr.data[0]){
 | ||||
| +                        break;
 | ||||
| +                    }
 | ||||
| +                    if (strlen(tentry->Glyph) == gnstr.size) {
 | ||||
| +                        if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) {
 | ||||
| +                            memcpy(Buffer, tentry->Unicode, 3);
 | ||||
| +                            return 3;
 | ||||
| +                        }
 | ||||
| +                    }
 | ||||
| +                    tentry++;
 | ||||
|                  } | ||||
| -                if (strlen(qentry->Glyph) == gnstr.size) {
 | ||||
| -                    if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) {
 | ||||
| -                        memcpy(Buffer, qentry->Unicode, 4);
 | ||||
| -                        return 4;
 | ||||
| +
 | ||||
| +                /* Search glyph to quadruple Unicode value table */
 | ||||
| +                while (qentry->Glyph != 0) {
 | ||||
| +                    if (qentry->Glyph[0] < gnstr.data[0]) {
 | ||||
| +                        qentry++;
 | ||||
| +                        continue;
 | ||||
| +                    }
 | ||||
| +                    if (qentry->Glyph[0] > gnstr.data[0]){
 | ||||
| +                        break;
 | ||||
|                      } | ||||
| +                    if (strlen(qentry->Glyph) == gnstr.size) {
 | ||||
| +                        if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) {
 | ||||
| +                            memcpy(Buffer, qentry->Unicode, 4);
 | ||||
| +                            return 4;
 | ||||
| +                        }
 | ||||
| +                    }
 | ||||
| +                    qentry++;
 | ||||
|                  } | ||||
| -                qentry++;
 | ||||
|              } | ||||
|          } | ||||
|          *Buffer = fallback; | ||||
| @@ -1890,8 +1893,8 @@ txtwrite_process_cmap_text(gs_text_enum_t *pte)
 | ||||
|                  pte->returned.total_width.x += dpt.x; | ||||
|                  pte->returned.total_width.y += dpt.y; | ||||
|   | ||||
| -                penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]);
 | ||||
|                  penum->Widths[penum->TextBufferIndex] += dpt.x; | ||||
| +                penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]);
 | ||||
|                  break; | ||||
|              case 2:		/* end of string */ | ||||
|                  return 0; | ||||
| diff --git a/psi/zbfont.c b/psi/zbfont.c
 | ||||
| index 262fea9..abc03aa 100644
 | ||||
| --- a/psi/zbfont.c
 | ||||
| +++ b/psi/zbfont.c
 | ||||
| @@ -272,7 +272,7 @@ gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph, int ch, ushort *u, u
 | ||||
|           * can't be a default value for FontInfo.GlyphNames2Unicode . | ||||
|           */ | ||||
|      } | ||||
| -    if (glyph <= GS_MIN_CID_GLYPH) {
 | ||||
| +    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
 | ||||
|          UnicodeDecoding = zfont_get_to_unicode_map(font->dir); | ||||
|          if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary) | ||||
|              return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length); | ||||
							
								
								
									
										57
									
								
								SOURCES/ghostscript-cve-2020-16310.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								SOURCES/ghostscript-cve-2020-16310.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| diff --git a/devices/gdevdm24.c b/devices/gdevdm24.c
 | ||||
| index 4736f4f..2f610cd 100644
 | ||||
| --- a/devices/gdevdm24.c
 | ||||
| +++ b/devices/gdevdm24.c
 | ||||
| @@ -51,21 +51,39 @@ static void dot24_improve_bitmap (byte *, int);
 | ||||
|  static int | ||||
|  dot24_print_page (gx_device_printer *pdev, FILE *prn_stream, char *init_string, int init_len) | ||||
|  { | ||||
| -  int xres = (int)pdev->x_pixels_per_inch;
 | ||||
| -  int yres = (int)pdev->y_pixels_per_inch;
 | ||||
| -  int x_high = (xres == 360);
 | ||||
| -  int y_high = (yres == 360);
 | ||||
| -  int bits_per_column = (y_high ? 48 : 24);
 | ||||
| -  uint line_size = gdev_prn_raster (pdev);
 | ||||
| -  uint in_size = line_size * bits_per_column;
 | ||||
| -  byte *in = (byte *) gs_malloc (pdev->memory, in_size, 1, "dot24_print_page (in)");
 | ||||
| -  uint out_size = ((pdev->width + 7) & -8) * 3;
 | ||||
| -  byte *out = (byte *) gs_malloc (pdev->memory, out_size, 1, "dot24_print_page (out)");
 | ||||
| -  int y_passes = (y_high ? 2 : 1);
 | ||||
| -  int dots_per_space = xres / 10;	/* pica space = 1/10" */
 | ||||
| -  int bytes_per_space = dots_per_space * 3;
 | ||||
| +  int xres;
 | ||||
| +  int yres;
 | ||||
| +  int x_high;
 | ||||
| +  int y_high;
 | ||||
| +  int bits_per_column;
 | ||||
| +  uint line_size;
 | ||||
| +  uint in_size;
 | ||||
| +  byte *in;
 | ||||
| +  uint out_size;
 | ||||
| +  byte *out;
 | ||||
| +  int y_passes;
 | ||||
| +  int dots_per_space;
 | ||||
| +  int bytes_per_space;
 | ||||
|    int skip = 0, lnum = 0, ypass; | ||||
|   | ||||
| +  xres = (int)pdev->x_pixels_per_inch;
 | ||||
| +  yres = (int)pdev->y_pixels_per_inch;
 | ||||
| +  x_high = (xres == 360);
 | ||||
| +  y_high = (yres == 360);
 | ||||
| +  dots_per_space = xres / 10;       /* pica space = 1/10" */
 | ||||
| +  bytes_per_space = dots_per_space * 3;
 | ||||
| +  if (bytes_per_space == 0) {
 | ||||
| +    /* We divide by bytes_per_space later on. */
 | ||||
| +    return_error(gs_error_rangecheck);
 | ||||
| +  }
 | ||||
| +  bits_per_column = (y_high ? 48 : 24);
 | ||||
| +  line_size = gdev_prn_raster (pdev);
 | ||||
| +  in_size = line_size * bits_per_column;
 | ||||
| +  in = (byte *) gs_malloc (pdev->memory, in_size, 1, "dot24_print_page (in)");
 | ||||
| +  out_size = ((pdev->width + 7) & -8) * 3;
 | ||||
| +  out = (byte *) gs_malloc (pdev->memory, out_size, 1, "dot24_print_page (out)");
 | ||||
| +  y_passes = (y_high ? 2 : 1);
 | ||||
| +
 | ||||
|    /* Check allocations */ | ||||
|    if (in == 0 || out == 0) | ||||
|      { | ||||
| @ -1,201 +0,0 @@ | ||||
| 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 | ||||
| 
 | ||||
| @ -1,56 +0,0 @@ | ||||
| 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 | ||||
| @ -36,8 +36,8 @@ | ||||
| 
 | ||||
| Name:             ghostscript | ||||
| Summary:          Interpreter for PostScript language & PDF | ||||
| Version:          9.25 | ||||
| Release:          7%{?dist} | ||||
| Version:          9.27 | ||||
| Release:          1%{?dist} | ||||
| 
 | ||||
| License:          AGPLv3+ | ||||
| 
 | ||||
| @ -87,25 +87,20 @@ BuildRequires:    libXt-devel | ||||
| # Upstream patches -- official upstream patches released by upstream since the | ||||
| # ----------------    last rebase that are necessary for any reason: | ||||
| #Patch000: example000.patch | ||||
| Patch000: ghostscript-cve-2018-19409.patch | ||||
| Patch001: ghostscript-cve-2018-18073.patch | ||||
| Patch002: ghostscript-cve-2018-17961.patch | ||||
| Patch003: ghostscript-cve-2018-18284.patch | ||||
| Patch004: ghostscript-cve-2018-19134.patch | ||||
| Patch005: ghostscript-cve-2018-19475.patch | ||||
| Patch006: ghostscript-cve-2018-19476.patch | ||||
| Patch007: ghostscript-cve-2018-19477.patch | ||||
| Patch008: ghostscript-cve-2019-6116.patch | ||||
| Patch009: ghostscript-cve-2019-6116-downstream.patch | ||||
| Patch010: ghostscript-cve-2019-3839.patch | ||||
| Patch011: ghostscript-cve-2019-3835.patch | ||||
| Patch012: ghostscript-cve-2019-3838.patch | ||||
| Patch013: ghostscript-fix-DSC-comment-parsing.patch | ||||
| Patch014: ghostscript-pdf2dsc-regression.patch | ||||
| Patch015: ghostscript-cve-2019-10216.patch | ||||
| Patch016: ghostscript-cve-2019-14811-14812-14813.patch | ||||
| Patch017: ghostscript-cve-2019-14817.patch | ||||
| Patch018: ghostscript-cve-2019-14869.patch | ||||
| Patch001: ghostscript-cve-2019-10216.patch | ||||
| Patch002: ghostscript-cve-2019-14811-14812-14813.patch | ||||
| Patch003: ghostscript-cve-2019-14817.patch | ||||
| # fixed in 9.51 | ||||
| Patch004: ghostscript-cve-2020-16290.patch | ||||
| Patch005: ghostscript-cve-2020-16291.patch | ||||
| Patch006: ghostscript-cve-2020-16293.patch | ||||
| Patch007: ghostscript-cve-2020-16295.patch | ||||
| Patch008: ghostscript-cve-2020-16299.patch | ||||
| Patch009: ghostscript-cve-2020-16302.patch | ||||
| Patch010: ghostscript-cve-2020-16304.patch | ||||
| Patch011: ghostscript-cve-2020-16306.patch | ||||
| Patch012: ghostscript-cve-2020-16307.patch | ||||
| Patch013: ghostscript-cve-2020-16310.patch | ||||
| 
 | ||||
| # Downstream patches -- these should be always included when doing rebase: | ||||
| # ------------------ | ||||
| @ -308,7 +303,7 @@ rm -f %{buildroot}%{_datadir}/%{name}/doc | ||||
| 
 | ||||
| # Move html documentation into html/ subdir: | ||||
| install -m 0755 -d %{buildroot}%{_docdir}/%{name}/html | ||||
| mv -f %{buildroot}%{_docdir}/%{name}/{*.htm*,*.el,html} | ||||
| mv -f %{buildroot}%{_docdir}/%{name}/{*.htm*,html} | ||||
| 
 | ||||
| # --------------- | ||||
| 
 | ||||
| @ -445,6 +440,10 @@ done | ||||
| # ============================================================================= | ||||
| 
 | ||||
| %changelog | ||||
| * Tue Sep 01 2020 Anna Khaitovich <akhaitov@redhat.com> - 9.27-1 | ||||
| - Rebase to 9.27 | ||||
| - Resolves: rhbz#1874523 | ||||
| 
 | ||||
| * Tue Apr 07 2020 Zdenek Dohnal <zdohnal@redhat.com> - 9.25-7 | ||||
| - 1813228 - ghostscript fontconfig support broken when gs used with -dSAFER/-dPARANOIDSAFER | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user