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 <thestig@chromium.org>
Commit-Queue: Art Snake <art-snake@yandex-team.ru>
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index 5d4fac4..aa8c751 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -619,10 +619,11 @@
   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<CPDF_SecurityHandler>();
-      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 @@
   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 39e0950..96643c8 100644
--- a/core/fpdfapi/edit/cpdf_creator.h
+++ b/core/fpdfapi/edit/cpdf_creator.h
@@ -75,7 +75,8 @@
 
   UnownedPtr<CPDF_Document> const m_pDocument;
   UnownedPtr<const CPDF_Parser> const m_pParser;
-  UnownedPtr<CPDF_Dictionary> m_pEncryptDict;
+  UnownedPtr<const CPDF_Dictionary> m_pEncryptDict;
+  std::unique_ptr<CPDF_Dictionary> m_pNewEncryptDict;
   fxcrt::MaybeOwned<CPDF_SecurityHandler> m_pSecurityHandler;
   UnownedPtr<const CPDF_Object> m_pMetadata;
   uint32_t m_dwLastObjNum;
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 4d38357..16077fd 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -119,10 +119,6 @@
   return GetObjectType(objnum) == ObjectType::kFree;
 }
 
-void CPDF_Parser::SetEncryptDictionary(const CPDF_Dictionary* pDict) {
-  m_pEncryptDict = pDict ? ToDictionary(pDict->Clone()) : nullptr;
-}
-
 RetainPtr<IFX_SeekableReadStream> CPDF_Parser::GetFileAccess() const {
   return m_pSyntax->GetFileAccess();
 }
@@ -260,37 +256,24 @@
   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<CPDF_SecurityHandler> pSecurityHandler =
-        pdfium::MakeUnique<CPDF_SecurityHandler>();
-    if (!pSecurityHandler->OnInit(m_pEncryptDict.get(), GetIDArray(),
-                                  m_Password))
-      return PASSWORD_ERROR;
+  std::unique_ptr<CPDF_SecurityHandler> pSecurityHandler =
+      pdfium::MakeUnique<CPDF_SecurityHandler>();
+  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 @@
   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 @@
 }
 
 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_LinearizedHeader> CPDF_Parser::ParseLinearizedHeader() {
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 92aaf7d..0af39d7 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -78,7 +78,7 @@
   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<CPDF_Object> ParseIndirectObject(uint32_t objnum);
 
@@ -141,7 +141,6 @@
   Error LoadLinearizedMainXRefTable();
   const CPDF_ObjectStream* GetObjectStream(uint32_t object_number);
   std::unique_ptr<CPDF_LinearizedHeader> 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 @@
   // m_CrossRefTable must be destroyed after m_pSecurityHandler due to the
   // ownership of the ID array data.
   std::unique_ptr<CPDF_CrossRefTable> m_CrossRefTable;
-  std::unique_ptr<CPDF_Dictionary> m_pEncryptDict;
   FX_FILESIZE m_LastXRefOffset;
   std::unique_ptr<CPDF_SecurityHandler> m_pSecurityHandler;
   ByteString m_Password;
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index eeba53e..caa82a9 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -119,7 +119,13 @@
 }
 
 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 5fdc82a..c44d582 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -313,7 +313,7 @@
   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;
 }