Return even more retained objects from CPDF_Array getters.

Change-Id: I17aac0d8bcc3fa38c459cba64cfa3797182f0f7e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97531
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index 787dfc4..1ff59fd 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -410,7 +410,7 @@
   if (!pFonts || pFonts->size() != 1)
     return false;
 
-  const CPDF_Dictionary* pCIDFontDict = pFonts->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> pCIDFontDict = pFonts->GetDictAt(0);
   if (!pCIDFontDict)
     return false;
 
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index 6e570c7..585da7a 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -71,11 +71,12 @@
         if (!pDash)
           break;
 
-        const CPDF_Array* pArray = pDash->GetArrayAt(0);
+        RetainPtr<const CPDF_Array> pArray = pDash->GetArrayAt(0);
         if (!pArray)
           break;
 
-        SetLineDash(pArray, pDash->GetNumberAt(1), 1.0f);
+        // TODO(tsepez): pass moved retained object.
+        SetLineDash(pArray.Get(), pDash->GetNumberAt(1), 1.0f);
         break;
       }
       case FXBSTR_ID('R', 'I', 0, 0):
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index d99e413..1561aa4 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -646,14 +646,14 @@
 uint32_t CPDF_CalGray::v_Load(CPDF_Document* pDoc,
                               const CPDF_Array* pArray,
                               std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  RetainPtr<const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
   if (!pDict)
     return 0;
 
-  if (!GetWhitePoint(pDict, m_WhitePoint))
+  if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
     return 0;
 
-  GetBlackPoint(pDict, m_BlackPoint);
+  GetBlackPoint(pDict.Get(), m_BlackPoint);
 
   m_Gamma = pDict->GetNumberFor("Gamma");
   if (m_Gamma == 0)
@@ -695,14 +695,14 @@
 uint32_t CPDF_CalRGB::v_Load(CPDF_Document* pDoc,
                              const CPDF_Array* pArray,
                              std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  RetainPtr<const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
   if (!pDict)
     return 0;
 
-  if (!GetWhitePoint(pDict, m_WhitePoint))
+  if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
     return 0;
 
-  GetBlackPoint(pDict, m_BlackPoint);
+  GetBlackPoint(pDict.Get(), m_BlackPoint);
 
   const CPDF_Array* pParam = pDict->GetArrayFor("Gamma");
   if (pParam) {
@@ -809,14 +809,14 @@
 uint32_t CPDF_LabCS::v_Load(CPDF_Document* pDoc,
                             const CPDF_Array* pArray,
                             std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  RetainPtr<const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
   if (!pDict)
     return 0;
 
-  if (!GetWhitePoint(pDict, m_WhitePoint))
+  if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
     return 0;
 
-  GetBlackPoint(pDict, m_BlackPoint);
+  GetBlackPoint(pDict.Get(), m_BlackPoint);
 
   const CPDF_Array* pParam = pDict->GetArrayFor("Range");
   static constexpr float kDefaultRanges[kRangesCount] = {-100.0f, 100.0f,
@@ -893,7 +893,7 @@
 uint32_t CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc,
                                  const CPDF_Array* pArray,
                                  std::set<const CPDF_Object*>* pVisited) {
-  const CPDF_Stream* pStream = pArray->GetStreamAt(1);
+  RetainPtr<const CPDF_Stream> pStream = pArray->GetStreamAt(1);
   if (!pStream)
     return 0;
 
@@ -906,7 +906,8 @@
     return 0;
 
   uint32_t nComponents = static_cast<uint32_t>(nDictComponents);
-  m_pProfile = CPDF_DocPageData::FromDocument(pDoc)->GetIccProfile(pStream);
+  m_pProfile =
+      CPDF_DocPageData::FromDocument(pDoc)->GetIccProfile(pStream.Get());
   if (!m_pProfile)
     return 0;
 
diff --git a/core/fpdfapi/page/cpdf_occontext.cpp b/core/fpdfapi/page/cpdf_occontext.cpp
index b52ebf0..19bdc4f 100644
--- a/core/fpdfapi/page/cpdf_occontext.cpp
+++ b/core/fpdfapi/page/cpdf_occontext.cpp
@@ -55,9 +55,9 @@
     return pConfig;
 
   for (size_t i = 0; i < pConfigs->size(); i++) {
-    const CPDF_Dictionary* pFind = pConfigs->GetDictAt(i);
-    if (pFind && HasIntent(pFind, "View", ""))
-      return pFind;
+    RetainPtr<const CPDF_Dictionary> pFind = pConfigs->GetDictAt(i);
+    if (pFind && HasIntent(pFind.Get(), "View", ""))
+      return pFind.Get();
   }
   return pConfig;
 }
@@ -112,7 +112,7 @@
 
   ByteString csFind = csConfig + "State";
   for (size_t i = 0; i < pArray->size(); i++) {
-    const CPDF_Dictionary* pUsage = pArray->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pUsage = pArray->GetDictAt(i);
     if (!pUsage)
       continue;
 
@@ -250,12 +250,12 @@
   bool bValidEntrySeen = false;
   for (size_t i = 0; i < pArray->size(); i++) {
     bool bItem = true;
-    const CPDF_Dictionary* pItemDict = pArray->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pItemDict = pArray->GetDictAt(i);
     if (!pItemDict)
       continue;
 
     bValidEntrySeen = true;
-    bItem = GetOCGVisible(pItemDict);
+    bItem = GetOCGVisible(pItemDict.Get());
 
     if ((csP == "AnyOn" && bItem) || (csP == "AnyOff" && !bItem))
       return true;
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index 3ce1b81..033021f 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -74,7 +74,7 @@
                             int width,
                             int height,
                             const ByteString& decoder,
-                            const CPDF_Dictionary* pParam,
+                            RetainPtr<const CPDF_Dictionary> pParam,
                             uint32_t orig_size) {
   // |decoder| should not be an abbreviation.
   DCHECK(decoder != "A85");
@@ -88,11 +88,11 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> ignored_result;
   uint32_t ignored_size;
   if (decoder == "FlateDecode") {
-    return FlateOrLZWDecode(false, src_span, pParam, orig_size, &ignored_result,
-                            &ignored_size);
+    return FlateOrLZWDecode(false, src_span, pParam.Get(), orig_size,
+                            &ignored_result, &ignored_size);
   }
   if (decoder == "LZWDecode") {
-    return FlateOrLZWDecode(true, src_span, pParam, 0, &ignored_result,
+    return FlateOrLZWDecode(true, src_span, pParam.Get(), 0, &ignored_result,
                             &ignored_size);
   }
   if (decoder == "DCTDecode") {
@@ -103,7 +103,7 @@
   }
   if (decoder == "CCITTFaxDecode") {
     std::unique_ptr<ScanlineDecoder> pDecoder =
-        CreateFaxDecoder(src_span, width, height, pParam);
+        CreateFaxDecoder(src_span, width, height, pParam.Get());
     return DecodeAllScanlines(std::move(pDecoder));
   }
 
@@ -139,7 +139,7 @@
     return nullptr;
 
   ByteString decoder;
-  const CPDF_Dictionary* pParam = nullptr;
+  RetainPtr<const CPDF_Dictionary> pParam;
   const CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
   if (pFilter) {
     const CPDF_Array* pArray = pFilter->AsArray();
@@ -151,7 +151,7 @@
         pParam = pParams->GetDictAt(0);
     } else {
       decoder = pFilter->GetString();
-      pParam = pDict->GetDictFor(pdfium::stream::kDecodeParms);
+      pParam.Reset(pDict->GetDictFor(pdfium::stream::kDecodeParms));
     }
   }
   uint32_t width = pDict->GetIntegerFor("Width");
@@ -186,7 +186,7 @@
     m_Pos += dwOrigSize;
   } else {
     dwStreamSize = DecodeInlineStream(m_pBuf.subspan(m_Pos), width, height,
-                                      decoder, pParam, dwOrigSize);
+                                      decoder, std::move(pParam), dwOrigSize);
     if (!pdfium::base::IsValueInRangeForNumericType<int>(dwStreamSize))
       return nullptr;
 
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index 900676b..eaf10ce 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -142,35 +142,36 @@
 }
 
 RetainPtr<CPDF_Dictionary> CPDF_Array::GetMutableDictAt(size_t index) {
-  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 {
-  RetainPtr<const CPDF_Object> p = GetDirectObjectAt(index);
+  RetainPtr<CPDF_Object> p = GetMutableDirectObjectAt(index);
   if (!p)
     return nullptr;
-  if (const CPDF_Dictionary* pDict = p->AsDictionary())
-    return pDict;
-  if (const CPDF_Stream* pStream = p->AsStream())
-    return pStream->GetDict();
+  CPDF_Dictionary* pDict = p->AsMutableDictionary();
+  if (pDict)
+    return pdfium::WrapRetain(pDict);
+  CPDF_Stream* pStream = p->AsMutableStream();
+  if (pStream)
+    return pStream->GetMutableDict();
   return nullptr;
 }
 
-RetainPtr<CPDF_Stream> CPDF_Array::GetMutableStreamAt(size_t index) {
-  return pdfium::WrapRetain(const_cast<CPDF_Stream*>(GetStreamAt(index)));
+RetainPtr<const CPDF_Dictionary> CPDF_Array::GetDictAt(size_t index) const {
+  return const_cast<CPDF_Array*>(this)->GetMutableDictAt(index);
 }
 
-const CPDF_Stream* CPDF_Array::GetStreamAt(size_t index) const {
-  return ToStream(GetDirectObjectAt(index)).Get();
+RetainPtr<CPDF_Stream> CPDF_Array::GetMutableStreamAt(size_t index) {
+  return ToStream(GetMutableDirectObjectAt(index));
+}
+
+RetainPtr<const CPDF_Stream> CPDF_Array::GetStreamAt(size_t index) const {
+  return const_cast<CPDF_Array*>(this)->GetMutableStreamAt(index);
 }
 
 RetainPtr<CPDF_Array> CPDF_Array::GetMutableArrayAt(size_t index) {
-  return pdfium::WrapRetain(const_cast<CPDF_Array*>(GetArrayAt(index)));
+  return ToArray(GetMutableDirectObjectAt(index));
 }
 
-const CPDF_Array* CPDF_Array::GetArrayAt(size_t index) const {
-  return ToArray(GetDirectObjectAt(index)).Get();
+RetainPtr<const CPDF_Array> CPDF_Array::GetArrayAt(size_t index) const {
+  return const_cast<CPDF_Array*>(this)->GetMutableArrayAt(index);
 }
 
 void CPDF_Array::Clear() {
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
index b0f7087..9fab3c0 100644
--- a/core/fpdfapi/parser/cpdf_array.h
+++ b/core/fpdfapi/parser/cpdf_array.h
@@ -61,11 +61,11 @@
   int GetIntegerAt(size_t index) const;
   float GetNumberAt(size_t index) const;
   RetainPtr<CPDF_Dictionary> GetMutableDictAt(size_t index);
-  const CPDF_Dictionary* GetDictAt(size_t index) const;
+  RetainPtr<const CPDF_Dictionary> GetDictAt(size_t index) const;
   RetainPtr<CPDF_Stream> GetMutableStreamAt(size_t index);
-  const CPDF_Stream* GetStreamAt(size_t index) const;
+  RetainPtr<const CPDF_Stream> GetStreamAt(size_t index) const;
   RetainPtr<CPDF_Array> GetMutableArrayAt(size_t index);
-  const CPDF_Array* GetArrayAt(size_t index) const;
+  RetainPtr<const CPDF_Array> GetArrayAt(size_t index) const;
 
   CFX_FloatRect GetRect() const;
   CFX_Matrix GetMatrix() const;
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index e7d8f02..c966745 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -93,11 +93,12 @@
   }
 
   for (size_t i = 0; i < pKidList->size(); i++) {
-    const CPDF_Dictionary* pKid = pKidList->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pKid = pKidList->GetDictAt(i);
     if (!pKid || pKid == pNode)
       continue;
 
-    int found_index = FindPageIndex(pKid, skip_count, objnum, index, level + 1);
+    int found_index =
+        FindPageIndex(pKid.Get(), skip_count, objnum, index, level + 1);
     if (found_index >= 0)
       return found_index;
   }
diff --git a/core/fpdfapi/parser/fpdf_parser_decode.cpp b/core/fpdfapi/parser/fpdf_parser_decode.cpp
index 647b4fc..d150bfe 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_decode.cpp
@@ -382,9 +382,10 @@
 
     const CPDF_Array* pParamsArray = ToArray(pParams);
     for (size_t i = 0; i < pDecoders->size(); ++i) {
+      // TODO(tsepez): push retained arguments.
       decoder_array.push_back(
           {pDecoders->GetStringAt(i),
-           pParamsArray ? pParamsArray->GetDictAt(i) : nullptr});
+           pParamsArray ? pParamsArray->GetDictAt(i).Get() : nullptr});
     }
   } else {
     DCHECK(pFilter->IsName());
diff --git a/core/fpdfdoc/cpdf_action.cpp b/core/fpdfdoc/cpdf_action.cpp
index be4912c..77df25d 100644
--- a/core/fpdfdoc/cpdf_action.cpp
+++ b/core/fpdfdoc/cpdf_action.cpp
@@ -167,8 +167,10 @@
     return CPDF_Action(nullptr);
 
   const CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next");
-  if (const CPDF_Array* pArray = ToArray(pNext))
-    return CPDF_Action(pArray->GetDictAt(iIndex));
+  if (const CPDF_Array* pArray = ToArray(pNext)) {
+    // TODO(tsepez): Actions should take retained arguments.
+    return CPDF_Action(pArray->GetDictAt(iIndex).Get());
+  }
   if (const CPDF_Dictionary* pDict = ToDictionary(pNext)) {
     if (iIndex == 0)
       return CPDF_Action(pDict);
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index 0f27b59..f28b086 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -457,7 +457,8 @@
     if (pBorderArray) {
       width = pBorderArray->GetNumberAt(2);
       if (pBorderArray->size() == 4) {
-        pDashArray = pBorderArray->GetArrayAt(3);
+        // TODO(tsepez): convert to retained in future CPDF_Dictionary CLs.
+        pDashArray = pBorderArray->GetArrayAt(3).Get();
         if (!pDashArray) {
           return;
         }
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index eb50ef4..62440a7 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -342,8 +342,11 @@
 
   if (const CPDF_Array* pBorderArray =
           pAnnotDict.GetArrayFor(pdfium::annotation::kBorder)) {
-    if (pBorderArray->size() == 4)
-      return pBorderArray->GetArrayAt(3);
+    if (pBorderArray->size() == 4) {
+      // TODO(tsepez): Convert to retained as part of future CPDF_Dictionary
+      // CLs.
+      return pBorderArray->GetArrayAt(3).Get();
+    }
   }
 
   return nullptr;
@@ -663,7 +666,7 @@
   pAnnotDict->SetRectFor(pdfium::annotation::kRect, rect);
 
   for (size_t i = 0; i < pInkList->size(); i++) {
-    const CPDF_Array* pInkCoordList = pInkList->GetArrayAt(i);
+    RetainPtr<const CPDF_Array> pInkCoordList = pInkList->GetArrayAt(i);
     if (!pInkCoordList || pInkCoordList->size() < 2)
       continue;
 
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 97457c1..11417d4 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -627,11 +627,12 @@
 
   for (size_t i = pAnnotList->size(); i > 0; --i) {
     size_t annot_index = i - 1;
-    const CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index);
+    RetainPtr<const CPDF_Dictionary> pAnnot =
+        pAnnotList->GetDictAt(annot_index);
     if (!pAnnot)
       continue;
 
-    const auto it = m_ControlMap.find(pAnnot);
+    const auto it = m_ControlMap.find(pAnnot.Get());
     if (it == m_ControlMap.end())
       continue;
 
@@ -765,7 +766,7 @@
     return;
   }
 
-  const CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> pFirstKid = pKids->GetDictAt(0);
   if (!pFirstKid)
     return;
 
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 01adfb4..be9e62b 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -374,11 +374,11 @@
 
   size_t nCount = 0;
   for (size_t i = 0; i < pKids->size(); i++) {
-    const CPDF_Dictionary* pKid = pKids->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pKid = pKids->GetDictAt(i);
     if (!pKid)
       continue;
 
-    nCount += CountNamesInternal(pKid, nLevel + 1, seen);
+    nCount += CountNamesInternal(pKid.Get(), nLevel + 1, seen);
   }
   return nCount;
 }
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
index 3427bb2..601e9b5 100644
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
@@ -255,37 +255,39 @@
   EXPECT_EQ(-5, name_tree->LookupValue(L"0.txt")->GetInteger());
 
   // Check that the node on the first level has the expected limits.
-  const CPDF_Dictionary* pKid1 =
+  RetainPtr<const CPDF_Dictionary> pKid1 =
       name_tree->GetRootForTesting()->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pKid1);
-  CheckLimitsArray(pKid1, "0.txt", "99.txt");
+  CheckLimitsArray(pKid1.Get(), "0.txt", "99.txt");
 
   // Check that the nodes on the second level has the expected limits and names.
-  const CPDF_Dictionary* pGrandKid2 = pKid1->GetArrayFor("Kids")->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> pGrandKid2 =
+      pKid1->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pGrandKid2);
-  CheckLimitsArray(pGrandKid2, "0.txt", "6.txt");
+  CheckLimitsArray(pGrandKid2.Get(), "0.txt", "6.txt");
 
-  const CPDF_Dictionary* pGrandKid3 = pKid1->GetArrayFor("Kids")->GetDictAt(1);
+  RetainPtr<const CPDF_Dictionary> pGrandKid3 =
+      pKid1->GetArrayFor("Kids")->GetDictAt(1);
   ASSERT_TRUE(pGrandKid3);
-  CheckLimitsArray(pGrandKid3, "9.txt", "99.txt");
+  CheckLimitsArray(pGrandKid3.Get(), "9.txt", "99.txt");
   const CPDF_Array* pNames = pGrandKid3->GetArrayFor("Names");
   CheckNameKeyValue(pNames, 0, "9.txt", 999);
   CheckNameKeyValue(pNames, 1, "99.txt", 99);
 
   // Check that the nodes on the third level has the expected limits and names.
-  const CPDF_Dictionary* pGreatGrandKid4 =
+  RetainPtr<const CPDF_Dictionary> pGreatGrandKid4 =
       pGrandKid2->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pGreatGrandKid4);
-  CheckLimitsArray(pGreatGrandKid4, "0.txt", "2.txt");
+  CheckLimitsArray(pGreatGrandKid4.Get(), "0.txt", "2.txt");
   pNames = pGreatGrandKid4->GetArrayFor("Names");
   CheckNameKeyValue(pNames, 0, "0.txt", -5);
   CheckNameKeyValue(pNames, 1, "1.txt", 111);
   CheckNameKeyValue(pNames, 2, "2.txt", 222);
 
-  const CPDF_Dictionary* pGreatGrandKid5 =
+  RetainPtr<const CPDF_Dictionary> pGreatGrandKid5 =
       pGrandKid2->GetArrayFor("Kids")->GetDictAt(1);
   ASSERT_TRUE(pGreatGrandKid5);
-  CheckLimitsArray(pGreatGrandKid5, "3.txt", "6.txt");
+  CheckLimitsArray(pGreatGrandKid5.Get(), "3.txt", "6.txt");
   pNames = pGreatGrandKid5->GetArrayFor("Names");
   CheckNameKeyValue(pNames, 0, "3.txt", 333);
   CheckNameKeyValue(pNames, 1, "4.txt", 444);
@@ -300,17 +302,19 @@
       CPDF_NameTree::CreateForTesting(pRootDict.Get());
 
   // Retrieve the kid dictionaries.
-  const CPDF_Dictionary* pKid1 =
+  RetainPtr<const CPDF_Dictionary> pKid1 =
       name_tree->GetRootForTesting()->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pKid1);
-  const CPDF_Dictionary* pGrandKid2 = pKid1->GetArrayFor("Kids")->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> pGrandKid2 =
+      pKid1->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pGrandKid2);
-  const CPDF_Dictionary* pGrandKid3 = pKid1->GetArrayFor("Kids")->GetDictAt(1);
+  RetainPtr<const CPDF_Dictionary> pGrandKid3 =
+      pKid1->GetArrayFor("Kids")->GetDictAt(1);
   ASSERT_TRUE(pGrandKid3);
-  const CPDF_Dictionary* pGreatGrandKid4 =
+  RetainPtr<const CPDF_Dictionary> pGreatGrandKid4 =
       pGrandKid2->GetArrayFor("Kids")->GetDictAt(0);
   ASSERT_TRUE(pGreatGrandKid4);
-  const CPDF_Dictionary* pGreatGrandKid5 =
+  RetainPtr<const CPDF_Dictionary> pGreatGrandKid5 =
       pGrandKid2->GetArrayFor("Kids")->GetDictAt(1);
   ASSERT_TRUE(pGreatGrandKid5);
 
@@ -327,7 +331,7 @@
   EXPECT_EQ(2u, pKid1->GetArrayFor("Kids")->size());
   EXPECT_TRUE(name_tree->DeleteValueAndName(4));
   EXPECT_EQ(1u, pKid1->GetArrayFor("Kids")->size());
-  CheckLimitsArray(pKid1, "1.txt", "5.txt");
+  CheckLimitsArray(pKid1.Get(), "1.txt", "5.txt");
 
   // Delete the name "2.txt", and check that its node does not get deleted, its
   // node's limits get updated, and no other limits get updated.
@@ -338,9 +342,9 @@
   EXPECT_EQ(4u, pGreatGrandKid4->GetArrayFor("Names")->size());
   EXPECT_TRUE(name_tree->DeleteValueAndName(1));
   EXPECT_EQ(2u, pGreatGrandKid4->GetArrayFor("Names")->size());
-  CheckLimitsArray(pGreatGrandKid4, "1.txt", "1.txt");
-  CheckLimitsArray(pGrandKid2, "1.txt", "5.txt");
-  CheckLimitsArray(pKid1, "1.txt", "5.txt");
+  CheckLimitsArray(pGreatGrandKid4.Get(), "1.txt", "1.txt");
+  CheckLimitsArray(pGrandKid2.Get(), "1.txt", "5.txt");
+  CheckLimitsArray(pKid1.Get(), "1.txt", "5.txt");
 
   // Delete the name "1.txt", and check that its node gets deleted, and its
   // parent's and gradparent's limits get updated.
@@ -351,8 +355,8 @@
   EXPECT_EQ(2u, pGrandKid2->GetArrayFor("Kids")->size());
   EXPECT_TRUE(name_tree->DeleteValueAndName(0));
   EXPECT_EQ(1u, pGrandKid2->GetArrayFor("Kids")->size());
-  CheckLimitsArray(pGrandKid2, "3.txt", "5.txt");
-  CheckLimitsArray(pKid1, "3.txt", "5.txt");
+  CheckLimitsArray(pGrandKid2.Get(), "3.txt", "5.txt");
+  CheckLimitsArray(pKid1.Get(), "3.txt", "5.txt");
 
   // Delete the name "3.txt", and check that its node does not get deleted, and
   // its node's, its parent's, and its grandparent's limits get updated.
@@ -363,9 +367,9 @@
   EXPECT_EQ(4u, pGreatGrandKid5->GetArrayFor("Names")->size());
   EXPECT_TRUE(name_tree->DeleteValueAndName(0));
   EXPECT_EQ(2u, pGreatGrandKid5->GetArrayFor("Names")->size());
-  CheckLimitsArray(pGreatGrandKid5, "5.txt", "5.txt");
-  CheckLimitsArray(pGrandKid2, "5.txt", "5.txt");
-  CheckLimitsArray(pKid1, "5.txt", "5.txt");
+  CheckLimitsArray(pGreatGrandKid5.Get(), "5.txt", "5.txt");
+  CheckLimitsArray(pGrandKid2.Get(), "5.txt", "5.txt");
+  CheckLimitsArray(pKid1.Get(), "5.txt", "5.txt");
 
   // Delete the name "5.txt", and check that all nodes in the tree get deleted
   // since they are now all empty.
diff --git a/core/fpdfdoc/cpdf_numbertree.cpp b/core/fpdfdoc/cpdf_numbertree.cpp
index 257db4b..a2c09fc 100644
--- a/core/fpdfdoc/cpdf_numbertree.cpp
+++ b/core/fpdfdoc/cpdf_numbertree.cpp
@@ -35,11 +35,11 @@
     return nullptr;
 
   for (size_t i = 0; i < pKids->size(); i++) {
-    const CPDF_Dictionary* pKid = pKids->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pKid = pKids->GetDictAt(i);
     if (!pKid)
       continue;
 
-    const CPDF_Object* pFound = SearchNumberNode(pKid, num);
+    const CPDF_Object* pFound = SearchNumberNode(pKid.Get(), num);
     if (pFound)
       return pFound;
   }
diff --git a/core/fpdfdoc/cpdf_structtree.cpp b/core/fpdfdoc/cpdf_structtree.cpp
index 1cf2c3b..fdecd3b 100644
--- a/core/fpdfdoc/cpdf_structtree.cpp
+++ b/core/fpdfdoc/cpdf_structtree.cpp
@@ -77,8 +77,11 @@
 
   StructElementMap element_map;
   for (size_t i = 0; i < pParentArray->size(); i++) {
-    if (const CPDF_Dictionary* pParent = pParentArray->GetDictAt(i))
-      AddPageNode(pParent, &element_map, 0);
+    RetainPtr<const CPDF_Dictionary> pParent = pParentArray->GetDictAt(i);
+    if (pParent) {
+      // TODO(tsepez): pass moved retained object.
+      AddPageNode(pParent.Get(), &element_map, 0);
+    }
   }
 }
 
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index 53e5ff2..eb7938a 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -190,7 +190,7 @@
       GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder);
   if (pBorder) {
     if (pBorder->size() >= 4) {
-      const CPDF_Array* pDP = pBorder->GetArrayAt(3);
+      RetainPtr<const CPDF_Array> pDP = pBorder->GetArrayAt(3);
       if (pDP && pDP->size() > 0)
         return BorderStyle::kDash;
     }
diff --git a/fpdfsdk/cpdfsdk_interactiveform.cpp b/fpdfsdk/cpdfsdk_interactiveform.cpp
index 23f1bdf..907636e 100644
--- a/fpdfsdk/cpdfsdk_interactiveform.cpp
+++ b/fpdfsdk/cpdfsdk_interactiveform.cpp
@@ -87,7 +87,7 @@
 
   fxcrt::ostringstream encoded_data;
   for (uint32_t i = 0; i < pFields->size(); i++) {
-    const CPDF_Dictionary* pField = pFields->GetDictAt(i);
+    RetainPtr<const CPDF_Dictionary> pField = pFields->GetDictAt(i);
     if (!pField)
       continue;
     WideString name = pField->GetUnicodeTextFor("T");
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index c57861b..ebc0343 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -896,7 +896,7 @@
   if (!ink_list)
     return 0;
 
-  const CPDF_Array* path = ink_list->GetArrayAt(path_index);
+  RetainPtr<const CPDF_Array> path = ink_list->GetArrayAt(path_index);
   if (!path)
     return 0;
 
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index d601f34..94e466d 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -3012,7 +3012,8 @@
   EXPECT_EQ(1u, descendant_array->size());
 
   // Check the CIDFontDict
-  const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> cidfont_dict =
+      descendant_array->GetDictAt(0);
   EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
   EXPECT_EQ("CIDFontType0", cidfont_dict->GetNameFor("Subtype"));
   EXPECT_EQ("Tinos-Regular", cidfont_dict->GetNameFor("BaseFont"));
@@ -3028,7 +3029,7 @@
   EXPECT_EQ(CPDF_Object::kString, ordering->GetType());
   EXPECT_EQ("Identity", ordering->GetString());
   EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
-  CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, span);
+  CheckFontDescriptor(cidfont_dict.Get(), FPDF_FONT_TYPE1, false, false, span);
 
   // Check widths
   const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
@@ -3060,7 +3061,8 @@
   EXPECT_EQ(1u, descendant_array->size());
 
   // Check the CIDFontDict
-  const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
+  RetainPtr<const CPDF_Dictionary> cidfont_dict =
+      descendant_array->GetDictAt(0);
   EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
   EXPECT_EQ("CIDFontType2", cidfont_dict->GetNameFor("Subtype"));
   EXPECT_EQ("Arimo-Italic", cidfont_dict->GetNameFor("BaseFont"));
@@ -3070,7 +3072,8 @@
   EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
   EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
   EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
-  CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, span);
+  CheckFontDescriptor(cidfont_dict.Get(), FPDF_FONT_TRUETYPE, false, true,
+                      span);
 
   // Check widths
   const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index 6ae5f50..3e136dc 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -626,8 +626,8 @@
     const CPDF_Array* pSrcContentArray = ToArray(pSrcContentObj);
     if (pSrcContentArray) {
       for (size_t i = 0; i < pSrcContentArray->size(); ++i) {
-        const CPDF_Stream* pStream = pSrcContentArray->GetStreamAt(i);
-        auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
+        RetainPtr<const CPDF_Stream> pStream = pSrcContentArray->GetStreamAt(i);
+        auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream.Get());
         pAcc->LoadAllDataFiltered();
         bsSrcContentStream += ByteString(pAcc->GetSpan());
         bsSrcContentStream += "\n";
diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp
index 86af669..6a291fc 100644
--- a/fpdfsdk/fpdf_structtree.cpp
+++ b/fpdfsdk/fpdf_structtree.cpp
@@ -166,7 +166,9 @@
     const CPDF_Array* array = attr_obj->AsArray();
     if (index < 0 || static_cast<size_t>(index) >= array->size())
       return nullptr;
-    return FPDFStructElementAttrFromCPDFDictionary(array->GetDictAt(index));
+    // TODO(tsepez): should embedder take a reference here?
+    return FPDFStructElementAttrFromCPDFDictionary(
+        array->GetDictAt(index).Get());
   }
 
   return nullptr;
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 4d79fc2..de2bfef 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -140,11 +140,12 @@
     if (!name)
       continue;
 
-    const CPDF_Stream* data = xfa_array->GetStreamAt(i + 1);
+    RetainPtr<const CPDF_Stream> data = xfa_array->GetStreamAt(i + 1);
     if (!data)
       continue;
 
-    packets.push_back({name->GetString(), data});
+    // TODO(tsepez): push retained objects.
+    packets.push_back({name->GetString(), data.Get()});
   }
   return packets;
 }
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 2c4d766..662bb0a 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -75,8 +75,11 @@
   if (pElementXFA->IsArray()) {
     const CPDF_Array* pXFAArray = pElementXFA->AsArray();
     for (size_t i = 0; i < pXFAArray->size() / 2; i++) {
-      if (const CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1))
-        xfaStreams.push_back(pStream);
+      RetainPtr<const CPDF_Stream> pStream = pXFAArray->GetStreamAt(i * 2 + 1);
+      if (pStream) {
+        // TODO(tsepez): push retained objects.
+        xfaStreams.push_back(pStream.Get());
+      }
     }
   } else if (pElementXFA->IsStream()) {
     xfaStreams.push_back(pElementXFA->AsStream());