Implement PDF version handling from catalog dictionary Add support for reading PDF version from the Version entry in the catalog dictionary. The catalog version takes precedence over the file header version. Bug: 409579362 Change-Id: I581e01a2ce79fd68126696a6ccbe45046f767bb4 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/130850 Auto-Submit: Helmut Januschka <helmut@januschka.com> Commit-Queue: Nicolás Peña <npm@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Nicolás Peña <npm@chromium.org>
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp index fb72ec0..b93dcae 100644 --- a/fpdfsdk/fpdf_view.cpp +++ b/fpdfsdk/fpdf_view.cpp
@@ -35,9 +35,11 @@ #include "core/fxcrt/cfx_timer.h" #include "core/fxcrt/check_op.h" #include "core/fxcrt/compiler_specific.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_memcpy_wrappers.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" #include "core/fxcrt/numerics/safe_conversions.h" #include "core/fxcrt/ptr_util.h" @@ -405,6 +407,24 @@ } *fileVersion = pParser->GetFileVersion(); + + const CPDF_Dictionary* root_dict = pDoc->GetRoot(); + if (root_dict) { + ByteString version = root_dict->GetNameFor("Version"); + if (!version.IsEmpty()) { + // Check for valid PDF version format "X.Y" + const bool has_valid_length = version.GetLength() == 3; + const bool has_valid_format = + has_valid_length && FXSYS_IsDecimalDigit(version[0]) && + version[1] == '.' && FXSYS_IsDecimalDigit(version[2]); + if (has_valid_format) { + const int major = FXSYS_DecimalCharToInt(version[0]); + const int minor = FXSYS_DecimalCharToInt(version[2]); + *fileVersion = major * 10 + minor; + } + } + } + return true; }
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp index bf5c8ed..7fb3479 100644 --- a/fpdfsdk/fpdf_view_embeddertest.cpp +++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -2236,3 +2236,10 @@ ASSERT_FALSE(bitmap); } } + +TEST_F(FPDFViewEmbedderTest, DocumentVersionInCatalog) { + ASSERT_TRUE(OpenDocument("version_in_catalog.pdf")); + int version; + EXPECT_TRUE(FPDF_GetFileVersion(document(), &version)); + EXPECT_EQ(16, version); +}
diff --git a/testing/resources/version_in_catalog.in b/testing/resources/version_in_catalog.in new file mode 100644 index 0000000..061e921 --- /dev/null +++ b/testing/resources/version_in_catalog.in
@@ -0,0 +1,24 @@ +{{header}} +%PDF-1.5 +{{object 1 0}} << + /Type /Catalog + /Version /1.6 + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF \ No newline at end of file
diff --git a/testing/resources/version_in_catalog.pdf b/testing/resources/version_in_catalog.pdf new file mode 100644 index 0000000..4835c0b --- /dev/null +++ b/testing/resources/version_in_catalog.pdf
@@ -0,0 +1,34 @@ +%PDF-1.7 +% ò¤ô +%PDF-1.5 +1 0 obj << + /Type /Catalog + /Version /1.6 + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] +>> +endobj +xref +0 4 +0000000000 65535 f +0000000024 00000 n +0000000093 00000 n +0000000156 00000 n +trailer << + /Root 1 0 R + /Size 4 +>> +startxref +233 +%%EOF