Add CPDF_Array::GetMutableDirectObjectAt().

Change-Id: Iea5c66e4533778f43cdb4b4ca5d76e22b58ff9dc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94510
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index bda93d6..8d5dd1b 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -113,9 +113,8 @@
   return m_Objects[index].Get();
 }
 
-CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t index) {
-  CPDF_Object* pObj = GetObjectAt(index);
-  return pObj ? pObj->GetDirect() : nullptr;
+RetainPtr<CPDF_Object> CPDF_Array::GetMutableDirectObjectAt(size_t index) {
+  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetDirectObjectAt(index)));
 }
 
 const CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t index) const {
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
index e039cd7..201a2a1 100644
--- a/core/fpdfapi/parser/cpdf_array.h
+++ b/core/fpdfapi/parser/cpdf_array.h
@@ -48,10 +48,10 @@
   CPDF_Object* GetObjectAt(size_t index);
   const CPDF_Object* GetObjectAt(size_t index) const;
 
-  // The GetDirectObjectAt() methods tolerate out-of-bounds indices and
+  // The Get*DirectObjectAt() methods tolerate out-of-bounds indices and
   // return nullptr in those cases. Furthermore, for reference objects that
   // do not correspond to a valid indirect object, nullptr is returned.
-  CPDF_Object* GetDirectObjectAt(size_t index);
+  RetainPtr<CPDF_Object> GetMutableDirectObjectAt(size_t index);
   const CPDF_Object* GetDirectObjectAt(size_t index) const;
 
   // The Get*At() methods tolerate out-of-bounds indices and return nullptr
diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h
index 864bbb2..c801a9a 100644
--- a/core/fpdfapi/parser/cpdf_number.h
+++ b/core/fpdfapi/parser/cpdf_number.h
@@ -49,4 +49,8 @@
   return obj ? obj->AsNumber() : nullptr;
 }
 
+inline RetainPtr<CPDF_Number> ToNumber(RetainPtr<CPDF_Object> obj) {
+  return RetainPtr<CPDF_Number>(ToNumber(obj.Get()));
+}
+
 #endif  // CORE_FPDFAPI_PARSER_CPDF_NUMBER_H_
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index cbb3ebf..ebf69a7 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -180,7 +180,8 @@
   bool bRegenerateAP =
       pAcroForm && pAcroForm->GetBooleanFor("NeedAppearances", false);
   for (size_t i = 0; i < pAnnots->size(); ++i) {
-    CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
+    RetainPtr<CPDF_Dictionary> pDict =
+        ToDictionary(pAnnots->GetMutableDirectObjectAt(i));
     if (!pDict)
       continue;
     const ByteString subtype =
@@ -192,11 +193,11 @@
     }
     pAnnots->ConvertToIndirectObjectAt(i, m_pDocument.Get());
     m_AnnotList.push_back(
-        std::make_unique<CPDF_Annot>(pDict, m_pDocument.Get()));
+        std::make_unique<CPDF_Annot>(pDict.Get(), m_pDocument.Get()));
     if (bRegenerateAP && subtype == "Widget" &&
         CPDF_InteractiveForm::IsUpdateAPEnabled() &&
         !pDict->GetDictFor(pdfium::annotation::kAP)) {
-      GenerateAP(m_pDocument.Get(), pDict);
+      GenerateAP(m_pDocument.Get(), pDict.Get());
     }
   }
 
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 539b0fd..f95e15c 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -172,7 +172,7 @@
 // will be the index of |csName| in |ppFind|. If |csName| is not found, |ppFind|
 // will be the leaf array that |csName| should be added to, and |pFindIndex|
 // will be the index that it should be added at.
-CPDF_Object* SearchNameNodeByNameInternal(
+RetainPtr<CPDF_Object> SearchNameNodeByNameInternal(
     const RetainPtr<CPDF_Dictionary>& pNode,
     const WideString& csName,
     int nLevel,
@@ -219,7 +219,7 @@
         continue;
 
       *nIndex += i;
-      return pNames->GetDirectObjectAt(i * 2 + 1);
+      return pNames->GetMutableDirectObjectAt(i * 2 + 1);
     }
     *nIndex += dwCount;
     return nullptr;
@@ -235,7 +235,7 @@
     if (!pKid)
       continue;
 
-    CPDF_Object* pFound = SearchNameNodeByNameInternal(
+    RetainPtr<CPDF_Object> pFound = SearchNameNodeByNameInternal(
         pKid, csName, nLevel + 1, nIndex, ppFind, pFindIndex);
     if (pFound)
       return pFound;
@@ -245,10 +245,11 @@
 
 // Wrapper for SearchNameNodeByNameInternal() so callers do not need to know
 // about the details.
-CPDF_Object* SearchNameNodeByName(const RetainPtr<CPDF_Dictionary>& pNode,
-                                  const WideString& csName,
-                                  RetainPtr<CPDF_Array>* ppFind,
-                                  int* pFindIndex) {
+RetainPtr<CPDF_Object> SearchNameNodeByName(
+    const RetainPtr<CPDF_Dictionary>& pNode,
+    const WideString& csName,
+    RetainPtr<CPDF_Array>* ppFind,
+    int* pFindIndex) {
   size_t nIndex = 0;
   return SearchNameNodeByNameInternal(pNode, csName, 0, &nIndex, ppFind,
                                       pFindIndex);
@@ -257,7 +258,7 @@
 struct IndexSearchResult {
   // For the n-th object in a tree, the key and value.
   WideString key;
-  CPDF_Object* value;
+  RetainPtr<CPDF_Object> value;
   // The leaf node that holds `key` and `value`.
   CPDF_Array* container;
   // The index for `key` in `container`. Must be even.
@@ -284,13 +285,13 @@
     }
 
     size_t index = 2 * (nTargetPairIndex - *nCurPairIndex);
-    CPDF_Object* value = pNames->GetDirectObjectAt(index + 1);
+    RetainPtr<CPDF_Object> value = pNames->GetMutableDirectObjectAt(index + 1);
     if (!value)
       return absl::nullopt;
 
     IndexSearchResult result;
     result.key = pNames->GetUnicodeTextAt(index);
-    result.value = value;
+    result.value = std::move(value);
     result.container = pNames;
     result.index = index;
     return result;
@@ -532,13 +533,15 @@
   }
 
   *csName = std::move(result.value().key);
-  return result.value().value;
+  return result.value().value.Get();
 }
 
-CPDF_Object* CPDF_NameTree::LookupValue(const WideString& csName) const {
+RetainPtr<CPDF_Object> CPDF_NameTree::LookupValue(
+    const WideString& csName) const {
   return SearchNameNodeByName(m_pRoot, csName, nullptr, nullptr);
 }
 
 CPDF_Array* CPDF_NameTree::LookupNewStyleNamedDest(const ByteString& sName) {
-  return GetNamedDestFromObject(LookupValue(PDF_DecodeText(sName.raw_span())));
+  return GetNamedDestFromObject(
+      LookupValue(PDF_DecodeText(sName.raw_span())).Get());
 }
diff --git a/core/fpdfdoc/cpdf_nametree.h b/core/fpdfdoc/cpdf_nametree.h
index e27f5b1..140cadb 100644
--- a/core/fpdfdoc/cpdf_nametree.h
+++ b/core/fpdfdoc/cpdf_nametree.h
@@ -45,7 +45,7 @@
   bool DeleteValueAndName(size_t nIndex);
 
   CPDF_Object* LookupValueAndName(size_t nIndex, WideString* csName) const;
-  CPDF_Object* LookupValue(const WideString& csName) const;
+  RetainPtr<CPDF_Object> LookupValue(const WideString& csName) const;
 
   size_t GetCount() const;
   CPDF_Dictionary* GetRootForTesting() const { return m_pRoot.Get(); }
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
index 3b9fa3b..9add6d3 100644
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
@@ -120,7 +120,7 @@
   EXPECT_STREQ(L"1", stored_name.c_str());
 
   // Check that the correct value object can be obtained by looking up "1".
-  const CPDF_Number* pNumber = ToNumber(name_tree->LookupValue(L"1"));
+  RetainPtr<CPDF_Number> pNumber = ToNumber(name_tree->LookupValue(L"1"));
   ASSERT_TRUE(pNumber);
   EXPECT_EQ(100, pNumber->GetInteger());
 }
@@ -142,7 +142,7 @@
   std::unique_ptr<CPDF_NameTree> name_tree =
       CPDF_NameTree::CreateForTesting(pRootDict.Get());
 
-  const CPDF_Number* pNumber = ToNumber(name_tree->LookupValue(L"9.txt"));
+  RetainPtr<CPDF_Number> pNumber = ToNumber(name_tree->LookupValue(L"9.txt"));
   ASSERT_TRUE(pNumber);
   EXPECT_EQ(999, pNumber->GetInteger());
   CheckLimitsArray(pKid1.Get(), "1.txt", "9.txt");
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 131ffc0..9cb2396 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -375,12 +375,13 @@
   if (!pAnnots || static_cast<size_t>(index) >= pAnnots->size())
     return nullptr;
 
-  CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index));
+  RetainPtr<CPDF_Dictionary> pDict =
+      ToDictionary(pAnnots->GetMutableDirectObjectAt(index));
   if (!pDict)
     return nullptr;
 
-  auto pNewAnnot =
-      std::make_unique<CPDF_AnnotContext>(pDict, IPDFPageFromFPDFPage(page));
+  auto pNewAnnot = std::make_unique<CPDF_AnnotContext>(
+      pDict.Get(), IPDFPageFromFPDFPage(page));
 
   // Caller takes ownership.
   return FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release());
diff --git a/fpdfsdk/fpdf_doc.cpp b/fpdfsdk/fpdf_doc.cpp
index 8bbb761..322e1b4 100644
--- a/fpdfsdk/fpdf_doc.cpp
+++ b/fpdfsdk/fpdf_doc.cpp
@@ -370,12 +370,13 @@
   if (!pAnnots)
     return false;
   for (size_t i = *start_pos; i < pAnnots->size(); i++) {
-    CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
+    RetainPtr<CPDF_Dictionary> pDict =
+        ToDictionary(pAnnots->GetMutableDirectObjectAt(i));
     if (!pDict)
       continue;
     if (pDict->GetStringFor("Subtype") == "Link") {
       *start_pos = static_cast<int>(i + 1);
-      *link_annot = FPDFLinkFromCPDFDictionary(pDict);
+      *link_annot = FPDFLinkFromCPDFDictionary(pDict.Get());
       return true;
     }
   }
diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp
index 691248d..df5be9d 100644
--- a/xfa/fxfa/cxfa_ffdoc.cpp
+++ b/xfa/fxfa/cxfa_ffdoc.cpp
@@ -279,7 +279,7 @@
   if (count == 0)
     return nullptr;
 
-  CPDF_Object* pObject = name_tree->LookupValue(WideString(wsName));
+  RetainPtr<CPDF_Object> pObject = name_tree->LookupValue(WideString(wsName));
   if (!pObject) {
     for (size_t i = 0; i < count; ++i) {
       WideString wsTemp;
@@ -291,11 +291,11 @@
     }
   }
 
-  CPDF_Stream* pStream = ToStream(pObject);
+  RetainPtr<CPDF_Stream> pStream = ToStream(pObject);
   if (!pStream)
     return nullptr;
 
-  auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
+  auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream.Get());
   pAcc->LoadAllDataFiltered();
 
   auto pImageFileRead =