Fix retained argument TODOs, part 2.

Use retained arguments in CPDF_Dictionary.

Change-Id: I67885e26097e6e80cb5bac0a901f818d81e1423b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98591
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 1f22bd0..e7d49ec 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -27,8 +27,8 @@
 
 const int kMaxPageLevel = 1024;
 
-int CountPages(CPDF_Dictionary* pPages,
-               std::set<CPDF_Dictionary*>* visited_pages) {
+int CountPages(RetainPtr<CPDF_Dictionary> pPages,
+               std::set<RetainPtr<CPDF_Dictionary>>* visited_pages) {
   int count = pPages->GetIntegerFor("Count");
   if (count > 0 && count < CPDF_Document::kPageMaxNum)
     return count;
@@ -38,12 +38,13 @@
   count = 0;
   for (size_t i = 0; i < pKidList->size(); i++) {
     RetainPtr<CPDF_Dictionary> pKid = pKidList->GetMutableDictAt(i);
-    if (!pKid || pdfium::Contains(*visited_pages, pKid.Get()))
+    if (!pKid || pdfium::Contains(*visited_pages, pKid))
       continue;
     if (pKid->KeyExist("Kids")) {
       // Use |visited_pages| to help detect circular references of pages.
-      ScopedSetInsertion<CPDF_Dictionary*> local_add(visited_pages, pKid.Get());
-      count += CountPages(pKid.Get(), visited_pages);
+      ScopedSetInsertion<RetainPtr<CPDF_Dictionary>> local_add(visited_pages,
+                                                               pKid);
+      count += CountPages(std::move(pKid), visited_pages);
     } else {
       // This page is a leaf node.
       count++;
@@ -186,13 +187,13 @@
   m_PageList[first_page_num] = objnum;
 }
 
-CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage,
-                                                 int* nPagesToGo,
-                                                 size_t level) {
+RetainPtr<CPDF_Dictionary> CPDF_Document::TraversePDFPages(int iPage,
+                                                           int* nPagesToGo,
+                                                           size_t level) {
   if (*nPagesToGo < 0 || m_bReachedMaxPageLevel)
     return nullptr;
 
-  CPDF_Dictionary* pPages = m_pTreeTraversal[level].first;
+  RetainPtr<CPDF_Dictionary> pPages = m_pTreeTraversal[level].first;
   RetainPtr<CPDF_Array> pKidList = pPages->GetMutableArrayFor("Kids");
   if (!pKidList) {
     m_pTreeTraversal.pop_back();
@@ -226,13 +227,13 @@
       (*nPagesToGo)--;
       m_pTreeTraversal[level].second++;
       if (*nPagesToGo == 0) {
-        page = pKid;
+        page = std::move(pKid);
         break;
       }
     } else {
       // If the vector has size level+1, the child is not in yet
       if (m_pTreeTraversal.size() == level + 1)
-        m_pTreeTraversal.push_back(std::make_pair(pKid.Get(), 0));
+        m_pTreeTraversal.push_back(std::make_pair(std::move(pKid), 0));
       // Now m_pTreeTraversal[level+1] should exist and be equal to pKid.
       CPDF_Dictionary* pageKid = TraversePDFPages(iPage, nPagesToGo, level + 1);
       // Check if child was completely processed, i.e. it popped itself out
@@ -248,7 +249,7 @@
   }
   if (m_pTreeTraversal[level].second == pKidList->size())
     m_pTreeTraversal.pop_back();
-  return page.Get();
+  return page;
 }
 
 void CPDF_Document::ResetTraversal() {
@@ -268,15 +269,14 @@
   return error;
 }
 
-// TODO(tsepez): return retained references.
-const CPDF_Dictionary* CPDF_Document::GetPagesDict() const {
+RetainPtr<const CPDF_Dictionary> CPDF_Document::GetPagesDict() const {
   const CPDF_Dictionary* pRoot = GetRoot();
-  return pRoot ? pRoot->GetDictFor("Pages").Get() : nullptr;
+  return pRoot ? pRoot->GetDictFor("Pages") : nullptr;
 }
 
-CPDF_Dictionary* CPDF_Document::GetPagesDict() {
-  return const_cast<CPDF_Dictionary*>(
-      static_cast<const CPDF_Document*>(this)->GetPagesDict());
+RetainPtr<CPDF_Dictionary> CPDF_Document::GetMutablePagesDict() {
+  return pdfium::WrapRetain(
+      const_cast<CPDF_Dictionary*>(this->GetPagesDict().Get()));
 }
 
 bool CPDF_Document::IsPageLoaded(int iPage) const {
@@ -295,19 +295,18 @@
       return result;
   }
 
-  CPDF_Dictionary* pPages = GetPagesDict();
+  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
   if (!pPages)
     return nullptr;
 
   if (m_pTreeTraversal.empty()) {
     ResetTraversal();
-    m_pTreeTraversal.push_back(std::make_pair(pPages, 0));
+    m_pTreeTraversal.push_back(std::make_pair(std::move(pPages), 0));
   }
   int nPagesToGo = iPage - m_iNextPageToTraverse + 1;
-  // TODO(tsepez): return retained page from TraversePDFPages().
-  CPDF_Dictionary* pPage = TraversePDFPages(iPage, &nPagesToGo, 0);
+  RetainPtr<CPDF_Dictionary> pPage = TraversePDFPages(iPage, &nPagesToGo, 0);
   m_iNextPageToTraverse = iPage + 1;
-  return pdfium::WrapRetain(pPage);
+  return pPage;
 }
 
 RetainPtr<CPDF_Dictionary> CPDF_Document::GetMutablePageDictionary(int iPage) {
@@ -325,11 +324,10 @@
   return m_pCodecContext.get();
 }
 
-// TODO(tsepez): return retained reference.
-CPDF_Stream* CPDF_Document::CreateModifiedAPStream() {
+RetainPtr<CPDF_Stream> CPDF_Document::CreateModifiedAPStream() {
   auto stream = NewIndirect<CPDF_Stream>();
   m_ModifiedAPStreamIDs.insert(stream->GetObjNum());
-  return stream.Get();
+  return stream;
 }
 
 bool CPDF_Document::IsModifiedAPStream(const CPDF_Stream* stream) const {
@@ -370,16 +368,15 @@
 }
 
 int CPDF_Document::RetrievePageCount() {
-  CPDF_Dictionary* pPages = GetPagesDict();
+  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
   if (!pPages)
     return 0;
 
   if (!pPages->KeyExist("Kids"))
     return 1;
 
-  std::set<CPDF_Dictionary*> visited_pages;
-  visited_pages.insert(pPages);
-  return CountPages(pPages, &visited_pages);
+  std::set<RetainPtr<CPDF_Dictionary>> visited_pages = {pPages};
+  return CountPages(std::move(pPages), &visited_pages);
 }
 
 uint32_t CPDF_Document::GetUserPermissions() const {
@@ -407,18 +404,19 @@
   auto pDict = NewIndirect<CPDF_Dictionary>();
   pDict->SetNewFor<CPDF_Name>("Type", "Page");
   uint32_t dwObjNum = pDict->GetObjNum();
-  if (!InsertNewPage(iPage, pDict.Get())) {
+  if (!InsertNewPage(iPage, pDict)) {
     DeleteIndirectObject(dwObjNum);
     return nullptr;
   }
   return pDict;
 }
 
-bool CPDF_Document::InsertDeletePDFPage(CPDF_Dictionary* pPages,
-                                        int nPagesToGo,
-                                        CPDF_Dictionary* pPageDict,
-                                        bool bInsert,
-                                        std::set<CPDF_Dictionary*>* pVisited) {
+bool CPDF_Document::InsertDeletePDFPage(
+    RetainPtr<CPDF_Dictionary> pPages,
+    int nPagesToGo,
+    RetainPtr<CPDF_Dictionary> pPageDict,
+    bool bInsert,
+    std::set<RetainPtr<CPDF_Dictionary>>* pVisited) {
   RetainPtr<CPDF_Array> pKidList = pPages->GetMutableArrayFor("Kids");
   if (!pKidList)
     return false;
@@ -447,11 +445,11 @@
       nPagesToGo -= nPages;
       continue;
     }
-    if (pdfium::Contains(*pVisited, pKid.Get()))
+    if (pdfium::Contains(*pVisited, pKid))
       return false;
 
-    ScopedSetInsertion<CPDF_Dictionary*> insertion(pVisited, pKid.Get());
-    if (!InsertDeletePDFPage(pKid.Get(), nPagesToGo, pPageDict, bInsert,
+    ScopedSetInsertion<RetainPtr<CPDF_Dictionary>> insertion(pVisited, pKid);
+    if (!InsertDeletePDFPage(std::move(pKid), nPagesToGo, pPageDict, bInsert,
                              pVisited)) {
       return false;
     }
@@ -462,7 +460,8 @@
   return true;
 }
 
-bool CPDF_Document::InsertNewPage(int iPage, CPDF_Dictionary* pPageDict) {
+bool CPDF_Document::InsertNewPage(int iPage,
+                                  RetainPtr<CPDF_Dictionary> pPageDict) {
   RetainPtr<CPDF_Dictionary> pRoot = GetMutableRoot();
   if (!pRoot)
     return false;
@@ -482,8 +481,8 @@
     pPageDict->SetNewFor<CPDF_Reference>("Parent", this, pPages->GetObjNum());
     ResetTraversal();
   } else {
-    std::set<CPDF_Dictionary*> stack = {pPages.Get()};
-    if (!InsertDeletePDFPage(pPages.Get(), iPage, pPageDict, true, &stack))
+    std::set<RetainPtr<CPDF_Dictionary>> stack = {pPages};
+    if (!InsertDeletePDFPage(std::move(pPages), iPage, pPageDict, true, &stack))
       return false;
   }
   m_PageList.insert(m_PageList.begin() + iPage, pPageDict->GetObjNum());
@@ -511,7 +510,7 @@
 }
 
 void CPDF_Document::DeletePage(int iPage) {
-  CPDF_Dictionary* pPages = GetPagesDict();
+  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
   if (!pPages)
     return;
 
@@ -519,8 +518,8 @@
   if (iPage < 0 || iPage >= nPages)
     return;
 
-  std::set<CPDF_Dictionary*> stack = {pPages};
-  if (!InsertDeletePDFPage(pPages, iPage, nullptr, false, &stack))
+  std::set<RetainPtr<CPDF_Dictionary>> stack = {pPages};
+  if (!InsertDeletePDFPage(std::move(pPages), iPage, nullptr, false, &stack))
     return;
 
   m_PageList.erase(m_PageList.begin() + iPage);
diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h
index 861948e..6fe8d53 100644
--- a/core/fpdfapi/parser/cpdf_document.h
+++ b/core/fpdfapi/parser/cpdf_document.h
@@ -116,7 +116,7 @@
   }
 
   // Behaves like NewIndirect<CPDF_Stream>(), but keeps track of the new stream.
-  CPDF_Stream* CreateModifiedAPStream();
+  RetainPtr<CPDF_Stream> CreateModifiedAPStream();
 
   // Returns whether CreateModifiedAPStream() created `stream`.
   bool IsModifiedAPStream(const CPDF_Stream* stream) const;
@@ -161,18 +161,22 @@
 
   // Retrieve page count information by getting count value from the tree nodes
   int RetrievePageCount();
+
   // When this method is called, m_pTreeTraversal[level] exists.
-  CPDF_Dictionary* TraversePDFPages(int iPage, int* nPagesToGo, size_t level);
+  RetainPtr<CPDF_Dictionary> TraversePDFPages(int iPage,
+                                              int* nPagesToGo,
+                                              size_t level);
 
-  const CPDF_Dictionary* GetPagesDict() const;
-  CPDF_Dictionary* GetPagesDict();
+  RetainPtr<const CPDF_Dictionary> GetPagesDict() const;
+  RetainPtr<CPDF_Dictionary> GetMutablePagesDict();
 
-  bool InsertDeletePDFPage(CPDF_Dictionary* pPages,
+  bool InsertDeletePDFPage(RetainPtr<CPDF_Dictionary> pPages,
                            int nPagesToGo,
-                           CPDF_Dictionary* pPageDict,
+                           RetainPtr<CPDF_Dictionary> pPageDict,
                            bool bInsert,
-                           std::set<CPDF_Dictionary*>* pVisited);
-  bool InsertNewPage(int iPage, CPDF_Dictionary* pPageDict);
+                           std::set<RetainPtr<CPDF_Dictionary>>* pVisited);
+
+  bool InsertNewPage(int iPage, RetainPtr<CPDF_Dictionary> pPageDict);
   void ResetTraversal();
   CPDF_Parser::Error HandleLoadResult(CPDF_Parser::Error error);
 
@@ -184,7 +188,7 @@
   // vector corresponds to the level being described. The pair contains a
   // pointer to the dictionary being processed at the level, and an index of the
   // of the child being processed within the dictionary's /Kids array.
-  std::vector<std::pair<CPDF_Dictionary*, size_t>> m_pTreeTraversal;
+  std::vector<std::pair<RetainPtr<CPDF_Dictionary>, size_t>> m_pTreeTraversal;
 
   // True if the CPDF_Parser succeeded without having to rebuild the cross
   // reference table.