Accept Latin-1 password encoding in document load functions.
BUG=pdfium:1194
Change-Id: Ie25fb194af813ed37d7a91d20777efbef5059a00
Reviewed-on: https://pdfium-review.googlesource.com/c/48213
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index 4e38a74..4909c56 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -397,6 +397,24 @@
bool CPDF_SecurityHandler::CheckPassword(const ByteString& password,
bool bOwner) {
+ if (CheckPasswordImpl(password, bOwner))
+ return true;
+
+ ByteStringView password_view = password.AsStringView();
+ if (password_view.IsASCII())
+ return false;
+
+ if (m_Revision >= 5) {
+ ByteString utf8_password = WideString::FromLatin1(password_view).ToUTF8();
+ return CheckPasswordImpl(utf8_password, bOwner);
+ }
+
+ ByteString latin1_password = WideString::FromUTF8(password_view).ToLatin1();
+ return CheckPasswordImpl(latin1_password, bOwner);
+}
+
+bool CPDF_SecurityHandler::CheckPasswordImpl(const ByteString& password,
+ bool bOwner) {
if (m_Revision >= 5)
return AES256_CheckPassword(password, bOwner);
diff --git a/core/fpdfapi/parser/cpdf_security_handler.h b/core/fpdfapi/parser/cpdf_security_handler.h
index ae37c35..8dcf009 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.h
+++ b/core/fpdfapi/parser/cpdf_security_handler.h
@@ -53,8 +53,8 @@
ByteString GetUserPassword(const ByteString& owner_password) const;
bool CheckPassword(const ByteString& user_password, bool bOwner);
+ bool CheckPasswordImpl(const ByteString& password, bool bOwner);
bool CheckUserPassword(const ByteString& password, bool bIgnoreEncryptMeta);
-
bool CheckOwnerPassword(const ByteString& password);
bool AES256_CheckPassword(const ByteString& password, bool bOwner);
void AES256_SetPassword(CPDF_Dictionary* pEncryptDict,
diff --git a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
index bfaacaa..dd30406 100644
--- a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
@@ -133,8 +133,8 @@
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion2UTF8) {
// The password is "age", where the 'a' has a circumflex. Encoding the
- // password as UTF-8 does not work. TODO(bug_1194): Fix this.
- ASSERT_FALSE(
+ // password as UTF-8 works.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r2.pdf", kAgeUTF8));
}
@@ -147,7 +147,7 @@
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion3UTF8) {
// Same as OwnerPasswordVersion2UTF8 test above.
- ASSERT_FALSE(
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r3.pdf", kAgeUTF8));
}
@@ -159,36 +159,35 @@
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion5UTF8) {
- // The password is "age", where the 'a' has a circumflex. Encoding the
- // password as UTF-8 works.
+ // Same as OwnerPasswordVersion2UTF8 test above.
ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r5.pdf", kAgeUTF8));
EXPECT_EQ(5, FPDF_GetSecurityHandlerRevision(document()));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion5Latin1) {
- // And Latin-1 encoding does not work. TODO(bug_1194): Fix this.
- ASSERT_FALSE(
+ // Same as OwnerPasswordVersion2Latin1 test above.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r5.pdf", kAgeLatin1));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion6UTF8) {
- // Same as OwnerPasswordVersion5UTF8 test above.
+ // Same as OwnerPasswordVersion2UTF8 test above.
ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r6.pdf", kAgeUTF8));
EXPECT_EQ(6, FPDF_GetSecurityHandlerRevision(document()));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPasswordVersion6Latin1) {
- // Same as OwnerPasswordVersion5Latin1 test above.
- ASSERT_FALSE(
+ // Same as OwnerPasswordVersion2Latin1 test above.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r6.pdf", kAgeLatin1));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion2UTF8) {
// The password is "hotel", where the 'o' has a circumflex. Encoding the
- // password as UTF-8 does not work. TODO(bug_1194): Fix this.
- ASSERT_FALSE(
+ // password as UTF-8 works.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r2.pdf", kHotelUTF8));
}
@@ -201,7 +200,7 @@
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion3UTF8) {
// Same as UserPasswordVersion2UTF8 test above.
- ASSERT_FALSE(
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r3.pdf", kHotelUTF8));
}
@@ -213,28 +212,27 @@
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion5UTF8) {
- // The password is "hotel", where the 'o' has a circumflex. Encoding the
- // password as UTF-8 works.
+ // Same as UserPasswordVersion2UTF8 test above.
ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r5.pdf", kHotelUTF8));
EXPECT_EQ(5, FPDF_GetSecurityHandlerRevision(document()));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion5Latin1) {
- // And Latin-1 encoding does not work. TODO(bug_1194): Fix this.
- ASSERT_FALSE(
+ // Same as UserPasswordVersion2Latin1 test above.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r5.pdf", kHotelLatin1));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion6UTF8) {
- // Same as UserPasswordVersion5UTF8 test above.
+ // Same as UserPasswordVersion2UTF8 test above.
ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r6.pdf", kHotelUTF8));
EXPECT_EQ(6, FPDF_GetSecurityHandlerRevision(document()));
}
TEST_F(CPDFSecurityHandlerEmbedderTest, UserPasswordVersion6Latin1) {
- // Same as UserPasswordVersion5Latin1 test above.
- ASSERT_FALSE(
+ // Same as UserPasswordVersion2Latin1 test above.
+ ASSERT_TRUE(
OpenDocumentWithPassword("encrypted_hello_world_r6.pdf", kHotelLatin1));
}
diff --git a/public/fpdf_dataavail.h b/public/fpdf_dataavail.h
index 68a76a0..ad70b7f 100644
--- a/public/fpdf_dataavail.h
+++ b/public/fpdf_dataavail.h
@@ -119,6 +119,8 @@
//
// When FPDFAvail_IsDocAvail() returns TRUE, call FPDFAvail_GetDocument() to
// retrieve the document handle.
+// See the comments for FPDF_LoadDocument() regarding the encoding for
+// |password|.
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password);
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 0ba50e2..acd7400 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -296,12 +296,19 @@
// file_path - Path to the PDF file (including extension).
// password - A string used as the password for the PDF file.
// If no password is needed, empty or NULL can be used.
+// See comments below regarding the encoding.
// Return value:
// A handle to the loaded document, or NULL on failure.
// Comments:
// Loaded document can be closed by FPDF_CloseDocument().
// If this function fails, you can use FPDF_GetLastError() to retrieve
// the reason why it failed.
+//
+// The encoding for |password| can be either UTF-8 or Latin-1. PDFs,
+// depending on the security handler revision, will only accept one or
+// the other encoding. If |password|'s encoding and the PDF's expected
+// encoding do not match, FPDF_LoadDocument() will automatically
+// convert |password| to the other encoding.
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password);
@@ -319,6 +326,9 @@
// The loaded document can be closed by FPDF_CloseDocument.
// If this function fails, you can use FPDF_GetLastError() to retrieve
// the reason why it failed.
+//
+// See the comments for FPDF_LoadDocument() regarding the encoding for
+// |password|.
// Notes:
// If PDFium is built with the XFA module, the application should call
// FPDF_LoadXFA() function after the PDF document loaded to support XFA
@@ -447,6 +457,9 @@
// document is closed.
//
// The loaded document can be closed with FPDF_CloseDocument.
+//
+// See the comments for FPDF_LoadDocument() regarding the encoding for
+// |password|.
// Notes:
// If PDFium is built with the XFA module, the application should call
// FPDF_LoadXFA() function after the PDF document loaded to support XFA