diff options
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/pdf_main.ps')
-rw-r--r-- | Master/tlpkg/tlgs/Resource/Init/pdf_main.ps | 403 |
1 files changed, 332 insertions, 71 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps index 85b5848e160..a16f5806734 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps @@ -85,6 +85,9 @@ pdfdict begin pdfformaterror ( Output may be incorrect.\n) pdfformaterror } bind + + /Recursive_XObject_D 1 dict def + .dicttomark readonly def % ======================== Main program ======================== % @@ -948,9 +951,17 @@ currentdict /xref-char-dict undef %% Bug #695883 the test file has an XRefStm which points beyond the end of the file. %% We check that here and simply fall back to thje classic xref if this error occurs. dup PDFfilelen lt{ - readpdf15xref pop + PDFSTOPONERROR not { + mark exch {readpdf15xref pop} stopped + { + ( **** Error: This hybrid file's XRefStm does not point to a valid stream.\n Ignoring error, output may be incorrect.\n) pdfformaterror + } if + cleartomark + } { + readpdf15xref pop + } ifelse } { - ( **** Error: This hybrid file's XRefStm points beyond the end of file.\n Ignoring error, output may be incorrect.\n) pdfformaterror + ( **** Error: This hybrid file's XRefStm points beyond the end of file.\n Ignoring error, output may be incorrect.\n) pdfformaterror pop }ifelse } if @@ -1129,7 +1140,37 @@ currentdict /xref-char-dict undef ( **** ) stderrprint stderrprint } ifelse } ifelse - } if + } { + % If the user told us to use a named OutputIntent + systemdict /UseOutputIntent .knownget { + cvn + Trailer /Root oget /OutputIntents knownoget { + { + dup /OutputConditionIdentifier get cvn + dup /Custom eq { + pop + dup /Info get cvn + }if + 2 index eq { + %% Found the required OutputIntent + /DestOutputProfile knownoget { + [ /ICCBased 3 -1 roll ] ICCBased-resolve + 1 get .set_outputintent + () + } if + pop + exit + }{ + pop + } ifelse + } + forall + pop + }{ + pop + }ifelse + } if + }ifelse Trailer /Root knownoget { /PageLabels knownoget { %% Currenlty only the pdfwrite device can handle PageLabels %% because we deal with these using putparams, not pdfmarks @@ -1283,6 +1324,8 @@ currentdict /xref-char-dict undef % Read any previous cross-reference tables. When we are done, % verify that the entries in the xref tables are valid if NoVerifyXref % is not defined. + /PrevArray [] def % Empty array, we use this to detect circular /Prev entries in xref (see below) + % For some reqason, leaving this on the stack messes up seom files. Trailer { /Prev knownoget not { % If no previous xref table then ... Classic-xref { @@ -1290,10 +1333,43 @@ currentdict /xref-char-dict undef } if exit } if + + %% This code is used to detect circular references in xref tables. Every time + %% we detect a /Prev in the xref, we check the given offset of the /Prev xref + %% against a list of all previously encountered /Prev offsets. If we find that + %% we have previously seen this one, we raise an error, stop processing the xref + %% but carry on with the PDF file (unless PDFSTOPONERROR is true). + //false exch PrevArray %% Used to determine if the looop found a circular ref + { %% //false offset 'array entry' + 1 index eq { + exch pop //true exch %% We've seen this offset before, pop the false and replace with true + exit %% //true offset + } if + } forall + + exch %% [...] offset bool + { + (\n **** Error: Circular /Prev entry while reading xref.\n Aborting xref read, output may be incorrect.\n) + pdfformaterror + PDFSTOPONERROR { + /readxref /syntaxerror cvx signalerror + } if + pop exit %% [...] and then exit this loop + } if + + PrevArray dup %% offset [...] [...] + length 1 add array %% offset [...] [ ] + dup 3 1 roll %% offset [ ] [...] [ ] + copy pop %% offset [... ] + dup dup length 1 sub %% offset [... ] [... ] index + 3 index %% offset [... ] [... ] index offset + put /PrevArray exch def + { readxref } PDFSTOPONERROR not { .internalstopped { recover_xref_data % Read failed. Attempt to recover xref data. + /PrevArray where {/PrevArray undef} if %% remove the array we were using to detect circular references exit % Exit loop since recover gets all obj data. } if % If readxref stopped } { @@ -1312,6 +1388,7 @@ currentdict /xref-char-dict undef } ifelse } forall } loop % Loop to previous trailer + /PrevArray where {/PrevArray undef} if %% remove the array we were using to detect circular references } if /NumObjects Objects length def % To check that obj# < NumObjects @@ -1584,10 +1661,32 @@ currentdict /xref-char-dict undef { 2 copy knownoget { exch pop exch pop //true } - { exch /Parent knownoget - { exch pget } + { + %% Check to see if there's a Parent + 1 index + 3 1 roll + exch /Parent knownoget + { + %% If there is a Parent, check to see if this dictionary has a stored object number + 3 -1 roll /.gs.pdfobj# .knownget { + %% if it does, check the Parent as wwell + 1 index /.gs.pdfobj# .knownget { + %% Both have object numbers, are they the same (ie its self-referencing) + eq { + pop pop + //false + }{ + exch pget + }ifelse + }{ + pop exch pget + }ifelse + } { + exch pget + }ifelse + } % finally see if the key is (misplaced) in the Root Catalog dict - { dup Trailer /Root oget exch knownoget dup { + { exch pop dup Trailer /Root oget exch knownoget dup { 3 -1 roll ( **** Error: The /) pdfformaterror 50 string cvs pdfformaterror ( key is missing from the Page tree.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror @@ -1600,6 +1699,30 @@ currentdict /xref-char-dict undef ifelse } bind def +/obj_get { + LocalResources 1 index knownoget { + dup 4 index known { + 3 index get + 0 get 4 1 roll pop pop pop + } if + } { + 1 index /Resources pget { + 1 index knownoget { + dup 4 index known { + 3 index get + 0 get 4 1 roll pop pop pop + }{ + pop pop pop 0 + }ifelse + }{ + pop pop pop 0 + } ifelse + } { + pop pop pop 0 + }ifelse + }ifelse +}bind def + % Get the value of a resource on a given page. /rget { % <resname> <pagedict> <restype> rget <value> -true- % <resname> <pagedict> <restype> rget -false- @@ -2109,14 +2232,61 @@ end readonly def /MediaBox exch get_media_box pop } { oforce_elems % <<pdict>> /SomeBox x0 y0 x1 y1 + %% Complicated stuff. We need to use the 'Box' we identified (if any), but we + %% need to clamp the boundaries of the 'Box' to the MediaBox. This appears to + %% be what Acrobat does. The complication arises because the Box values don't + %% have to be sensibly positive, its permissible to have the MediaBox set up + %% so that it extends down and left instead of up and right. We take care of the + %% content when we st up the CTM, but we do need to make sure that we clamp + %% the BoundingBox, and that means we need to take direcitonality into account... + 6 -1 roll get_media_box { % /SomeBox x0 y0 x1 y1 [MediaBox] aload pop % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 - 5 -1 roll .min exch % /SomeBox x0 y0 x1 X0 Y0 mY1 X1 - 5 -1 roll .min exch % /SomeBox x0 y0 X0 Y0 mX1 mY1 - 4 2 roll % /SomeBox x0 y0 mX1 mY1 X0 Y0 - 5 -1 roll .max exch % /SomeBox x0 mX1 mY1 mY0 X0 - 5 -1 roll .max exch % /SomeBox mX1 mY1 mX0 mY0 - 4 2 roll % /SomeBox mX0 mY0 mX1 mY1 + + %% Start with the width, get the X0 and X1 values of the MediaBox + 3 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 + 2 index % /SomeBox x0 y0 x1 y1 X0 Y0 X1 Y1 X0 X1 + gt { + %% Media extends to left + 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 + 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 + .min % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 + 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 + exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 + 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 + .max % /SomeBox mX0 y0 y1 Y0 Y1 mX1 + 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 + }{ + %% Media extends to right + 4 -1 roll % /SomeBox x0 y0 x1 y1 Y0 X1 Y1 X0 + 8 -1 roll % /SomeBox y0 x1 y1 Y0 X1 Y1 X0 x0 + .max % /SomeBox y0 x1 y1 Y0 X1 Y1 mX0 + 7 1 roll % /SomeBox mX0 y0 x1 y1 Y0 X1 Y1 + exch % /SomeBox mX0 y0 x1 y1 Y0 Y1 X1 + 5 -1 roll % /SomeBox mX0 y0 y1 Y0 Y1 X1 x1 + .min % /SomeBox mX0 y0 y1 Y0 Y1 mX1 + 5 1 roll % /SomeBox mX0 mX1 y0 y1 Y0 Y1 + } ifelse + + %% Now deal with the height + 2 copy % /SomeBox mX0 mX1 y0 y1 Y0 Y1 Y0 Y1 + gt { + %% Media extends down + exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 + 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 + .min % /SomeBox mX0 mX1 y1 Y1 mY0 + 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 + .max % /SomeBox mX0 mX1 mY0 mY1 + }{ + %% Media extends up + exch % /SomeBox mX0 mX1 y0 y1 Y1 Y0 + 4 -1 roll % /SomeBox mX0 mX1 y1 Y1 Y0 y0 + .max % /SomeBox mX0 mX1 y1 Y1 mY0 + 3 1 roll % /SomeBox mX0 mX1 mY0 y1 Y1 + .min % /SomeBox mX0 mX1 mY0 mY1 + } ifelse + exch % /SomeBox mX0 mX1 mY1 mY0 + 3 1 roll % /SomeBox mX0 mY0 mX1 mY1 } { pop } ifelse @@ -2268,6 +2438,37 @@ currentdict /PDF2PS_matrix_key undef % is not actually used on the page. currentpagedevice /PageSpotColors known { /PageSpotColors 2 index countspotcolors def } if + % If the user told us to use a named OutputIntent + systemdict /UseOutputIntent .knownget { + cvn + % Check to see if this page has such an OutputIntent + 2 index /OutputIntents knownoget { + { + dup /OutputConditionIdentifier get cvn + dup /Custom eq { + pop + dup /Info get cvn + }if + 2 index eq { + %% Found the required OutputIntent + /DestOutputProfile knownoget { + [ /ICCBased 3 -1 roll ] ICCBased-resolve + 1 get .set_outputintent + () + } if + pop + exit + }{ + pop + } ifelse + } + forall + pop + }{ + pop + }ifelse + } if + % Let the device know if we will be using PDF 1.4 transparency. % The clist logic may need to adjust the size of bands. 1 index pageusestransparency /PageUsesTransparency exch def @@ -2541,7 +2742,22 @@ currentdict /PDF2PS_matrix_key undef } { dup //false exch { 4 dict 1 index resourceusestransparency { pop not exit } if - /Parent knownoget not { exit } if + %% Check the current dictionary and its Parent (if any) to see + %% if they both have stored object numbers. If they do then + %% check the numbers, don't allow self-references. + dup /Parent knownoget not { pop exit } + { + exch /.gs.pdfobj# .knownget + { + 1 index /.gs.pdfobj# .knownget { + eq { + pop exit + }if + }{ + pop + }ifelse + }if + } ifelse } loop % Also check for transparency in the annotation (if not in resources). { pop //true } { annotsusetransparency } ifelse @@ -2884,74 +3100,87 @@ currentdict /PDF2PS_matrix_key undef } if } bind def -%%<Objectdict> <calling obj_num> pdfform_detect_cspacesub <boolean> +%% <loopdict> <Objectdict> <calling obj_num> pdfform_detect_cspacesub <boolean> %% /pdf_object_detect_cspacesub { - exch %% <calling obj_num> <Objectdict> - dup pdf_colorspace_detect_cspacesub { - pop //true - }{ %% <calling obj_num> <Objectdict> - /Resources knownoget { %% <calling obj_num> <Resourcesdict> - /XObject knownoget { %% <calling obj_num> <XObjectdict> - //false exch %% <calling obj_num> <XObjectdict> false - %% We have files where the XObject Resource is not a dictionary - dup type /dicttype eq { %% <calling obj_num> <XObjectdict> false - - %% check each Xobject entry in the dictionary, - %% forall purs a key/value pair on the stack for us. - %% - { %% <calling obj_num> <XObjectdict> false key value - exch pop %% <calling obj_num> <XObjectdict> false value - - %% If this is an indirect reference, check if its the smae object - %% as the current one. If its not indirect, make the object number 0 - %% for comparison purposes. - dup type /packedarraytype eq { - dup 0 get dup 4 index - eq - } { - 0 false - }ifelse + %% use loop operator for an exitable context + %% we need this to detect recursion/looping + { + exch %% <loopdict> <calling obj_num> <Objectdict> + dup pdf_colorspace_detect_cspacesub { + pop pop //true exit + }{ %% <loopdict> <calling obj_num> <Objectdict> + /Resources knownoget { %% <loopdict> <calling obj_num> <Resourcesdict> + 2 index 1 index known { + %% We've already seen this object, ignore it and exit + pop pop //false exit + }{ + 2 index 1 index //null put + } ifelse - %% <calling obj_num> <XObjectdict> false value <form object or 0 if not indirect> <boolean> - not { - %% swap object number and value, and dereference value - exch oforce - %% Apparently we have files where the content of the XObject Resource dictionary is null - dup //null ne { - %% and files where the indivudal XObjects are not dictionaries - dup type /dicttype eq { - dup /Subtype get /Form eq { - exch - pdf_object_detect_cspacesub { - pop //true exit - } if - } { + /XObject knownoget { %% <loopdict> <calling obj_num> <XObjectdict> + //false exch %% <loopdict> <calling obj_num> <XObjectdict> false + %% We have files where the XObject Resource is not a dictionary + dup type /dicttype eq { %% <loopdict> <calling obj_num> <XObjectdict> false + + %% check each Xobject entry in the dictionary, + %% forall purs a key/value pair on the stack for us. + %% + { %% <loopdict> <calling obj_num> <XObjectdict> false key value + exch pop %% <loopdict> <calling obj_num> <XObjectdict> false value + + %% If this is an indirect reference, check if its the smae object + %% as the current one. If its not indirect, make the object number 0 + %% for comparison purposes. + dup type /packedarraytype eq { + dup 0 get dup 4 index + eq + } { + 0 false + }ifelse + + %% <calling obj_num> <XObjectdict> false value <form object or 0 if not indirect> <boolean> + not { + %% swap object number and value, and dereference value + exch oforce + %% Apparently we have files where the content of the XObject Resource dictionary is null + dup //null ne { + %% and files where the indivudal XObjects are not dictionaries + dup type /dicttype eq { + dup /Subtype get /Form eq { + exch + 4 index 3 1 roll pdf_object_detect_cspacesub { + pop //true exit + } if + } { + pop pop + }ifelse + }{ pop pop - }ifelse + } ifelse }{ pop pop - } ifelse + } + ifelse }{ pop pop - } - ifelse - }{ - pop pop - } ifelse - } forall - }{ - pop + } ifelse + } forall + }{ + pop + }ifelse + } { + %% No forms, so can't be any Default* spaces + //false }ifelse } { - %% No forms, so can't be any Default* spaces //false - }ifelse - } { - //false + } ifelse } ifelse - } ifelse - %% Remove the calling object ID, return our boolean + %% Remove the calling object ID, return our boolean + exch pop exit + } loop + %% remove and discard the loopdict exch pop } bind def @@ -2966,12 +3195,11 @@ currentdict /PDF2PS_matrix_key undef % not using UseCIEColor with pdfwrite. % /pdfshowpage_detect_cspacesub { - dup 0 pdf_object_detect_cspacesub + dup 0 1 dict 3 1 roll pdf_object_detect_cspacesub /HighLevelDevice /GetDeviceParam .special_op { exch pop not exch pop }if - } bind def % @@ -3110,3 +3338,36 @@ currentdict /PDF2PS_matrix_key undef end % pdfdict .setglobal + +DELAYBIND not { +%% 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. +[ +/.pdfawidthshow /.pdfwidthshow +/.setfillcolor /.setfillcolorspace /.setstrokecolor /.setstrokecolorspace /.currentrenderingintent /.setrenderingintent +/.currenttextrenderingmode /.settextspacing /.currenttextspacing /.settextleading /.currenttextleading +/.settextrise /.currenttextrise /.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling +/.settextlinematrix /.currenttextlinematrix /.currenttextmatrix /.settextmatrix /.currentblendmode +/.currentopacityalpha /.currentshapealpha /.currenttextknockout +/.pushextendedgstate /.popextendedgstate /.begintransparencytextgroup +/.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.endtransparencymask /.image3x +/.abortpdf14devicefilter /.pdfinkpath /.pdfFormName /.setstrokeconstantalpha +/.setfillconstantalpha /.setalphaisshape /.currentalphaisshape +/.settextspacing /.currenttextspacing /.settextleading /.currenttextleading /.settextrise /.currenttextrise +/.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling + +% Used by our own test suite files +%/.pushpdf14devicefilter % transparency-example.ps +%/.poppdf14devicefilter % transparency-example.ps +%/.setopacityalpha % transparency-example.ps +%/.setshapealpha % transparency-example.ps +%/.endtransparencygroup % transparency-example.ps + +% undefining these causes errors/incorrect output +%/.settextrenderingmode /.setblendmode /.begintransparencygroup /.settextknockout /check_r6_password /.setstrokeoverprint /.setfilloverprint +%/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha +] +{systemdict exch .undef} forall +} if |