Save encrypted files without IDs in CPDFSecurityHandlerEmbedderTests.
Add methods to CPDF_Parser and CPDF_CrossRefTable to strip the /ID entry
from the PDF trailer. Use this in CPDFSecurityHandlerEmbedderTests to
exercise the PDF creation code paths where they attempt to write out new
encryption dictionaries. This uncovered at least 2 bugs in the code, so
some of the new test code is disabled for now, with TODOs to fix them.
Bug: chromium:1032090,pdfium:1440
Change-Id: Ic285e4ed7ff89b3dc9c604f3e51c5345a4f64f27
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/63752
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.h b/core/fpdfapi/parser/cpdf_cross_ref_table.h
index c2b4f1e..66a51de 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.h
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.h
@@ -50,8 +50,9 @@
void AddNormal(uint32_t obj_num, uint16_t gen_num, FX_FILESIZE pos);
void SetFree(uint32_t obj_num);
- const CPDF_Dictionary* trailer() const { return trailer_.Get(); }
void SetTrailer(RetainPtr<CPDF_Dictionary> trailer);
+ const CPDF_Dictionary* trailer() const { return trailer_.Get(); }
+ CPDF_Dictionary* GetMutableTrailerForTesting() { return trailer_.Get(); }
const ObjectInfo* GetObjectInfo(uint32_t obj_num) const;
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index e4ac195..8cfb6fc 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -246,7 +246,7 @@
return HANDLER_ERROR;
auto pSecurityHandler = pdfium::MakeRetain<CPDF_SecurityHandler>();
- if (!pSecurityHandler->OnInit(pEncryptDict, GetIDArray(), m_Password))
+ if (!pSecurityHandler->OnInit(pEncryptDict, GetIDArray(), GetPassword()))
return PASSWORD_ERROR;
m_pSecurityHandler = std::move(pSecurityHandler);
@@ -824,6 +824,10 @@
return m_CrossRefTable->trailer();
}
+CPDF_Dictionary* CPDF_Parser::GetMutableTrailerForTesting() {
+ return m_CrossRefTable->GetMutableTrailerForTesting();
+}
+
RetainPtr<CPDF_Dictionary> CPDF_Parser::GetCombinedTrailer() const {
return m_CrossRefTable->trailer()
? ToDictionary(m_CrossRefTable->trailer()->Clone())
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 30d08ea..8259f08 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -68,6 +68,7 @@
ByteString GetPassword() const { return m_Password; }
const CPDF_Dictionary* GetTrailer() const;
+ CPDF_Dictionary* GetMutableTrailerForTesting();
// Returns a new trailer which combines the last read trailer with the /Root
// and /Info from previous ones.
diff --git a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
index 6bab48b..a3cf04b 100644
--- a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
@@ -6,6 +6,9 @@
#include <string>
#include "build/build_config.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fxcrt/fx_system.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdf_edit.h"
@@ -52,6 +55,19 @@
CloseSavedDocument();
}
+ void RemoveTrailerIdFromDocument() {
+ // This is cheating slightly to avoid a layering violation, since this file
+ // cannot include fpdfsdk/cpdfsdk_helpers.h to get access to
+ // CPDFDocumentFromFPDFDocument().
+ CPDF_Document* doc = reinterpret_cast<CPDF_Document*>((document()));
+ ASSERT_TRUE(doc);
+ CPDF_Parser* parser = doc->GetParser();
+ ASSERT_TRUE(parser);
+ CPDF_Dictionary* trailer = parser->GetMutableTrailerForTesting();
+ ASSERT_TRUE(trailer);
+ ASSERT_TRUE(trailer->RemoveFor("ID"));
+ }
+
private:
void VerifyHelloWorldPage(FPDF_PAGE page) {
ASSERT_TRUE(page);
@@ -180,6 +196,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion2Latin1) {
@@ -190,6 +216,12 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion3UTF8) {
@@ -200,6 +232,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion3Latin1) {
@@ -210,6 +252,12 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion5UTF8) {
@@ -220,6 +268,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion5Latin1) {
@@ -230,6 +288,18 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion6UTF8) {
@@ -240,6 +310,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion6Latin1) {
@@ -250,6 +330,18 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion2UTF8) {
@@ -261,6 +353,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion2Latin1) {
@@ -271,6 +373,12 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion3UTF8) {
@@ -281,6 +389,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion3Latin1) {
@@ -291,6 +409,12 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion5UTF8) {
@@ -301,6 +425,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion5Latin1) {
@@ -311,6 +445,18 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion6UTF8) {
@@ -321,6 +467,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion6Latin1) {
@@ -331,4 +487,16 @@
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+
+#if 0
+ // TODO(crbug.com/1032090): This triggers an MSAN error.
+ // Fix and enable this code.
+ // TODO(crbug.com/pdfium/1440): Password is in the wrong encoding.
+ // Fix and enable this code.
+ ClearString();
+ RemoveTrailerIdFromDocument();
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedHelloWorldDocumentWithPassword(kAgeLatin1);
+ VerifySavedHelloWorldDocumentWithPassword(kAgeUTF8);
+#endif
}