Return more retained objects from CPDF_Array getters.

Change-Id: I4cd80b1e62e586ebc32cbe25ca2f3282a1909acb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97530
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index 530f73a..6c05051 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -566,7 +566,8 @@
 
   m_pIDArray = pdfium::MakeRetain<CPDF_Array>();
   const CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : nullptr;
-  const CPDF_Object* pID1 = pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr;
+  RetainPtr<const CPDF_Object> pID1 =
+      pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr;
   if (pID1) {
     m_pIDArray->Append(pID1->Clone());
   } else {
@@ -576,7 +577,7 @@
   }
 
   if (pOldIDArray) {
-    const CPDF_Object* pID2 = pOldIDArray->GetObjectAt(1);
+    RetainPtr<const CPDF_Object> pID2 = pOldIDArray->GetObjectAt(1);
     if (m_IsIncremental && m_pEncryptDict && pID2) {
       m_pIDArray->Append(pID2->Clone());
       return;
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index a5f2e7c..787dfc4 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -230,7 +230,7 @@
   int first_code = 0;
   int last_code = 0;
   for (size_t i = 0; i < pArray->size(); i++) {
-    const CPDF_Object* pObj = pArray->GetDirectObjectAt(i);
+    RetainPtr<const CPDF_Object> pObj = pArray->GetDirectObjectAt(i);
     if (!pObj)
       continue;
 
diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp
index 9f710ac..dcdff59 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -136,7 +136,7 @@
   m_CharNames.resize(kInternalTableSize);
   uint32_t cur_code = 0;
   for (uint32_t i = 0; i < diffs->size(); i++) {
-    const CPDF_Object* element = diffs->GetDirectObjectAt(i);
+    RetainPtr<const CPDF_Object> element = diffs->GetDirectObjectAt(i);
     if (!element)
       continue;
 
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index e3eb1d0..d99e413 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -494,7 +494,7 @@
   if (!pArray || pArray->IsEmpty())
     return nullptr;
 
-  const CPDF_Object* pFamilyObj = pArray->GetDirectObjectAt(0);
+  RetainPtr<const CPDF_Object> pFamilyObj = pArray->GetDirectObjectAt(0);
   if (!pFamilyObj)
     return nullptr;
 
@@ -1113,20 +1113,20 @@
   if (m_IsNoneType)
     return 1;
 
-  const CPDF_Object* pAltArray = pArray->GetDirectObjectAt(2);
+  RetainPtr<const CPDF_Object> pAltArray = pArray->GetDirectObjectAt(2);
   if (pAltArray == GetArray())
     return 0;
 
-  m_pBaseCS = Load(pDoc, pAltArray, pVisited);
+  m_pBaseCS = Load(pDoc, pAltArray.Get(), pVisited);
   if (!m_pBaseCS)
     return 0;
 
   if (m_pBaseCS->IsSpecial())
     return 0;
 
-  const CPDF_Object* pFuncObj = pArray->GetDirectObjectAt(3);
+  RetainPtr<const CPDF_Object> pFuncObj = pArray->GetDirectObjectAt(3);
   if (pFuncObj && !pFuncObj->IsName()) {
-    auto pFunc = CPDF_Function::Load(pFuncObj);
+    auto pFunc = CPDF_Function::Load(pFuncObj.Get());
     if (pFunc && pFunc->CountOutputs() >= m_pBaseCS->CountComponents())
       m_pFunc = std::move(pFunc);
   }
@@ -1182,16 +1182,16 @@
 uint32_t CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc,
                                 const CPDF_Array* pArray,
                                 std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Array* pObj = ToArray(pArray->GetDirectObjectAt(1));
+  RetainPtr<const CPDF_Array> pObj = ToArray(pArray->GetDirectObjectAt(1));
   if (!pObj)
     return 0;
 
-  const CPDF_Object* pAltCS = pArray->GetDirectObjectAt(2);
+  RetainPtr<const CPDF_Object> pAltCS = pArray->GetDirectObjectAt(2);
   if (!pAltCS || pAltCS == GetArray())
     return 0;
 
-  m_pBaseCS = Load(pDoc, pAltCS, pVisited);
-  m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3));
+  m_pBaseCS = Load(pDoc, pAltCS.Get(), pVisited);
+  m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3).Get());
   if (!m_pBaseCS || !m_pFunc)
     return 0;
 
diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp
index acfde16..3ad7bee 100644
--- a/core/fpdfapi/page/cpdf_contentparser.cpp
+++ b/core/fpdfapi/page/cpdf_contentparser.cpp
@@ -149,10 +149,10 @@
   DCHECK(m_pObjectHolder->IsPage());
   const CPDF_Array* pContent =
       m_pObjectHolder->GetDict()->GetArrayFor(pdfium::page_object::kContents);
-  const CPDF_Stream* pStreamObj = ToStream(
+  RetainPtr<const CPDF_Stream> pStreamObj = ToStream(
       pContent ? pContent->GetDirectObjectAt(m_CurrentOffset) : nullptr);
   m_StreamArray[m_CurrentOffset] =
-      pdfium::MakeRetain<CPDF_StreamAcc>(pStreamObj);
+      pdfium::MakeRetain<CPDF_StreamAcc>(pStreamObj.Get());
   m_StreamArray[m_CurrentOffset]->LoadAllDataFiltered();
   m_CurrentOffset++;
 
diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp
index 221d67f..d2198f7 100644
--- a/core/fpdfapi/page/cpdf_docpagedata.cpp
+++ b/core/fpdfapi/page/cpdf_docpagedata.cpp
@@ -311,7 +311,7 @@
     return nullptr;
 
   if (pArray->size() == 1) {
-    return GetColorSpaceInternal(pArray->GetDirectObjectAt(0), pResources,
+    return GetColorSpaceInternal(pArray->GetDirectObjectAt(0).Get(), pResources,
                                  pVisited, pVisitedInternal);
   }
 
diff --git a/core/fpdfapi/page/cpdf_indexedcs.cpp b/core/fpdfapi/page/cpdf_indexedcs.cpp
index 10e112e..c8c7770 100644
--- a/core/fpdfapi/page/cpdf_indexedcs.cpp
+++ b/core/fpdfapi/page/cpdf_indexedcs.cpp
@@ -34,12 +34,13 @@
   if (pArray->size() < 4)
     return 0;
 
-  const CPDF_Object* pBaseObj = pArray->GetDirectObjectAt(1);
+  RetainPtr<const CPDF_Object> pBaseObj = pArray->GetDirectObjectAt(1);
   if (pBaseObj == GetArray())
     return 0;
 
   auto* pDocPageData = CPDF_DocPageData::FromDocument(pDoc);
-  m_pBaseCS = pDocPageData->GetColorSpaceGuarded(pBaseObj, nullptr, pVisited);
+  m_pBaseCS =
+      pDocPageData->GetColorSpaceGuarded(pBaseObj.Get(), nullptr, pVisited);
   if (!m_pBaseCS)
     return 0;
 
@@ -59,7 +60,7 @@
   }
   m_MaxIndex = pArray->GetIntegerAt(2);
 
-  const CPDF_Object* pTableObj = pArray->GetDirectObjectAt(3);
+  RetainPtr<const CPDF_Object> pTableObj = pArray->GetDirectObjectAt(3);
   if (!pTableObj)
     return 0;
 
diff --git a/core/fpdfapi/page/cpdf_occontext.cpp b/core/fpdfapi/page/cpdf_occontext.cpp
index afeda6a..b52ebf0 100644
--- a/core/fpdfapi/page/cpdf_occontext.cpp
+++ b/core/fpdfapi/page/cpdf_occontext.cpp
@@ -189,7 +189,7 @@
 
   ByteString csOperator = pExpression->GetStringAt(0);
   if (csOperator == "Not") {
-    const CPDF_Object* pOCGObj = pExpression->GetDirectObjectAt(1);
+    RetainPtr<const CPDF_Object> pOCGObj = pExpression->GetDirectObjectAt(1);
     if (!pOCGObj)
       return false;
     if (const CPDF_Dictionary* pDict = pOCGObj->AsDictionary())
@@ -204,7 +204,7 @@
 
   bool bValue = false;
   for (size_t i = 1; i < pExpression->size(); i++) {
-    const CPDF_Object* pOCGObj = pExpression->GetDirectObjectAt(i);
+    RetainPtr<const CPDF_Object> pOCGObj = pExpression->GetDirectObjectAt(i);
     if (!pOCGObj)
       continue;
 
diff --git a/core/fpdfapi/page/cpdf_patterncs.cpp b/core/fpdfapi/page/cpdf_patterncs.cpp
index 5b85b3e..f2ef15e 100644
--- a/core/fpdfapi/page/cpdf_patterncs.cpp
+++ b/core/fpdfapi/page/cpdf_patterncs.cpp
@@ -22,12 +22,13 @@
 uint32_t CPDF_PatternCS::v_Load(CPDF_Document* pDoc,
                                 const CPDF_Array* pArray,
                                 std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Object* pBaseCS = pArray->GetDirectObjectAt(1);
+  RetainPtr<const CPDF_Object> pBaseCS = pArray->GetDirectObjectAt(1);
   if (pBaseCS == GetArray())
     return 0;
 
   auto* pDocPageData = CPDF_DocPageData::FromDocument(pDoc);
-  m_pBaseCS = pDocPageData->GetColorSpaceGuarded(pBaseCS, nullptr, pVisited);
+  m_pBaseCS =
+      pDocPageData->GetColorSpaceGuarded(pBaseCS.Get(), nullptr, pVisited);
   if (!m_pBaseCS)
     return 1;
 
diff --git a/core/fpdfapi/page/cpdf_shadingpattern.cpp b/core/fpdfapi/page/cpdf_shadingpattern.cpp
index 849f4e1..81a0439 100644
--- a/core/fpdfapi/page/cpdf_shadingpattern.cpp
+++ b/core/fpdfapi/page/cpdf_shadingpattern.cpp
@@ -60,8 +60,10 @@
   if (pFunc) {
     if (const CPDF_Array* pArray = pFunc->AsArray()) {
       m_pFunctions.resize(std::min<size_t>(pArray->size(), 4));
-      for (size_t i = 0; i < m_pFunctions.size(); ++i)
-        m_pFunctions[i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
+      for (size_t i = 0; i < m_pFunctions.size(); ++i) {
+        m_pFunctions[i] =
+            CPDF_Function::Load(pArray->GetDirectObjectAt(i).Get());
+      }
     } else {
       m_pFunctions.push_back(CPDF_Function::Load(pFunc));
     }
diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp
index 880e91d..2a3c97a 100644
--- a/core/fpdfapi/page/cpdf_stitchfunc.cpp
+++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp
@@ -68,11 +68,12 @@
   {
     absl::optional<uint32_t> nOutputs;
     for (uint32_t i = 0; i < nSubs; ++i) {
-      const CPDF_Object* pSub = pFunctionsArray->GetDirectObjectAt(i);
+      RetainPtr<const CPDF_Object> pSub = pFunctionsArray->GetDirectObjectAt(i);
       if (pSub == pObj)
         return false;
 
-      std::unique_ptr<CPDF_Function> pFunc(CPDF_Function::Load(pSub, pVisited));
+      std::unique_ptr<CPDF_Function> pFunc(
+          CPDF_Function::Load(pSub.Get(), pVisited));
       if (!pFunc)
         return false;
 
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 07e04c8..078c172 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -1279,7 +1279,7 @@
   size_t n = pArray->size();
   size_t nsegs = 0;
   for (size_t i = 0; i < n; i++) {
-    const CPDF_Object* pDirectObject = pArray->GetDirectObjectAt(i);
+    RetainPtr<const CPDF_Object> pDirectObject = pArray->GetDirectObjectAt(i);
     if (pDirectObject && pDirectObject->IsString())
       nsegs++;
   }
@@ -1296,7 +1296,7 @@
   size_t iSegment = 0;
   float fInitKerning = 0;
   for (size_t i = 0; i < n; i++) {
-    const CPDF_Object* pObj = pArray->GetDirectObjectAt(i);
+    RetainPtr<const CPDF_Object> pObj = pArray->GetDirectObjectAt(i);
     if (!pObj)
       continue;
 
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index 30911bd..900676b 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -93,23 +93,21 @@
   return Find(pThat).has_value();
 }
 
-RetainPtr<CPDF_Object> CPDF_Array::GetMutableObjectAt(size_t index) {
-  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetObjectAt(index)));
+RetainPtr<const CPDF_Object> CPDF_Array::GetObjectAt(size_t index) const {
+  return const_cast<CPDF_Array*>(this)->GetMutableObjectAt(index);
 }
 
-const CPDF_Object* CPDF_Array::GetObjectAt(size_t index) const {
-  if (index >= m_Objects.size())
-    return nullptr;
-  return m_Objects[index].Get();
+RetainPtr<CPDF_Object> CPDF_Array::GetMutableObjectAt(size_t index) {
+  return index < m_Objects.size() ? m_Objects[index] : nullptr;
+}
+
+RetainPtr<const CPDF_Object> CPDF_Array::GetDirectObjectAt(size_t index) const {
+  return const_cast<CPDF_Array*>(this)->GetMutableDirectObjectAt(index);
 }
 
 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 {
-  const CPDF_Object* pObj = GetObjectAt(index);
-  return pObj ? pObj->GetDirect().Get() : nullptr;
+  RetainPtr<CPDF_Object> pObj = GetMutableObjectAt(index);
+  return pObj ? pObj->GetMutableDirect() : nullptr;
 }
 
 ByteString CPDF_Array::GetStringAt(size_t index) const {
@@ -147,8 +145,9 @@
   return pdfium::WrapRetain(const_cast<CPDF_Dictionary*>(GetDictAt(index)));
 }
 
+// TODO(tsepez): return retained objects from these.
 const CPDF_Dictionary* CPDF_Array::GetDictAt(size_t index) const {
-  const CPDF_Object* p = GetDirectObjectAt(index);
+  RetainPtr<const CPDF_Object> p = GetDirectObjectAt(index);
   if (!p)
     return nullptr;
   if (const CPDF_Dictionary* pDict = p->AsDictionary())
@@ -163,7 +162,7 @@
 }
 
 const CPDF_Stream* CPDF_Array::GetStreamAt(size_t index) const {
-  return ToStream(GetDirectObjectAt(index));
+  return ToStream(GetDirectObjectAt(index)).Get();
 }
 
 RetainPtr<CPDF_Array> CPDF_Array::GetMutableArrayAt(size_t index) {
@@ -171,7 +170,7 @@
 }
 
 const CPDF_Array* CPDF_Array::GetArrayAt(size_t index) const {
-  return ToArray(GetDirectObjectAt(index));
+  return ToArray(GetDirectObjectAt(index)).Get();
 }
 
 void CPDF_Array::Clear() {
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
index c3ce2a1..b0f7087 100644
--- a/core/fpdfapi/parser/cpdf_array.h
+++ b/core/fpdfapi/parser/cpdf_array.h
@@ -44,13 +44,13 @@
   // nullptr in those cases. Otherwise, for in-bound indices, the result
   // is never nullptr.
   RetainPtr<CPDF_Object> GetMutableObjectAt(size_t index);
-  const CPDF_Object* GetObjectAt(size_t index) const;
+  RetainPtr<const CPDF_Object> GetObjectAt(size_t index) const;
 
   // 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.
   RetainPtr<CPDF_Object> GetMutableDirectObjectAt(size_t index);
-  const CPDF_Object* GetDirectObjectAt(size_t index) const;
+  RetainPtr<const CPDF_Object> GetDirectObjectAt(size_t index) const;
 
   // The Get*At() methods tolerate out-of-bounds indices and return nullptr
   // in those cases. Furthermore, these safely coerce to the sub-class,
diff --git a/core/fpdfapi/parser/cpdf_array_unittest.cpp b/core/fpdfapi/parser/cpdf_array_unittest.cpp
index 4833a08..82ca9db 100644
--- a/core/fpdfapi/parser/cpdf_array_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_array_unittest.cpp
@@ -157,9 +157,9 @@
       EXPECT_NE(arr_elem, arr1_elem);
       EXPECT_NE(arr_elem, arr2_elem);
       for (size_t j = 0; j < kNumOfRowElems; ++j) {
-        auto* elem_obj = arr_elem->GetObjectAt(j);
-        auto* elem_obj1 = arr1_elem->GetObjectAt(j);
-        auto* elem_obj2 = arr2_elem->GetObjectAt(j);
+        auto elem_obj = arr_elem->GetObjectAt(j);
+        auto elem_obj1 = arr1_elem->GetObjectAt(j);
+        auto elem_obj2 = arr2_elem->GetObjectAt(j);
         // Results from not deferencing reference objects.
         EXPECT_NE(elem_obj, elem_obj1);
         EXPECT_TRUE(elem_obj1->IsReference());
@@ -178,7 +178,7 @@
     for (size_t i = 0; i < kNumOfRows; ++i) {
       for (size_t j = 0; j < kNumOfRowElems; ++j) {
         // Results from not deferencing reference objects.
-        auto* elem_obj1 = arr1->GetObjectAt(i)->AsArray()->GetObjectAt(j);
+        auto elem_obj1 = arr1->GetObjectAt(i)->AsArray()->GetObjectAt(j);
         EXPECT_TRUE(elem_obj1->IsReference());
         EXPECT_EQ(elems[i][j], elem_obj1->GetInteger());
         // Results from deferencing reference objects.
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 8f03085..93bd0be 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -548,7 +548,7 @@
 
   pPageNode->m_type = PageNode::Type::kPages;
   for (size_t i = 0; i < pArray->size(); ++i) {
-    const CPDF_Reference* pKid = ToReference(pArray->GetObjectAt(i));
+    RetainPtr<const CPDF_Reference> pKid = ToReference(pArray->GetObjectAt(i));
     if (!pKid)
       continue;
 
@@ -613,7 +613,8 @@
     case CPDF_Object::kArray: {
       const CPDF_Array* pKidsArray = pKids->AsArray();
       for (size_t i = 0; i < pKidsArray->size(); ++i) {
-        const CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i));
+        RetainPtr<const CPDF_Reference> pKid =
+            ToReference(pKidsArray->GetObjectAt(i));
         if (!pKid)
           continue;
 
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index c5bf71e..e7d8f02 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -85,7 +85,8 @@
 
   if (count && count == pKidList->size()) {
     for (size_t i = 0; i < count; i++) {
-      const CPDF_Reference* pKid = ToReference(pKidList->GetObjectAt(i));
+      RetainPtr<const CPDF_Reference> pKid =
+          ToReference(pKidList->GetObjectAt(i));
       if (pKid && pKid->GetRefObjNum() == objnum)
         return static_cast<int>(*index + i);
     }
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index b7e0ea0..8c25fb9 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -135,8 +135,10 @@
         if (array1->size() != array2->size())
           return false;
         for (size_t i = 0; i < array1->size(); ++i) {
-          if (!Equal(array1->GetObjectAt(i), array2->GetObjectAt(i)))
+          if (!Equal(array1->GetObjectAt(i).Get(),
+                     array2->GetObjectAt(i).Get())) {
             return false;
+          }
         }
         return true;
       }
@@ -814,7 +816,7 @@
   auto array = pdfium::MakeRetain<CPDF_Array>();
   array->AppendNew<CPDF_Reference>(&objects_holder, 1234);
   ASSERT_EQ(1U, array->size());
-  const CPDF_Object* obj = array->GetObjectAt(0);
+  RetainPtr<const CPDF_Object> obj = array->GetObjectAt(0);
   ASSERT_TRUE(obj);
   EXPECT_TRUE(obj->IsReference());
 
@@ -824,7 +826,7 @@
 
   RetainPtr<CPDF_Array> cloned_array = ToArray(std::move(cloned_array_object));
   ASSERT_EQ(0U, cloned_array->size());
-  const CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0);
+  RetainPtr<const CPDF_Object> cloned_obj = cloned_array->GetObjectAt(0);
   EXPECT_FALSE(cloned_obj);
 }
 
@@ -833,8 +835,8 @@
   auto array = pdfium::MakeRetain<CPDF_Array>();
   CPDF_Object* pObj = array->AppendNew<CPDF_Number>(42);
   array->ConvertToIndirectObjectAt(0, &objects_holder);
-  const CPDF_Object* pRef = array->GetObjectAt(0);
-  const CPDF_Object* pNum = array->GetDirectObjectAt(0);
+  RetainPtr<const CPDF_Object> pRef = array->GetObjectAt(0);
+  RetainPtr<const CPDF_Object> pNum = array->GetDirectObjectAt(0);
   EXPECT_TRUE(pRef->IsReference());
   EXPECT_TRUE(pNum->IsNumber());
   EXPECT_NE(pObj, pRef);
@@ -946,7 +948,7 @@
     // Cloned object should be the same as the original.
     ASSERT_TRUE(cloned_array);
     EXPECT_EQ(1u, cloned_array->size());
-    const CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0);
+    RetainPtr<const CPDF_Object> cloned_dict = cloned_array->GetObjectAt(0);
     ASSERT_TRUE(cloned_dict);
     ASSERT_TRUE(cloned_dict->IsDictionary());
     // Recursively referenced object is not cloned.
@@ -976,7 +978,7 @@
     RetainPtr<CPDF_Array> arr_obj = pdfium::MakeRetain<CPDF_Array>();
     arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder,
                                          dict_obj->GetObjNum());
-    const CPDF_Object* elem0 = arr_obj->GetObjectAt(0);
+    RetainPtr<const CPDF_Object> elem0 = arr_obj->GetObjectAt(0);
     dict_obj->SetFor("arr", std::move(arr_obj));
     EXPECT_EQ(1u, dict_obj->GetObjNum());
     ASSERT_TRUE(elem0);
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 7992d98..b313daa 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -82,10 +82,14 @@
   std::vector<CrossRefV5IndexEntry> indices;
   if (array) {
     for (size_t i = 0; i < array->size() / 2; i++) {
-      const CPDF_Number* pStartNumObj = ToNumber(array->GetObjectAt(i * 2));
-      const CPDF_Number* pCountObj = ToNumber(array->GetObjectAt(i * 2 + 1));
+      RetainPtr<const CPDF_Number> pStartNumObj =
+          ToNumber(array->GetObjectAt(i * 2));
+      if (!pStartNumObj)
+        continue;
 
-      if (!pStartNumObj || !pCountObj)
+      RetainPtr<const CPDF_Number> pCountObj =
+          ToNumber(array->GetObjectAt(i * 2 + 1));
+      if (!pCountObj)
         continue;
 
       int nStartNum = pStartNumObj->GetInteger();
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index f52e834..2baa63e 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -61,4 +61,9 @@
   return RetainPtr<CPDF_Reference>(ToReference(obj.Get()));
 }
 
+inline RetainPtr<const CPDF_Reference> ToReference(
+    RetainPtr<const CPDF_Object> obj) {
+  return RetainPtr<const CPDF_Reference>(ToReference(obj.Get()));
+}
+
 #endif  // CORE_FPDFAPI_PARSER_CPDF_REFERENCE_H_
diff --git a/core/fpdfapi/parser/cpdf_string.h b/core/fpdfapi/parser/cpdf_string.h
index f7bfd38..5ef0e30 100644
--- a/core/fpdfapi/parser/cpdf_string.h
+++ b/core/fpdfapi/parser/cpdf_string.h
@@ -48,4 +48,8 @@
   return obj ? obj->AsString() : nullptr;
 }
 
+inline RetainPtr<const CPDF_String> ToString(RetainPtr<const CPDF_Object> obj) {
+  return RetainPtr<const CPDF_String>(ToString(obj.Get()));
+}
+
 #endif  // CORE_FPDFAPI_PARSER_CPDF_STRING_H_
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index e3a5209..209aa8a 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -216,11 +216,11 @@
       const CPDF_Array* p = pObj->AsArray();
       buf << "[";
       for (size_t i = 0; i < p->size(); i++) {
-        const CPDF_Object* pElement = p->GetObjectAt(i);
+        RetainPtr<const CPDF_Object> pElement = p->GetObjectAt(i);
         if (!pElement->IsInline()) {
           buf << " " << pElement->GetObjNum() << " 0 R";
         } else {
-          buf << pElement;
+          buf << pElement.Get();
         }
       }
       buf << "]";
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp
index 8887b42..1a351d5 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp
@@ -84,7 +84,8 @@
       return nullptr;
 
     for (uint32_t i = 0; i < 3; ++i) {
-      pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
+      // TODO(tsepez): pass retained objects to Load().
+      pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i).Get());
       if (!pFuncs[2 - i])
         return nullptr;
     }
diff --git a/core/fpdfdoc/cpdf_action.cpp b/core/fpdfdoc/cpdf_action.cpp
index 56b6e57..be4912c 100644
--- a/core/fpdfdoc/cpdf_action.cpp
+++ b/core/fpdfdoc/cpdf_action.cpp
@@ -127,9 +127,11 @@
     result.push_back(pFields);
   } else if (const CPDF_Array* pArray = pFields->AsArray()) {
     for (size_t i = 0; i < pArray->size(); ++i) {
-      const CPDF_Object* pObj = pArray->GetDirectObjectAt(i);
-      if (pObj)
-        result.push_back(pObj);
+      RetainPtr<const CPDF_Object> pObj = pArray->GetDirectObjectAt(i);
+      if (pObj) {
+        // TODO(tsepez): push retained objects.
+        result.push_back(pObj.Get());
+      }
     }
   }
   return result;
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index 3ce7dc1..0f27b59 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -464,7 +464,7 @@
         size_t nLen = pDashArray->size();
         size_t i = 0;
         for (; i < nLen; ++i) {
-          const CPDF_Object* pObj = pDashArray->GetDirectObjectAt(i);
+          RetainPtr<const CPDF_Object> pObj = pDashArray->GetDirectObjectAt(i);
           if (pObj && pObj->GetInteger()) {
             break;
           }
diff --git a/core/fpdfdoc/cpdf_dest.cpp b/core/fpdfdoc/cpdf_dest.cpp
index 02c6fe5..3636d70 100644
--- a/core/fpdfdoc/cpdf_dest.cpp
+++ b/core/fpdfdoc/cpdf_dest.cpp
@@ -53,7 +53,7 @@
   if (!m_pArray)
     return -1;
 
-  const CPDF_Object* pPage = m_pArray->GetDirectObjectAt(0);
+  RetainPtr<const CPDF_Object> pPage = m_pArray->GetDirectObjectAt(0);
   if (!pPage)
     return -1;
 
@@ -70,7 +70,7 @@
   if (!m_pArray)
     return 0;
 
-  const CPDF_Object* pArray = m_pArray->GetDirectObjectAt(1);
+  RetainPtr<const CPDF_Object> pArray = m_pArray->GetDirectObjectAt(1);
   if (!pArray)
     return 0;
 
@@ -99,13 +99,14 @@
   if (m_pArray->size() < 5)
     return false;
 
-  const CPDF_Name* xyz = ToName(m_pArray->GetDirectObjectAt(1));
+  RetainPtr<const CPDF_Name> xyz = ToName(m_pArray->GetDirectObjectAt(1));
   if (!xyz || xyz->GetString() != "XYZ")
     return false;
 
-  const CPDF_Number* numX = ToNumber(m_pArray->GetDirectObjectAt(2));
-  const CPDF_Number* numY = ToNumber(m_pArray->GetDirectObjectAt(3));
-  const CPDF_Number* numZoom = ToNumber(m_pArray->GetDirectObjectAt(4));
+  RetainPtr<const CPDF_Number> numX = ToNumber(m_pArray->GetDirectObjectAt(2));
+  RetainPtr<const CPDF_Number> numY = ToNumber(m_pArray->GetDirectObjectAt(3));
+  RetainPtr<const CPDF_Number> numZoom =
+      ToNumber(m_pArray->GetDirectObjectAt(4));
 
   // If the value is a CPDF_Null then ToNumber will return nullptr.
   *pHasX = !!numX;
diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp
index 428728b..dc98c66 100644
--- a/core/fpdfdoc/cpdf_formfield.cpp
+++ b/core/fpdfdoc/cpdf_formfield.cpp
@@ -313,7 +313,7 @@
     case CPDF_Object::kStream:
       return pValue->GetUnicodeText();
     case CPDF_Object::kArray:
-      pValue = pValue->AsArray()->GetDirectObjectAt(0);
+      pValue = pValue->AsArray()->GetDirectObjectAt(0).Get();
       if (pValue)
         return pValue->GetUnicodeText();
       break;
@@ -444,7 +444,8 @@
     if (!pArray || index < 0)
       return -1;
 
-    const CPDF_Object* elementValue = pArray->GetDirectObjectAt(index);
+    RetainPtr<const CPDF_Object> elementValue =
+        pArray->GetDirectObjectAt(index);
     sel_value = elementValue ? elementValue->GetUnicodeText() : WideString();
   }
   if (index < CountSelectedOptions()) {
@@ -558,13 +559,18 @@
   if (!pArray)
     return WideString();
 
-  const CPDF_Object* pOption = pArray->GetDirectObjectAt(index);
+  RetainPtr<const CPDF_Object> pOption = pArray->GetDirectObjectAt(index);
   if (!pOption)
     return WideString();
-  if (const CPDF_Array* pOptionArray = pOption->AsArray())
+
+  const CPDF_Array* pOptionArray = pOption->AsArray();
+  if (pOptionArray)
     pOption = pOptionArray->GetDirectObjectAt(sub_index);
 
-  const CPDF_String* pString = ToString(pOption);
+  if (!pOption)
+    return WideString();
+
+  const CPDF_String* pString = pOption->AsString();
   return pString ? pString->GetUnicodeText() : WideString();
 }
 
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index d92d580..eb50ef4 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -1247,12 +1247,13 @@
           if (FXSYS_IsFloatSmaller(fy, rcBody.bottom))
             break;
 
-          if (const CPDF_Object* pOpt = pOpts->GetDirectObjectAt(i)) {
+          if (RetainPtr<const CPDF_Object> pOpt = pOpts->GetDirectObjectAt(i)) {
             WideString swItem;
             if (pOpt->IsString()) {
               swItem = pOpt->GetUnicodeText();
             } else if (const CPDF_Array* pArray = pOpt->AsArray()) {
-              const CPDF_Object* pDirectObj = pArray->GetDirectObjectAt(1);
+              RetainPtr<const CPDF_Object> pDirectObj =
+                  pArray->GetDirectObjectAt(1);
               if (pDirectObj)
                 swItem = pDirectObj->GetUnicodeText();
             }
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 89c419b..97457c1 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -672,9 +672,9 @@
   if (!pArray)
     return nullptr;
 
-  const CPDF_Dictionary* pElement =
+  RetainPtr<const CPDF_Dictionary> pElement =
       ToDictionary(pArray->GetDirectObjectAt(index));
-  return pElement ? GetFieldByDict(pElement) : nullptr;
+  return pElement ? GetFieldByDict(pElement.Get()) : nullptr;
 }
 
 int CPDF_InteractiveForm::FindFieldInCalculationOrder(
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 36baa01..01adfb4 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -248,7 +248,7 @@
         continue;
 
       *nIndex += i;
-      return pdfium::WrapRetain(pNames->GetDirectObjectAt(i * 2 + 1));
+      return pNames->GetDirectObjectAt(i * 2 + 1);
     }
     *nIndex += dwCount;
     return nullptr;
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
index ea22ed3..3427bb2 100644
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
@@ -7,6 +7,7 @@
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_number.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fxcrt/retain_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -40,9 +41,9 @@
   const CPDF_Array* limits = node->GetArrayFor("Limits");
   ASSERT_TRUE(limits);
   EXPECT_EQ(2u, limits->size());
-  const CPDF_String* left = ToString(limits->GetObjectAt(0));
+  RetainPtr<const CPDF_String> left = ToString(limits->GetObjectAt(0));
   ASSERT_TRUE(left);
-  const CPDF_String* right = ToString(limits->GetObjectAt(1));
+  RetainPtr<const CPDF_String> right = ToString(limits->GetObjectAt(1));
   ASSERT_TRUE(right);
   EXPECT_STREQ(least, left->GetString().c_str());
   EXPECT_STREQ(greatest, right->GetString().c_str());
diff --git a/core/fpdfdoc/cpdf_numbertree.cpp b/core/fpdfdoc/cpdf_numbertree.cpp
index 85f488b..257db4b 100644
--- a/core/fpdfdoc/cpdf_numbertree.cpp
+++ b/core/fpdfdoc/cpdf_numbertree.cpp
@@ -11,6 +11,7 @@
 
 namespace {
 
+// TODO(tsepez): return retained objects.
 const CPDF_Object* SearchNumberNode(const CPDF_Dictionary* pNode, int num) {
   const CPDF_Array* pLimits = pNode->GetArrayFor("Limits");
   if (pLimits &&
@@ -22,7 +23,7 @@
     for (size_t i = 0; i < pNumbers->size() / 2; i++) {
       int index = pNumbers->GetIntegerAt(i * 2);
       if (num == index)
-        return pNumbers->GetDirectObjectAt(i * 2 + 1);
+        return pNumbers->GetDirectObjectAt(i * 2 + 1).Get();
       if (index > num)
         break;
     }
diff --git a/core/fpdfdoc/cpdf_structelement.cpp b/core/fpdfdoc/cpdf_structelement.cpp
index caa8b85..5cb54ec 100644
--- a/core/fpdfdoc/cpdf_structelement.cpp
+++ b/core/fpdfdoc/cpdf_structelement.cpp
@@ -106,8 +106,10 @@
   if (const CPDF_Array* pArray = pKids->AsArray()) {
     m_Kids.resize(pArray->size());
     for (size_t i = 0; i < pArray->size(); ++i) {
-      const CPDF_Object* pKid = pArray->GetDirectObjectAt(i);
-      LoadKid(PageObjNum, pKid, &m_Kids[i]);
+      RetainPtr<const CPDF_Object> pKid = pArray->GetDirectObjectAt(i);
+
+      // TODO(tsepez): LoadKid() can take moved retained pKid
+      LoadKid(PageObjNum, pKid.Get(), &m_Kids[i]);
     }
     return;
   }
diff --git a/core/fpdfdoc/cpdf_structtree.cpp b/core/fpdfdoc/cpdf_structtree.cpp
index bbac010..1cf2c3b 100644
--- a/core/fpdfdoc/cpdf_structtree.cpp
+++ b/core/fpdfdoc/cpdf_structtree.cpp
@@ -135,7 +135,8 @@
 
   bool bSave = false;
   for (size_t i = 0; i < pTopKids->size(); i++) {
-    const CPDF_Reference* pKidRef = ToReference(pTopKids->GetObjectAt(i));
+    RetainPtr<const CPDF_Reference> pKidRef =
+        ToReference(pTopKids->GetObjectAt(i));
     if (pKidRef && pKidRef->GetRefObjNum() == pDict->GetObjNum()) {
       m_Kids[i] = pElement;
       bSave = true;
diff --git a/fpdfsdk/cpdfsdk_interactiveform.cpp b/fpdfsdk/cpdfsdk_interactiveform.cpp
index 37b7ab4..23f1bdf 100644
--- a/fpdfsdk/cpdfsdk_interactiveform.cpp
+++ b/fpdfsdk/cpdfsdk_interactiveform.cpp
@@ -185,7 +185,7 @@
       continue;
 
     for (size_t j = 0, jsz = pAnnots->size(); j < jsz; j++) {
-      const CPDF_Object* pDict = pAnnots->GetDirectObjectAt(j);
+      RetainPtr<const CPDF_Object> pDict = pAnnots->GetDirectObjectAt(j);
       if (pAnnotDict == pDict)
         return i;
     }
diff --git a/fpdfsdk/fpdf_doc.cpp b/fpdfsdk/fpdf_doc.cpp
index edb7c49..d4e4b32 100644
--- a/fpdfsdk/fpdf_doc.cpp
+++ b/fpdfsdk/fpdf_doc.cpp
@@ -475,7 +475,8 @@
     return 0;
 
   size_t nIndex = id_type == FILEIDTYPE_PERMANENT ? 0 : 1;
-  const CPDF_String* pValue = ToString(pFileId->GetDirectObjectAt(nIndex));
+  RetainPtr<const CPDF_String> pValue =
+      ToString(pFileId->GetDirectObjectAt(nIndex));
   if (!pValue)
     return 0;
 
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 130d55a..d601f34 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -163,7 +163,7 @@
       int cid = widths_array->GetNumberAt(idx);
       EXPECT_GE(cid, cur_cid);
       ASSERT_FALSE(++idx == widths_array->size());
-      const CPDF_Object* next = widths_array->GetObjectAt(idx);
+      RetainPtr<const CPDF_Object> next = widths_array->GetObjectAt(idx);
       if (next->IsArray()) {
         // We are in the c [w1 w2 ...] case
         const CPDF_Array* arr = next->AsArray();
diff --git a/fpdfsdk/fpdf_save.cpp b/fpdfsdk/fpdf_save.cpp
index 03b5c61..7672057 100644
--- a/fpdfsdk/fpdf_save.cpp
+++ b/fpdfsdk/fpdf_save.cpp
@@ -66,7 +66,7 @@
   int iFormIndex = -1;
   int iDataSetsIndex = -1;
   for (int i = 0; i < size - 1; i++) {
-    const CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
+    RetainPtr<const CPDF_Object> pPDFObj = pArray->GetObjectAt(i);
     if (!pPDFObj->IsString())
       continue;
     if (pPDFObj->GetString() == "form")
diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp
index fd43e49..86af669 100644
--- a/fpdfsdk/fpdf_structtree.cpp
+++ b/fpdfsdk/fpdf_structtree.cpp
@@ -444,7 +444,7 @@
     const CPDF_Array* array = p->AsArray();
     if (index < 0 || static_cast<size_t>(index) >= array->size())
       return -1;
-    const CPDF_Object* array_elem = array->GetObjectAt(index);
+    RetainPtr<const CPDF_Object> array_elem = array->GetObjectAt(index);
     if (array_elem->IsNumber())
       return array_elem->GetInteger();
     if (array_elem->IsDictionary()) {
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index dc426bc..4d79fc2 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -136,7 +136,7 @@
     if (i + 1 == xfa_array->size())
       break;
 
-    const CPDF_String* name = ToString(xfa_array->GetObjectAt(i));
+    RetainPtr<const CPDF_String> name = ToString(xfa_array->GetObjectAt(i));
     if (!name)
       continue;
 
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index c2340c9..2e0bbfe 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -469,8 +469,8 @@
       return;
 
     for (size_t i = 1; i < pArray->size(); i += 2) {
-      const CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
-      const CPDF_Object* pPrePDFObj = pArray->GetObjectAt(i - 1);
+      RetainPtr<const CPDF_Object> pPDFObj = pArray->GetObjectAt(i);
+      RetainPtr<const CPDF_Object> pPrePDFObj = pArray->GetObjectAt(i - 1);
       if (!pPrePDFObj->IsString())
         continue;
       if (!pPDFObj->IsReference())