Return retained objects from indirect object holder, part 3.

Pass retained results back thru CPDF_Object::GetDirect().

-- flip virtual method and non-virtual wrapper to avoid WrapRetain().

Change-Id: I2cb348b02e34d90dd331f8e39e6878950d7a73aa
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97313
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 f582b75..30911bd 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -109,7 +109,7 @@
 
 const CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t index) const {
   const CPDF_Object* pObj = GetObjectAt(index);
-  return pObj ? pObj->GetDirect() : nullptr;
+  return pObj ? pObj->GetDirect().Get() : nullptr;
 }
 
 ByteString CPDF_Array::GetStringAt(size_t index) const {
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index 8afff3b..a92ffea 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -84,7 +84,7 @@
 const CPDF_Object* CPDF_Dictionary::GetDirectObjectFor(
     const ByteString& key) const {
   const CPDF_Object* p = GetObjectFor(key);
-  return p ? p->GetDirect() : nullptr;
+  return p ? p->GetDirect().Get() : nullptr;
 }
 
 RetainPtr<CPDF_Object> CPDF_Dictionary::GetMutableDirectObjectFor(
@@ -106,7 +106,7 @@
 WideString CPDF_Dictionary::GetUnicodeTextFor(const ByteString& key) const {
   const CPDF_Object* p = GetObjectFor(key);
   if (const CPDF_Reference* pRef = ToReference(p))
-    p = pRef->GetDirect();
+    p = pRef->GetDirect().Get();
   return p ? p->GetUnicodeText() : WideString();
 }
 
diff --git a/core/fpdfapi/parser/cpdf_name.h b/core/fpdfapi/parser/cpdf_name.h
index 8379db6..5476f44 100644
--- a/core/fpdfapi/parser/cpdf_name.h
+++ b/core/fpdfapi/parser/cpdf_name.h
@@ -41,4 +41,8 @@
   return obj ? obj->AsName() : nullptr;
 }
 
+inline RetainPtr<const CPDF_Name> ToName(RetainPtr<const CPDF_Object> obj) {
+  return RetainPtr<const CPDF_Name>(ToName(obj.Get()));
+}
+
 #endif  // CORE_FPDFAPI_PARSER_CPDF_NAME_H_
diff --git a/core/fpdfapi/parser/cpdf_object.cpp b/core/fpdfapi/parser/cpdf_object.cpp
index 92fd602..0f96704 100644
--- a/core/fpdfapi/parser/cpdf_object.cpp
+++ b/core/fpdfapi/parser/cpdf_object.cpp
@@ -33,11 +33,11 @@
 }
 
 RetainPtr<CPDF_Object> CPDF_Object::GetMutableDirect() {
-  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetDirect()));
+  return pdfium::WrapRetain(this);
 }
 
-const CPDF_Object* CPDF_Object::GetDirect() const {
-  return this;
+RetainPtr<const CPDF_Object> CPDF_Object::GetDirect() const {
+  return const_cast<CPDF_Object*>(this)->GetMutableDirect();
 }
 
 RetainPtr<CPDF_Object> CPDF_Object::CloneObjectNonCyclic(bool bDirect) const {
diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h
index 86d7f54..b61dfa3 100644
--- a/core/fpdfapi/parser/cpdf_object.h
+++ b/core/fpdfapi/parser/cpdf_object.h
@@ -59,7 +59,7 @@
   // copied to the object it points to directly.
   virtual RetainPtr<CPDF_Object> CloneDirectObject() const;
 
-  virtual const CPDF_Object* GetDirect() const;
+  virtual RetainPtr<CPDF_Object> GetMutableDirect();
   virtual ByteString GetString() const;
   virtual WideString GetUnicodeText() const;
   virtual float GetNumber() const;
@@ -96,8 +96,8 @@
   virtual RetainPtr<CPDF_Reference> MakeReference(
       CPDF_IndirectObjectHolder* holder) const;
 
-  RetainPtr<CPDF_Object> GetMutableDirect();    // Wraps virtual method.
-  RetainPtr<CPDF_Dictionary> GetMutableDict();  // Wraps virtual method.
+  RetainPtr<const CPDF_Object> GetDirect() const;  // Wraps virtual method.
+  RetainPtr<CPDF_Dictionary> GetMutableDict();     // Wraps virtual method.
 
   // Const methods wrapping non-const virtual As*() methods.
   const CPDF_Array* AsArray() const;
diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp
index 59e11b0..47af7fb 100644
--- a/core/fpdfapi/parser/cpdf_reference.cpp
+++ b/core/fpdfapi/parser/cpdf_reference.cpp
@@ -21,22 +21,22 @@
 }
 
 ByteString CPDF_Reference::GetString() const {
-  const CPDF_Object* obj = SafeGetDirect();
+  RetainPtr<const CPDF_Object> obj = SafeGetDirect();
   return obj ? obj->GetString() : ByteString();
 }
 
 float CPDF_Reference::GetNumber() const {
-  const CPDF_Object* obj = SafeGetDirect();
+  RetainPtr<const CPDF_Object> obj = SafeGetDirect();
   return obj ? obj->GetNumber() : 0;
 }
 
 int CPDF_Reference::GetInteger() const {
-  const CPDF_Object* obj = SafeGetDirect();
+  RetainPtr<const CPDF_Object> obj = SafeGetDirect();
   return obj ? obj->GetInteger() : 0;
 }
 
 const CPDF_Dictionary* CPDF_Reference::GetDict() const {
-  const CPDF_Object* obj = SafeGetDirect();
+  RetainPtr<const CPDF_Object> obj = SafeGetDirect();
   return obj ? obj->GetDict() : nullptr;
 }
 
@@ -52,17 +52,17 @@
     bool bDirect,
     std::set<const CPDF_Object*>* pVisited) const {
   pVisited->insert(this);
-  if (bDirect) {
-    auto* pDirect = GetDirect();
-    return pDirect && !pdfium::Contains(*pVisited, pDirect)
-               ? pDirect->CloneNonCyclic(true, pVisited)
-               : nullptr;
+  if (!bDirect) {
+    return pdfium::MakeRetain<CPDF_Reference>(m_pObjList.Get(), m_RefObjNum);
   }
-  return pdfium::MakeRetain<CPDF_Reference>(m_pObjList.Get(), m_RefObjNum);
+  RetainPtr<const CPDF_Object> pDirect = GetDirect();
+  return pDirect && !pdfium::Contains(*pVisited, pDirect.Get())
+             ? pDirect->CloneNonCyclic(true, pVisited)
+             : nullptr;
 }
 
-const CPDF_Object* CPDF_Reference::SafeGetDirect() const {
-  const CPDF_Object* obj = GetDirect();
+RetainPtr<const CPDF_Object> CPDF_Reference::SafeGetDirect() const {
+  RetainPtr<const CPDF_Object> obj = GetDirect();
   return (obj && !obj->IsReference()) ? obj : nullptr;
 }
 
@@ -71,8 +71,8 @@
   m_RefObjNum = objnum;
 }
 
-const CPDF_Object* CPDF_Reference::GetDirect() const {
-  return m_pObjList ? m_pObjList->GetOrParseIndirectObject(m_RefObjNum).Get()
+RetainPtr<CPDF_Object> CPDF_Reference::GetMutableDirect() {
+  return m_pObjList ? m_pObjList->GetOrParseIndirectObject(m_RefObjNum)
                     : nullptr;
 }
 
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index 6a22fec..f52e834 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -22,7 +22,7 @@
   // CPDF_Object:
   Type GetType() const override;
   RetainPtr<CPDF_Object> Clone() const override;
-  const CPDF_Object* GetDirect() const override;
+  RetainPtr<CPDF_Object> GetMutableDirect() override;
   ByteString GetString() const override;
   float GetNumber() const override;
   int GetInteger() const override;
@@ -43,7 +43,7 @@
   RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
-  const CPDF_Object* SafeGetDirect() const;
+  RetainPtr<const CPDF_Object> SafeGetDirect() const;
 
   UnownedPtr<CPDF_IndirectObjectHolder> m_pObjList;
   uint32_t m_RefObjNum;
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index e16a817..e3a5209 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -169,8 +169,9 @@
 
   CPDF_DictionaryLocker locker(dict);
   for (const auto& it : locker) {
-    const CPDF_Dictionary* entry = ToDictionary(it.second->GetDirect());
-    if (!ValidateDictType(entry, type))
+    RetainPtr<const CPDF_Dictionary> entry =
+        ToDictionary(it.second->GetDirect());
+    if (!ValidateDictType(entry.Get(), type))
       return false;
   }
   return true;
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 7f238da..89c419b 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -185,8 +185,9 @@
   CPDF_DictionaryLocker locker(pFonts);
   for (const auto& it : locker) {
     const ByteString& csKey = it.first;
-    const CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
-    if (!ValidateDictType(pElement, "Font"))
+    RetainPtr<const CPDF_Dictionary> pElement =
+        ToDictionary(it.second->GetDirect());
+    if (!ValidateDictType(pElement.Get(), "Font"))
       continue;
     if (pFont->GetFontDict() == pElement) {
       *csNameTag = csKey;
diff --git a/core/fpdfdoc/cpdf_pagelabel.cpp b/core/fpdfdoc/cpdf_pagelabel.cpp
index 909f77d..5c1a475 100644
--- a/core/fpdfdoc/cpdf_pagelabel.cpp
+++ b/core/fpdfdoc/cpdf_pagelabel.cpp
@@ -95,10 +95,11 @@
     return absl::nullopt;
 
   CPDF_NumberTree numberTree(pLabels);
-  const CPDF_Object* pValue = nullptr;
+  RetainPtr<const CPDF_Object> pValue;
   int n = nPage;
   while (n >= 0) {
-    pValue = numberTree.LookupValue(n);
+    // TODO(tsepez): make LookupValue() return retained object.
+    pValue = pdfium::WrapRetain(numberTree.LookupValue(n));
     if (pValue)
       break;
     n--;
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 7092a09..568b9b4 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -71,7 +71,7 @@
   if (!pFormDict->KeyExist(pdfium::page_object::kType))
     return false;
 
-  const CPDF_Name* pName =
+  RetainPtr<const CPDF_Name> pName =
       ToName(pFormDict->GetObjectFor(pdfium::page_object::kType)->GetDirect());
   return pName && pName->GetString() == "Page";
 }
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index c5faa04..6ae5f50 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -158,12 +158,12 @@
     return nullptr;
   }
 
-  const CPDF_Name* pName =
+  RetainPtr<const CPDF_Name> pName =
       ToName(pDict->GetObjectFor(pdfium::page_object::kType)->GetDirect());
   if (!pName || pName->GetString() != "Page")
     return nullptr;
 
-  const CPDF_Dictionary* pp = ToDictionary(
+  RetainPtr<const CPDF_Dictionary> pp = ToDictionary(
       pDict->GetObjectFor(pdfium::page_object::kParent)->GetDirect());
   if (!pp)
     return nullptr;
@@ -343,7 +343,7 @@
   if (dwNewObjNum)
     return dwNewObjNum;
 
-  const CPDF_Object* pDirect = pRef->GetDirect();
+  RetainPtr<const CPDF_Object> pDirect = pRef->GetDirect();
   if (!pDirect)
     return 0;
 
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 1466b40..dc426bc 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -120,13 +120,14 @@
   if (!xfa_object)
     return packets;
 
-  const CPDF_Stream* xfa_stream = ToStream(xfa_object->GetDirect());
+  RetainPtr<const CPDF_Stream> xfa_stream = ToStream(xfa_object->GetDirect());
   if (xfa_stream) {
-    packets.push_back({"", xfa_stream});
+    // TODO(tsepez): push retained objects.
+    packets.push_back({"", xfa_stream.Get()});
     return packets;
   }
 
-  const CPDF_Array* xfa_array = ToArray(xfa_object->GetDirect());
+  RetainPtr<const CPDF_Array> xfa_array = ToArray(xfa_object->GetDirect());
   if (!xfa_array)
     return packets;
 
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index e09aa39..c2340c9 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -476,7 +476,7 @@
       if (!pPDFObj->IsReference())
         continue;
 
-      const CPDF_Stream* pStream = ToStream(pPDFObj->GetDirect());
+      RetainPtr<const CPDF_Stream> pStream = ToStream(pPDFObj->GetDirect());
       if (!pStream)
         continue;
       if (pPrePDFObj->GetString() == "form") {
@@ -503,7 +503,8 @@
         ByteString content = ByteString::Format(kFormat, bPath.c_str());
         fileWrite->WriteString(content.AsStringView());
       }
-      auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
+      // TODO(tsepez): stream acc should take a retained object.
+      auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream.Get());
       pAcc->LoadAllDataFiltered();
       pdfium::span<const uint8_t> span = pAcc->GetSpan();
       fileWrite->WriteBlock(span.data(), span.size());