Add CPDF_Dictionary::GetMutableDirectObjectFor().

Change-Id: Ib31aa06d814d93790d7a662983aac6278aa9b738
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94671
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_type3font.cpp b/core/fpdfapi/font/cpdf_type3font.cpp
index 8610d1e..a5ca94e 100644
--- a/core/fpdfapi/font/cpdf_type3font.cpp
+++ b/core/fpdfapi/font/cpdf_type3font.cpp
@@ -117,14 +117,15 @@
   if (!m_pCharProcs)
     return nullptr;
 
-  CPDF_Stream* pStream = ToStream(m_pCharProcs->GetDirectObjectFor(name));
+  RetainPtr<CPDF_Stream> pStream =
+      ToStream(m_pCharProcs->GetMutableDirectObjectFor(name));
   if (!pStream)
     return nullptr;
 
   std::unique_ptr<CPDF_Font::FormIface> pForm = m_pFormFactory->CreateForm(
       m_pDocument.Get(),
       m_pFontResources ? m_pFontResources.Get() : m_pPageResources.Get(),
-      pStream);
+      pStream.Get());
 
   auto pNewChar = std::make_unique<CPDF_Type3Char>();
 
diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp
index 2fed936..bf20c2c 100644
--- a/core/fpdfapi/page/cpdf_contentparser.cpp
+++ b/core/fpdfapi/page/cpdf_contentparser.cpp
@@ -33,8 +33,8 @@
     return;
   }
 
-  CPDF_Object* pContent =
-      pPage->GetDict()->GetDirectObjectFor(pdfium::page_object::kContents);
+  RetainPtr<CPDF_Object> pContent = pPage->GetDict()->GetMutableDirectObjectFor(
+      pdfium::page_object::kContents);
   if (!pContent) {
     HandlePageContentFailure();
     return;
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 9cc2ed6..dce3dde 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -624,7 +624,7 @@
     }
   }
   ReplaceAbbr(pDict.Get());
-  CPDF_Object* pCSObj = nullptr;
+  const CPDF_Object* pCSObj = nullptr;
   if (pDict->KeyExist("ColorSpace")) {
     pCSObj = pDict->GetDirectObjectFor("ColorSpace");
     if (pCSObj->IsName()) {
@@ -1129,10 +1129,11 @@
   return m_pPageResources->GetMutableDictFor(type).Get();
 }
 
+// TODO(tsepez): return retained reference.
 CPDF_Object* CPDF_StreamContentParser::FindResourceObj(const ByteString& type,
                                                        const ByteString& name) {
   CPDF_Dictionary* pHolder = FindResourceHolder(type);
-  return pHolder ? pHolder->GetDirectObjectFor(name) : nullptr;
+  return pHolder ? pHolder->GetMutableDirectObjectFor(name).Get() : nullptr;
 }
 
 RetainPtr<CPDF_Font> CPDF_StreamContentParser::FindFont(
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index 333108b..5a9d57c 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -140,7 +140,7 @@
 
   ByteString decoder;
   const CPDF_Dictionary* pParam = nullptr;
-  CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
+  const CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
   if (pFilter) {
     const CPDF_Array* pArray = pFilter->AsArray();
     if (pArray) {
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index 56d1e53..9c0eea5 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -99,9 +99,9 @@
   return p ? p->GetDirect() : nullptr;
 }
 
-CPDF_Object* CPDF_Dictionary::GetDirectObjectFor(const ByteString& key) {
-  return const_cast<CPDF_Object*>(
-      static_cast<const CPDF_Dictionary*>(this)->GetDirectObjectFor(key));
+RetainPtr<CPDF_Object> CPDF_Dictionary::GetMutableDirectObjectFor(
+    const ByteString& key) {
+  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetDirectObjectFor(key)));
 }
 
 ByteString CPDF_Dictionary::GetStringFor(const ByteString& key) const {
@@ -179,7 +179,7 @@
 }
 
 CPDF_Stream* CPDF_Dictionary::GetStreamFor(const ByteString& key) {
-  return ToStream(GetDirectObjectFor(key));
+  return ToStream(GetMutableDirectObjectFor(key)).Get();
 }
 
 CFX_FloatRect CPDF_Dictionary::GetRectFor(const ByteString& key) const {
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index 7f187b7..c868816 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -48,8 +48,9 @@
   size_t size() const { return m_Map.size(); }
   const CPDF_Object* GetObjectFor(const ByteString& key) const;
   CPDF_Object* GetObjectFor(const ByteString& key);
+
   const CPDF_Object* GetDirectObjectFor(const ByteString& key) const;
-  CPDF_Object* GetDirectObjectFor(const ByteString& key);
+  RetainPtr<CPDF_Object> GetMutableDirectObjectFor(const ByteString& key);
 
   // These will return the string representation of the object specified by
   // |key|, for any object type that has a string representation.
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 6298e4e..30be451 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -1001,7 +1001,7 @@
   CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
   dict->ConvertToIndirectObjectFor("clams", &objects_holder);
   CPDF_Object* pRef = dict->GetObjectFor("clams");
-  CPDF_Object* pNum = dict->GetDirectObjectFor("clams");
+  const CPDF_Object* pNum = dict->GetDirectObjectFor("clams");
   EXPECT_TRUE(pRef->IsReference());
   EXPECT_TRUE(pNum->IsNumber());
   EXPECT_NE(pObj, pRef);
diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp
index f69ed17..8581e56 100644
--- a/core/fpdfapi/render/cpdf_imagerenderer.cpp
+++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp
@@ -143,9 +143,9 @@
     pDocument = m_pImageObject->GetImage()->GetDocument();
   }
   CPDF_Dictionary* pPageResources = pPage ? pPage->GetPageResources() : nullptr;
-  CPDF_Object* pCSObj =
-      m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor(
-          "ColorSpace");
+  CPDF_Dictionary* pStreamDict =
+      m_pImageObject->GetImage()->GetStream()->GetDict();
+  const CPDF_Object* pCSObj = pStreamDict->GetDirectObjectFor("ColorSpace");
   auto* pData = CPDF_DocPageData::FromDocument(pDocument);
   RetainPtr<CPDF_ColorSpace> pColorSpace =
       pData->GetColorSpace(pCSObj, pPageResources);
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index fa6d59b..0165c9d 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -72,9 +72,10 @@
   if (bFallbackToNormal && !pAP->KeyExist(ap_entry))
     ap_entry = "N";
 
-  CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry);
+  RetainPtr<CPDF_Object> psub = pAP->GetMutableDirectObjectFor(ap_entry);
   if (!psub)
     return nullptr;
+
   if (CPDF_Stream* pStream = psub->AsStream())
     return pStream;
 
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 7e636fa..b0b5ee4 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -823,14 +823,14 @@
     if (pParent && pParent != pFieldDict &&
         !pParent->KeyExist(pdfium::form_fields::kFT)) {
       if (pFieldDict->KeyExist(pdfium::form_fields::kFT)) {
-        CPDF_Object* pFTValue =
+        const CPDF_Object* pFTValue =
             pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFT);
         if (pFTValue)
           pParent->SetFor(pdfium::form_fields::kFT, pFTValue->Clone());
       }
 
       if (pFieldDict->KeyExist(pdfium::form_fields::kFf)) {
-        CPDF_Object* pFfValue =
+        const CPDF_Object* pFfValue =
             pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFf);
         if (pFfValue)
           pParent->SetFor(pdfium::form_fields::kFf, pFfValue->Clone());
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 37d7fee..6a50e4e 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -371,7 +371,7 @@
       pDoc->GetRoot()->GetMutableDictFor("Dests");
   if (!pDests)
     return nullptr;
-  return GetNamedDestFromObject(pDests->GetDirectObjectFor(name));
+  return GetNamedDestFromObject(pDests->GetMutableDirectObjectFor(name).Get());
 }
 
 }  // namespace
diff --git a/fpdfsdk/fpdf_editimg.cpp b/fpdfsdk/fpdf_editimg.cpp
index 77bc238..8ee8b53 100644
--- a/fpdfsdk/fpdf_editimg.cpp
+++ b/fpdfsdk/fpdf_editimg.cpp
@@ -307,8 +307,9 @@
   if (!pImg)
     return 0;
 
-  CPDF_Dictionary* pDict = pImg->GetDict();
-  CPDF_Object* pFilter = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr;
+  const CPDF_Dictionary* pDict = pImg->GetDict();
+  const CPDF_Object* pFilter =
+      pDict ? pDict->GetDirectObjectFor("Filter") : nullptr;
   if (!pFilter)
     return 0;
 
@@ -330,13 +331,11 @@
     return 0;
 
   CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
-  CPDF_Object* pFilter =
-      pObj->AsImage()->GetImage()->GetDict()->GetDirectObjectFor("Filter");
-  ByteString bsFilter;
-  if (pFilter->IsName())
-    bsFilter = pFilter->AsName()->GetString();
-  else
-    bsFilter = pFilter->AsArray()->GetStringAt(index);
+  const CPDF_Dictionary* pDict = pObj->AsImage()->GetImage()->GetDict();
+  const CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
+  ByteString bsFilter = pFilter->IsName()
+                            ? pFilter->AsName()->GetString()
+                            : pFilter->AsArray()->GetStringAt(index);
 
   return NulTerminateMaybeCopyAndReturnLength(bsFilter, buffer, buflen);
 }
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index d8709a9..ce9cadd 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -61,8 +61,8 @@
   return true;
 }
 
-CPDF_Object* GetPageContent(CPDF_Dictionary* pPageDict) {
-  return pPageDict->GetDirectObjectFor(pdfium::page_object::kContents);
+RetainPtr<CPDF_Object> GetPageContent(CPDF_Dictionary* pPageDict) {
+  return pPageDict->GetMutableDirectObjectFor(pdfium::page_object::kContents);
 }
 
 void OutputPath(fxcrt::ostringstream& buf, CPDF_Path path) {
@@ -209,7 +209,7 @@
     return false;
 
   CPDF_Dictionary* pPageDict = pPage->GetDict();
-  CPDF_Object* pContentObj = GetPageContent(pPageDict);
+  RetainPtr<CPDF_Object> pContentObj = GetPageContent(pPageDict);
   if (!pContentObj)
     return false;
 
@@ -242,7 +242,8 @@
       pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>());
   pEndStream->SetData(ByteStringView(" Q").raw_span());
 
-  if (CPDF_Array* pContentArray = ToArray(pContentObj)) {
+  RetainPtr<CPDF_Array> pContentArray = ToArray(pContentObj);
+  if (pContentArray) {
     pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
     pContentArray->AppendNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
   } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
@@ -386,7 +387,7 @@
     return;
 
   CPDF_Dictionary* pPageDict = pPage->GetDict();
-  CPDF_Object* pContentObj = GetPageContent(pPageDict);
+  RetainPtr<CPDF_Object> pContentObj = GetPageContent(pPageDict);
   if (!pContentObj)
     return;
 
@@ -415,7 +416,8 @@
       pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>());
   pStream->SetDataFromStringstream(&strClip);
 
-  if (CPDF_Array* pArray = ToArray(pContentObj)) {
+  RetainPtr<CPDF_Array> pArray = ToArray(pContentObj);
+  if (pArray) {
     pArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
   } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
     CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();