Add CPDF_Dictionary::GetMutableObject()

Change-Id: Ib22a45f570c5b581f65127c687da83d16b81e19d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94711
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
index 9f8832f..da37120 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
@@ -6,6 +6,7 @@
 
 #include <map>
 #include <numeric>
+#include <utility>
 #include <vector>
 
 #include "core/fpdfapi/page/cpdf_pageobject.h"
@@ -23,14 +24,15 @@
     const CPDF_PageObjectHolder* obj_holder)
     : obj_holder_(obj_holder), doc_(obj_holder_->GetDocument()) {
   CPDF_Dictionary* page_dict = obj_holder_->GetDict();
-  CPDF_Object* contents_obj = page_dict->GetObjectFor("Contents");
-  CPDF_Array* contents_array = ToArray(contents_obj);
+  RetainPtr<CPDF_Object> contents_obj =
+      page_dict->GetMutableObjectFor("Contents");
+  RetainPtr<CPDF_Array> contents_array = ToArray(contents_obj);
   if (contents_array) {
-    contents_array_.Reset(contents_array);
+    contents_array_ = std::move(contents_array);
     return;
   }
 
-  CPDF_Reference* contents_reference = ToReference(contents_obj);
+  RetainPtr<CPDF_Reference> contents_reference = ToReference(contents_obj);
   if (contents_reference) {
     CPDF_Object* indirect_obj = contents_reference->GetDirect();
     if (!indirect_obj)
@@ -38,7 +40,7 @@
 
     contents_array = indirect_obj->AsArray();
     if (contents_array)
-      contents_array_.Reset(contents_array);
+      contents_array_ = std::move(contents_array);
     else if (indirect_obj->IsStream())
       contents_stream_.Reset(indirect_obj->AsStream());
   }
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 4f08c30..cf17395 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -35,17 +35,18 @@
 
 namespace {
 
-// static
-CPDF_Object* GetResourceObject(CPDF_Dictionary* pDict) {
+RetainPtr<CPDF_Object> GetResourceObject(CPDF_Dictionary* pDict) {
   constexpr size_t kMaxHierarchyDepth = 64;
   size_t depth = 0;
 
-  CPDF_Dictionary* dictionary_to_check = pDict;
+  RetainPtr<CPDF_Dictionary> dictionary_to_check(pDict);
   while (dictionary_to_check) {
-    CPDF_Object* result = dictionary_to_check->GetObjectFor("Resources");
+    RetainPtr<CPDF_Object> result =
+        dictionary_to_check->GetMutableObjectFor("Resources");
     if (result)
       return result;
-    CPDF_Object* parent = dictionary_to_check->GetObjectFor("Parent");
+    RetainPtr<CPDF_Object> parent =
+        dictionary_to_check->GetMutableObjectFor("Parent");
     dictionary_to_check = parent ? parent->GetDict() : nullptr;
 
     if (++depth > kMaxHierarchyDepth) {
@@ -599,7 +600,7 @@
   }
 
   pPageNode->m_type = PageNode::Type::kPages;
-  CPDF_Object* pKids = pDict->GetObjectFor("Kids");
+  RetainPtr<CPDF_Object> pKids = pDict->GetMutableObjectFor("Kids");
   if (!pKids) {
     m_internalStatus = InternalStatus::kPage;
     return true;
@@ -891,7 +892,7 @@
     CPDF_Dictionary* page) {
   DCHECK(page);
   CPDF_ReadValidator::ScopedSession read_session(GetValidator());
-  CPDF_Object* resources = GetResourceObject(page);
+  RetainPtr<CPDF_Object> resources = GetResourceObject(page);
   if (GetValidator()->has_read_problems())
     return kDataNotAvailable;
 
@@ -901,8 +902,9 @@
   CPDF_PageObjectAvail* resource_avail =
       m_PagesResourcesAvail
           .insert(std::make_pair(
-              resources, std::make_unique<CPDF_PageObjectAvail>(
-                             GetValidator(), m_pDocument.Get(), resources)))
+              resources,
+              std::make_unique<CPDF_PageObjectAvail>(
+                  GetValidator(), m_pDocument.Get(), resources.Get())))
           .first->second.get();
   return resource_avail->CheckAvail();
 }
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index 236fbe2..56fec86 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -88,9 +88,9 @@
   return it != m_Map.end() ? it->second.Get() : nullptr;
 }
 
-CPDF_Object* CPDF_Dictionary::GetObjectFor(const ByteString& key) {
-  return const_cast<CPDF_Object*>(
-      static_cast<const CPDF_Dictionary*>(this)->GetObjectFor(key));
+RetainPtr<CPDF_Object> CPDF_Dictionary::GetMutableObjectFor(
+    const ByteString& key) {
+  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetObjectFor(key)));
 }
 
 const CPDF_Object* CPDF_Dictionary::GetDirectObjectFor(
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index 8d54406..4d73fb0 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -47,7 +47,7 @@
 
   size_t size() const { return m_Map.size(); }
   const CPDF_Object* GetObjectFor(const ByteString& key) const;
-  CPDF_Object* GetObjectFor(const ByteString& key);
+  RetainPtr<CPDF_Object> GetMutableObjectFor(const ByteString& key);
 
   const CPDF_Object* GetDirectObjectFor(const ByteString& key) const;
   RetainPtr<CPDF_Object> GetMutableDirectObjectFor(const ByteString& key);
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp
index 3445e90..36cfa2e 100644
--- a/core/fpdfapi/parser/cpdf_hint_tables.cpp
+++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp
@@ -441,7 +441,7 @@
     return false;
 
   CPDF_Dictionary* pDict = pHintStream->GetDict();
-  CPDF_Object* pOffset = pDict ? pDict->GetObjectFor("S") : nullptr;
+  const CPDF_Object* pOffset = pDict ? pDict->GetObjectFor("S") : nullptr;
   if (!pOffset || !pOffset->IsNumber())
     return false;
 
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 30be451..2cd551b 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -916,7 +916,7 @@
   auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234);
   ASSERT_EQ(1U, dict->size());
-  CPDF_Object* obj = dict->GetObjectFor("foo");
+  const CPDF_Object* obj = dict->GetObjectFor("foo");
   ASSERT_TRUE(obj);
   EXPECT_TRUE(obj->IsReference());
 
@@ -927,7 +927,7 @@
   RetainPtr<CPDF_Dictionary> cloned_dict =
       ToDictionary(std::move(cloned_dict_object));
   ASSERT_EQ(0U, cloned_dict->size());
-  CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
+  const CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
   EXPECT_FALSE(cloned_obj);
 }
 
@@ -985,7 +985,7 @@
         ToDictionary(dict_obj->CloneDirectObject());
     // Cloned object should be the same as the original.
     ASSERT_TRUE(cloned_dict);
-    CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr");
+    const CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr");
     ASSERT_TRUE(cloned_arr);
     ASSERT_TRUE(cloned_arr->IsArray());
     EXPECT_EQ(0U, cloned_arr->AsArray()->size());
@@ -1000,7 +1000,7 @@
   auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
   CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
   dict->ConvertToIndirectObjectFor("clams", &objects_holder);
-  CPDF_Object* pRef = dict->GetObjectFor("clams");
+  const CPDF_Object* pRef = dict->GetObjectFor("clams");
   const CPDF_Object* pNum = dict->GetDirectObjectFor("clams");
   EXPECT_TRUE(pRef->IsReference());
   EXPECT_TRUE(pNum->IsNumber());
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 2d0f4ae..391a3f8 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -269,7 +269,7 @@
       return eRet;
   }
   if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
-    CPDF_Reference* pMetadata =
+    const CPDF_Reference* pMetadata =
         ToReference(GetRoot()->GetObjectFor("Metadata"));
     if (pMetadata)
       m_MetadataObjnum = pMetadata->GetRefObjNum();
@@ -1086,8 +1086,9 @@
   }
 
   if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
-    if (CPDF_Reference* pMetadata =
-            ToReference(GetRoot()->GetObjectFor("Metadata")))
+    const CPDF_Reference* pMetadata =
+        ToReference(GetRoot()->GetObjectFor("Metadata"));
+    if (pMetadata)
       m_MetadataObjnum = pMetadata->GetRefObjNum();
   }
   return SUCCESS;
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index b998a6f..601c2cd 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -840,7 +840,7 @@
 
     auto newField = std::make_unique<CPDF_FormField>(this, pParent.Get());
     pField = newField.get();
-    CPDF_Object* pTObj = pDict->GetObjectFor(pdfium::form_fields::kT);
+    const CPDF_Object* pTObj = pDict->GetObjectFor(pdfium::form_fields::kT);
     if (ToReference(pTObj)) {
       RetainPtr<CPDF_Object> pClone = pTObj->CloneDirectObject();
       if (pClone)
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index e93f125..cfe9fdd 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -145,7 +145,7 @@
     return FPDF_OBJECT_UNKNOWN;
 
   CPDF_FileSpec spec(CPDFObjectFromFPDFAttachment(attachment));
-  CPDF_Object* pObj = spec.GetParamsDict()->GetObjectFor(key);
+  const CPDF_Object* pObj = spec.GetParamsDict()->GetObjectFor(key);
   return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN;
 }
 
@@ -187,7 +187,8 @@
   ByteString bsKey = key;
   WideString value = pParamsDict->GetUnicodeTextFor(bsKey);
   if (bsKey == kChecksumKey && !value.IsEmpty()) {
-    CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString();
+    const CPDF_String* stringValue =
+        pParamsDict->GetObjectFor(bsKey)->AsString();
     if (stringValue->IsHex()) {
       ByteString encoded =
           PDF_HexEncodeString(stringValue->GetString().AsStringView());
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index 7c60121..934cff4 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -264,7 +264,7 @@
   if (cbRootType.IsEmpty())
     pNewRoot->SetNewFor<CPDF_Name>("Type", "Catalog");
 
-  CPDF_Object* pElement = pNewRoot->GetObjectFor("Pages");
+  RetainPtr<CPDF_Object> pElement = pNewRoot->GetMutableObjectFor("Pages");
   CPDF_Dictionary* pNewPages =
       pElement ? ToDictionary(pElement->GetDirect()) : nullptr;
   if (!pNewPages) {
diff --git a/fpdfsdk/fpdf_save.cpp b/fpdfsdk/fpdf_save.cpp
index e64e0af..e6606fb 100644
--- a/fpdfsdk/fpdf_save.cpp
+++ b/fpdfsdk/fpdf_save.cpp
@@ -54,7 +54,7 @@
   if (!pAcroForm)
     return false;
 
-  CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
+  RetainPtr<CPDF_Object> pXFA = pAcroForm->GetMutableObjectFor("XFA");
   if (!pXFA)
     return true;