From aa50728980036f07fda232cea974fd80c89b7cb7 Mon Sep 17 00:00:00 2001 From: Artem Strygin Date: Tue, 24 Jul 2018 10:14:24 +0000 Subject: Fix encryption dictionary owning. Return encryption dictionary as const reference from CPDF_Parser. Create a copy in CPDF_Creator if needed. Change-Id: I270f71d307d818fba7f65ebe379f5942ae816934 Reviewed-on: https://pdfium-review.googlesource.com/38390 Reviewed-by: Lei Zhang Commit-Queue: Art Snake --- core/fpdfapi/edit/cpdf_creator.cpp | 8 ++-- core/fpdfapi/edit/cpdf_creator.h | 3 +- core/fpdfapi/parser/cpdf_parser.cpp | 66 ++++++++++++--------------- core/fpdfapi/parser/cpdf_parser.h | 4 +- core/fpdfapi/parser/cpdf_security_handler.cpp | 8 +++- fpdfsdk/fpdf_view.cpp | 2 +- 6 files changed, 45 insertions(+), 46 deletions(-) diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp index 5d4fac478d..aa8c751046 100644 --- a/core/fpdfapi/edit/cpdf_creator.cpp +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -619,10 +619,11 @@ void CPDF_Creator::InitID() { if (m_pEncryptDict) { ASSERT(m_pParser); if (m_pEncryptDict->GetStringFor("Filter") == "Standard") { - ByteString user_pass = m_pParser->GetPassword(); + m_pNewEncryptDict = ToDictionary(m_pEncryptDict->Clone()); + m_pEncryptDict = m_pNewEncryptDict.get(); m_pSecurityHandler = pdfium::MakeUnique(); - m_pSecurityHandler->OnCreate(m_pEncryptDict.Get(), m_pIDArray.get(), - user_pass); + m_pSecurityHandler->OnCreate(m_pNewEncryptDict.get(), m_pIDArray.get(), + m_pParser->GetPassword()); m_bSecurityChanged = true; } } @@ -666,6 +667,7 @@ void CPDF_Creator::RemoveSecurity() { m_pSecurityHandler.Reset(); m_bSecurityChanged = true; m_pEncryptDict = nullptr; + m_pNewEncryptDict.reset(); } CPDF_CryptoHandler* CPDF_Creator::GetCryptoHandler() { diff --git a/core/fpdfapi/edit/cpdf_creator.h b/core/fpdfapi/edit/cpdf_creator.h index 39e0950af6..96643c882f 100644 --- a/core/fpdfapi/edit/cpdf_creator.h +++ b/core/fpdfapi/edit/cpdf_creator.h @@ -75,7 +75,8 @@ class CPDF_Creator { UnownedPtr const m_pDocument; UnownedPtr const m_pParser; - UnownedPtr m_pEncryptDict; + UnownedPtr m_pEncryptDict; + std::unique_ptr m_pNewEncryptDict; fxcrt::MaybeOwned m_pSecurityHandler; UnownedPtr m_pMetadata; uint32_t m_dwLastObjNum; diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index 4d3835795c..16077fd39e 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -119,10 +119,6 @@ bool CPDF_Parser::IsObjectFree(uint32_t objnum) const { return GetObjectType(objnum) == ObjectType::kFree; } -void CPDF_Parser::SetEncryptDictionary(const CPDF_Dictionary* pDict) { - m_pEncryptDict = pDict ? ToDictionary(pDict->Clone()) : nullptr; -} - RetainPtr CPDF_Parser::GetFileAccess() const { return m_pSyntax->GetFileAccess(); } @@ -260,37 +256,24 @@ CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { if (!GetTrailer()) return FORMAT_ERROR; - const CPDF_Object* pEncryptObj = GetTrailer()->GetObjectFor("Encrypt"); - if (pEncryptObj) { - if (const CPDF_Dictionary* pEncryptDict = pEncryptObj->AsDictionary()) { - SetEncryptDictionary(pEncryptDict); - } else if (const CPDF_Reference* pRef = pEncryptObj->AsReference()) { - pEncryptObj = - m_pObjectsHolder->GetOrParseIndirectObject(pRef->GetRefObjNum()); - if (pEncryptObj) - SetEncryptDictionary(pEncryptObj->GetDict()); - } - } + const CPDF_Dictionary* pEncryptDict = GetEncryptDict(); + if (!pEncryptDict) + return SUCCESS; - if (m_pEncryptDict) { - ByteString filter = m_pEncryptDict->GetStringFor("Filter"); - if (filter != "Standard") - return HANDLER_ERROR; + if (pEncryptDict->GetStringFor("Filter") != "Standard") + return HANDLER_ERROR; - std::unique_ptr pSecurityHandler = - pdfium::MakeUnique(); - if (!pSecurityHandler->OnInit(m_pEncryptDict.get(), GetIDArray(), - m_Password)) - return PASSWORD_ERROR; + std::unique_ptr pSecurityHandler = + pdfium::MakeUnique(); + if (!pSecurityHandler->OnInit(pEncryptDict, GetIDArray(), m_Password)) + return PASSWORD_ERROR; - m_pSecurityHandler = std::move(pSecurityHandler); - } + m_pSecurityHandler = std::move(pSecurityHandler); return SUCCESS; } void CPDF_Parser::ReleaseEncryptHandler() { m_pSecurityHandler.reset(); - SetEncryptDictionary(nullptr); } // Ideally, all the cross reference entries should be verified. @@ -828,6 +811,24 @@ CPDF_Dictionary* CPDF_Parser::GetRoot() const { return obj ? obj->GetDict() : nullptr; } +const CPDF_Dictionary* CPDF_Parser::GetEncryptDict() const { + if (!GetTrailer()) + return nullptr; + + const CPDF_Object* pEncryptObj = GetTrailer()->GetObjectFor("Encrypt"); + if (!pEncryptObj) + return nullptr; + + if (pEncryptObj->IsDictionary()) + return ToDictionary(pEncryptObj); + + if (pEncryptObj->IsReference()) { + return ToDictionary(m_pObjectsHolder->GetOrParseIndirectObject( + pEncryptObj->AsReference()->GetRefObjNum())); + } + return nullptr; +} + const CPDF_Dictionary* CPDF_Parser::GetTrailer() const { return m_CrossRefTable->trailer(); } @@ -954,16 +955,7 @@ std::unique_ptr CPDF_Parser::LoadTrailerV4() { } uint32_t CPDF_Parser::GetPermissions() const { - if (!m_pSecurityHandler) - return 0xFFFFFFFF; - - uint32_t dwPermission = m_pSecurityHandler->GetPermissions(); - if (m_pEncryptDict && m_pEncryptDict->GetStringFor("Filter") == "Standard") { - // See PDF Reference 1.7, page 123, table 3.20. - dwPermission &= 0xFFFFFFFC; - dwPermission |= 0xFFFFF0C0; - } - return dwPermission; + return m_pSecurityHandler ? m_pSecurityHandler->GetPermissions() : 0xFFFFFFFF; } std::unique_ptr CPDF_Parser::ParseLinearizedHeader() { diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h index 92aaf7df6a..0af39d7529 100644 --- a/core/fpdfapi/parser/cpdf_parser.h +++ b/core/fpdfapi/parser/cpdf_parser.h @@ -78,7 +78,7 @@ class CPDF_Parser { const CPDF_Array* GetIDArray() const; CPDF_Dictionary* GetRoot() const; - CPDF_Dictionary* GetEncryptDict() const { return m_pEncryptDict.get(); } + const CPDF_Dictionary* GetEncryptDict() const; std::unique_ptr ParseIndirectObject(uint32_t objnum); @@ -141,7 +141,6 @@ class CPDF_Parser { Error LoadLinearizedMainXRefTable(); const CPDF_ObjectStream* GetObjectStream(uint32_t object_number); std::unique_ptr ParseLinearizedHeader(); - void SetEncryptDictionary(const CPDF_Dictionary* pDict); void ShrinkObjectMap(uint32_t size); // A simple check whether the cross reference table matches with // the objects. @@ -172,7 +171,6 @@ class CPDF_Parser { // m_CrossRefTable must be destroyed after m_pSecurityHandler due to the // ownership of the ID array data. std::unique_ptr m_CrossRefTable; - std::unique_ptr m_pEncryptDict; FX_FILESIZE m_LastXRefOffset; std::unique_ptr m_pSecurityHandler; ByteString m_Password; diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp index eeba53ef34..caa82a9ddd 100644 --- a/core/fpdfapi/parser/cpdf_security_handler.cpp +++ b/core/fpdfapi/parser/cpdf_security_handler.cpp @@ -119,7 +119,13 @@ bool CPDF_SecurityHandler::CheckSecurity(const ByteString& password) { } uint32_t CPDF_SecurityHandler::GetPermissions() const { - return m_bOwnerUnlocked ? 0xFFFFFFFF : m_Permissions; + uint32_t dwPermission = m_bOwnerUnlocked ? 0xFFFFFFFF : m_Permissions; + if (m_pEncryptDict && m_pEncryptDict->GetStringFor("Filter") == "Standard") { + // See PDF Reference 1.7, page 123, table 3.20. + dwPermission &= 0xFFFFFFFC; + dwPermission |= 0xFFFFF0C0; + } + return dwPermission; } static bool LoadCryptInfo(const CPDF_Dictionary* pEncryptDict, diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp index 5fdc82af73..c44d582fd0 100644 --- a/fpdfsdk/fpdf_view.cpp +++ b/fpdfsdk/fpdf_view.cpp @@ -313,7 +313,7 @@ FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) { if (!pDoc || !pDoc->GetParser()) return -1; - CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict(); + const CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict(); return pDict ? pDict->GetIntegerFor("R") : -1; } -- cgit v1.2.3