Skip to content

Support reading PDF 2.0 files (#490) - #495

Open
jafin wants to merge 1 commit into
ststeiger:masterfrom
jafin:upstream-490-pdf-2.0
Open

Support reading PDF 2.0 files (#490)#495
jafin wants to merge 1 commit into
ststeiger:masterfrom
jafin:upstream-490-pdf-2.0

Conversation

@jafin

@jafin jafin commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Fixes #490, at the lines the issue points to.

What happens

GetPdfFileVersion gates the major version digit with major < '2':

if (major >= '1' && major < '2' && minor >= '0' && minor <= '9')
    return (major - '0') * 10 + (minor - '0');

So a %PDF-2.0 header falls through and the method returns 0. PdfReader.Open treats 0 as fatal:

document._version = GetPdfFileVersion(header);
if (document._version == 0)
    throw new InvalidOperationException(PSSR.InvalidPdf);

Every PDF 2.0 file therefore fails with "The file is not a valid PDF document.", whatever is actually in it.

The fix

Accept major version 1 or 2, which are the versions defined so far.

The version scan was duplicated verbatim — once against PdfEncoders.RawEncoding and again as an ASCII fallback for incorrectly encoded files — so rather than patch the same condition in two places it is extracted into ScanFileVersion(encoding, bytes) and called twice. The behaviour of the fallback is unchanged.

While the scan was being lifted out, the indexing into the header is now guarded explicitly (ich + 6 < header.Length, and an empty header returns early) instead of relying on the surrounding catch { } to swallow an IndexOutOfRangeException. A header ending exactly at PDF- no longer depends on an exception to be rejected.

Two smaller things follow from this:

  • PdfDocument.Version rejected anything outside 12..17, so a document read as 2.0 could not have its version set. 20 is now permitted.
  • PSSR.InvalidVersionNumber still read "Valid values are 12, 13, and 14.", which had been stale since 1.5 support arrived. It now matches what the setter accepts.

PdfWriter needs no change: it already formats the header from version / 10 and version % 10, so it writes %PDF-2.0 once the version survives being read.

Verification

PdfSharpCore.Test/IO/PdfVersionTests.cs covers the header scan directly through the existing TestPdfFile(byte[]) overload — 1.0, 1.4, 1.7, 2.0, and the PostScript style %!PS-Adobe-3.0 PDF-2.0 header that the comment in the method says Acrobat accepts — along with headers that must still be rejected (%PDF-0.9, %PDF-1.A, a truncated %PDF, and something that is not a PDF at all).

Three further tests use a real PDF 2.0 document produced by wkhtmltopdf, added as Assets/Pdf20.pdf alongside the assets already in the suite: it opens, it reports version 20, and saving it again still writes a %PDF-2.0 header.

All five of the PDF 2.0 assertions fail without the change and pass with it; the seven that guard existing behaviour pass either way.

Test run on net8.0: 38 passed, 5 failed, 1 skipped. The five failures are the XTextFormatterTest rendering comparisons, which fail identically on an unmodified master here because they shell out to Ghostscript (gswin64c.exe, exit 127) and it is not installed on this machine. Baseline on master is 26 passed with the same 5 failures, so this adds 12 passing tests and changes nothing else.

GetPdfFileVersion gated the major version digit with `major < '2'`, so a
%PDF-2.0 header parsed to 0. PdfReader.Open treats 0 as fatal, which made
every PDF 2.0 file fail with "The file is not a valid PDF document."

Accept major version 1 or 2. The version scan was duplicated verbatim in a
raw-encoding attempt and an ASCII fallback, so extract it into
ScanFileVersion rather than patching the same condition twice, and guard
the header indexing explicitly instead of relying on a caught
IndexOutOfRangeException.

PdfDocument.Version rejected anything outside 12..17, so setting 20 threw;
permit it, and refresh the stale InvalidVersionNumber message. PdfWriter
needs no change, as it already formats the header from version/10 and
version%10.

Fixes ststeiger#490
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PDF with %PDF-2.0 are not supported

1 participant