Add RetainPtr<>::BackPointer() method.

Return an UnownedPtr from a RetainPtr. Prefered over calls to Get(),
since calls to Get() are almost always avoidable except in this one
circumstance where we would otherwise have a cycle of RetainPtr.

Use it in one place and remove some Get() calls along the way. In turn,
keep a RetainPtr in one class where we didn't really need a backpointer.

Change-Id: I89bb6291dc71a62d6aa989858c6e62aaa599ee17
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53617
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
index e5cdb70..6dc8d00 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
@@ -40,7 +40,7 @@
   if (current_status_ == CPDF_DataAvail::DataAvailable)
     return CPDF_DataAvail::DataAvailable;
 
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   while (true) {
     bool check_result = false;
     switch (current_state_) {
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index d276fc1..d80feef 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -174,7 +174,7 @@
 
 bool CPDF_DataAvail::CheckAndLoadAllXref() {
   if (!m_pCrossRefAvail) {
-    const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+    const CPDF_ReadValidator::Session read_session(GetValidator());
     const FX_FILESIZE last_xref_offset = m_parser.ParseStartXRef();
     if (GetValidator()->has_read_problems())
       return false;
@@ -222,7 +222,7 @@
 
   std::unique_ptr<CPDF_Object> pRet;
   if (pParser) {
-    const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+    const CPDF_ReadValidator::Session read_session(GetValidator());
     pRet = pParser->ParseIndirectObject(objnum);
     if (GetValidator()->has_read_problems())
       return nullptr;
@@ -241,7 +241,7 @@
     return true;
   }
 
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   m_parser.ParseIndirectObject(dwInfoObjNum);
   if (GetValidator()->has_read_problems())
     return false;
@@ -257,7 +257,7 @@
     return true;
   }
 
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   m_pRoot = ToDictionary(m_parser.ParseIndirectObject(dwRootObjNum));
   if (GetValidator()->has_read_problems())
     return false;
@@ -436,7 +436,7 @@
 }
 
 bool CPDF_DataAvail::CheckHintTables() {
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   m_pHintTables =
       CPDF_HintTables::Parse(GetSyntaxParser(), m_pLinearized.get());
 
@@ -484,7 +484,7 @@
   if (m_bHeaderAvail)
     return DocAvailStatus::DataAvailable;
 
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   const Optional<FX_FILESIZE> header_offset = GetHeaderOffset(GetValidator());
   if (GetValidator()->has_read_problems())
     return DocAvailStatus::DataNotAvailable;
@@ -813,7 +813,7 @@
 
       auto page_num_obj = std::make_pair(
           dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>(
-                      GetValidator().Get(), m_pDocument.Get(), pPageDict));
+                      GetValidator(), m_pDocument.Get(), pPageDict));
 
       CPDF_PageObjectAvail* page_obj_avail =
           m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get();
@@ -865,7 +865,7 @@
   {
     auto page_num_obj = std::make_pair(
         dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>(
-                    GetValidator().Get(), m_pDocument.Get(), pPageDict));
+                    GetValidator(), m_pDocument.Get(), pPageDict));
     CPDF_PageObjectAvail* page_obj_avail =
         m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get();
     const DocAvailStatus status = page_obj_avail->CheckAvail();
@@ -886,7 +886,7 @@
 CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckResources(
     const CPDF_Dictionary* page) {
   ASSERT(page);
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   const CPDF_Object* resources = GetResourceObject(page);
   if (GetValidator()->has_read_problems())
     return DocAvailStatus::DataNotAvailable;
@@ -897,9 +897,8 @@
   CPDF_PageObjectAvail* resource_avail =
       m_PagesResourcesAvail
           .insert(std::make_pair(
-              resources,
-              pdfium::MakeUnique<CPDF_PageObjectAvail>(
-                  GetValidator().Get(), m_pDocument.Get(), resources)))
+              resources, pdfium::MakeUnique<CPDF_PageObjectAvail>(
+                             GetValidator(), m_pDocument.Get(), resources)))
           .first->second.get();
   return resource_avail->CheckAvail();
 }
@@ -978,7 +977,7 @@
       return FormNotExist;
 
     m_pFormAvail = pdfium::MakeUnique<CPDF_PageObjectAvail>(
-        GetValidator().Get(), m_pDocument.Get(), pAcroForm);
+        GetValidator(), m_pDocument.Get(), pAcroForm);
   }
   switch (m_pFormAvail->CheckAvail()) {
     case DocAvailStatus::DataError:
@@ -998,8 +997,7 @@
   auto* pPageDict = m_pDocument->GetPageDictionary(safePage.ValueOrDie());
   if (!pPageDict)
     return false;
-  CPDF_PageObjectAvail obj_avail(GetValidator().Get(), m_pDocument.Get(),
-                                 pPageDict);
+  CPDF_PageObjectAvail obj_avail(GetValidator(), m_pDocument.Get(), pPageDict);
   return obj_avail.CheckAvail() == DocAvailStatus::DataAvailable;
 }
 
@@ -1012,7 +1010,7 @@
   auto document = pdfium::MakeUnique<CPDF_Document>();
   document->AddObserver(this);
 
-  CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  CPDF_ReadValidator::Session read_session(GetValidator());
   CPDF_Parser::Error error =
       document->LoadLinearizedDoc(GetValidator(), password);
 
diff --git a/core/fpdfapi/parser/cpdf_object_avail.cpp b/core/fpdfapi/parser/cpdf_object_avail.cpp
index e1b9b3f..5beb7a0 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail.cpp
@@ -13,9 +13,10 @@
 #include "core/fpdfapi/parser/cpdf_reference.h"
 #include "third_party/base/ptr_util.h"
 
-CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator,
-                                   CPDF_IndirectObjectHolder* holder,
-                                   const CPDF_Object* root)
+CPDF_ObjectAvail::CPDF_ObjectAvail(
+    const RetainPtr<CPDF_ReadValidator>& validator,
+    CPDF_IndirectObjectHolder* holder,
+    const CPDF_Object* root)
     : validator_(validator), holder_(holder), root_(root) {
   ASSERT(validator_);
   ASSERT(holder);
@@ -24,9 +25,10 @@
     parsed_objnums_.insert(root_->GetObjNum());
 }
 
-CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator,
-                                   CPDF_IndirectObjectHolder* holder,
-                                   uint32_t obj_num)
+CPDF_ObjectAvail::CPDF_ObjectAvail(
+    const RetainPtr<CPDF_ReadValidator>& validator,
+    CPDF_IndirectObjectHolder* holder,
+    uint32_t obj_num)
     : validator_(validator),
       holder_(holder),
       root_(pdfium::MakeUnique<CPDF_Reference>(holder, obj_num)) {
@@ -58,7 +60,7 @@
       return true;
     }
 
-    const CPDF_ReadValidator::Session parse_session(validator_.Get());
+    const CPDF_ReadValidator::Session parse_session(validator_);
     const CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num);
     if (validator_->has_read_problems())
       return false;
@@ -88,7 +90,7 @@
     if (!checked_objects.insert(obj_num).second)
       continue;
 
-    const CPDF_ReadValidator::Session parse_session(validator_.Get());
+    const CPDF_ReadValidator::Session parse_session(validator_);
     const CPDF_Object* direct = holder_->GetOrParseIndirectObject(obj_num);
     if (direct == root_.Get())
       continue;
@@ -111,7 +113,7 @@
 
   CPDF_ObjectWalker walker(object);
   while (const CPDF_Object* obj = walker.GetNext()) {
-    const CPDF_ReadValidator::Session parse_session(validator_.Get());
+    const CPDF_ReadValidator::Session parse_session(validator_);
 
     // Skip if this object if it's an inlined root, the parent object or
     // explicitily excluded.
diff --git a/core/fpdfapi/parser/cpdf_object_avail.h b/core/fpdfapi/parser/cpdf_object_avail.h
index ea4d449..017ea9a 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.h
+++ b/core/fpdfapi/parser/cpdf_object_avail.h
@@ -10,6 +10,7 @@
 
 #include "core/fpdfapi/parser/cpdf_data_avail.h"
 #include "core/fxcrt/maybe_owned.h"
+#include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 
 class CPDF_Object;
@@ -20,10 +21,10 @@
 // Helper for check availability of object tree.
 class CPDF_ObjectAvail {
  public:
-  CPDF_ObjectAvail(CPDF_ReadValidator* validator,
+  CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
                    CPDF_IndirectObjectHolder* holder,
                    const CPDF_Object* root);
-  CPDF_ObjectAvail(CPDF_ReadValidator* validator,
+  CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
                    CPDF_IndirectObjectHolder* holder,
                    uint32_t obj_num);
   virtual ~CPDF_ObjectAvail();
@@ -41,7 +42,7 @@
   void CleanMemory();
   bool HasObjectParsed(uint32_t obj_num) const;
 
-  UnownedPtr<CPDF_ReadValidator> validator_;
+  RetainPtr<CPDF_ReadValidator> validator_;
   UnownedPtr<CPDF_IndirectObjectHolder> holder_;
   MaybeOwned<const CPDF_Object> root_;
   std::set<uint32_t> parsed_objnums_;
diff --git a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
index 9bbc8f4..f7e0cad 100644
--- a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
@@ -132,7 +132,7 @@
   TestHolder holder;
   holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
   holder.SetObjectState(1, TestHolder::ObjectState::Available);
@@ -145,7 +145,7 @@
                    TestHolder::ObjectState::Unavailable);
   holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
 
@@ -166,7 +166,7 @@
   holder.AddObject(3, pdfium::MakeUnique<CPDF_Reference>(&holder, 1),
                    TestHolder::ObjectState::Unavailable);
 
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
 
@@ -192,7 +192,7 @@
   holder.GetTestObject(2)->GetDict()->SetNewFor<CPDF_Reference>("Parent",
                                                                 &holder, 1);
 
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 2);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 2);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
 
@@ -215,8 +215,7 @@
   holder.AddObject(kDepth, pdfium::MakeUnique<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Unavailable);
 
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
-
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   for (uint32_t i = 1; i <= kDepth; ++i) {
     EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
               avail.CheckAvail());
@@ -229,7 +228,7 @@
   TestHolder holder;
   holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
-  CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
 }
 
@@ -239,7 +238,7 @@
                    TestHolder::ObjectState::Available);
   holder.AddObject(2, pdfium::MakeUnique<CPDF_Dictionary>(),
                    TestHolder::ObjectState::Available);
-  CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
 }
 
@@ -258,7 +257,7 @@
       3,
       pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
       TestHolder::ObjectState::Unavailable);
-  CPDF_ObjectAvailExcludeArray avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvailExcludeArray avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
 }
 
@@ -287,7 +286,7 @@
       pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
       TestHolder::ObjectState::Unavailable);
 
-  CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator(), &holder, 1);
 
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
@@ -306,7 +305,7 @@
                    TestHolder::ObjectState::Available);
   holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>(
       "NotExistsObjRef", &holder, 2);
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   // Now object should be available, although the object '2' is not exists. But
   // all exists in file related data are checked.
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
@@ -317,7 +316,7 @@
   holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
                    TestHolder::ObjectState::Unavailable);
 
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
   EXPECT_EQ(avail.CheckAvail(), avail.CheckAvail());
 
   holder.SetObjectState(1, TestHolder::ObjectState::Available);
@@ -339,7 +338,7 @@
   holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "Data", false),
                    TestHolder::ObjectState::Unavailable);
 
-  CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, root);
+  CPDF_ObjectAvail avail(holder.GetValidator(), &holder, root);
 
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
             avail.CheckAvail());
diff --git a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
index e3f97df..18a973b 100644
--- a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
@@ -116,7 +116,7 @@
       4, pdfium::MakeUnique<CPDF_String>(nullptr, "Other page data", false),
       TestHolder::ObjectState::Unavailable);
 
-  CPDF_PageObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+  CPDF_PageObjectAvail avail(holder.GetValidator(), &holder, 1);
   // Now object should be available, although the object '4' is not available,
   // because it is in skipped other page.
   EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
diff --git a/core/fpdfapi/parser/cpdf_read_validator.cpp b/core/fpdfapi/parser/cpdf_read_validator.cpp
index 37f17ce..426e06f 100644
--- a/core/fpdfapi/parser/cpdf_read_validator.cpp
+++ b/core/fpdfapi/parser/cpdf_read_validator.cpp
@@ -27,8 +27,9 @@
 
 }  // namespace
 
-CPDF_ReadValidator::Session::Session(CPDF_ReadValidator* validator)
-    : validator_(validator) {
+CPDF_ReadValidator::Session::Session(
+    const RetainPtr<CPDF_ReadValidator>& validator)
+    : validator_(validator.BackPointer()) {
   ASSERT(validator_);
   saved_read_error_ = validator_->read_error_;
   saved_has_unavailable_data_ = validator_->has_unavailable_data_;
diff --git a/core/fpdfapi/parser/cpdf_read_validator.h b/core/fpdfapi/parser/cpdf_read_validator.h
index 23cc4d0..6adde02 100644
--- a/core/fpdfapi/parser/cpdf_read_validator.h
+++ b/core/fpdfapi/parser/cpdf_read_validator.h
@@ -12,7 +12,7 @@
  public:
   class Session {
    public:
-    explicit Session(CPDF_ReadValidator* validator);
+    explicit Session(const RetainPtr<CPDF_ReadValidator>& validator);
     ~Session();
 
    private:
@@ -21,16 +21,14 @@
     bool saved_has_unavailable_data_;
   };
 
-  void SetDownloadHints(CPDF_DataAvail::DownloadHints* hints) {
-    hints_ = hints;
-  }
-
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+  void SetDownloadHints(CPDF_DataAvail::DownloadHints* hints) {
+    hints_ = hints;
+  }
   bool read_error() const { return read_error_; }
   bool has_unavailable_data() const { return has_unavailable_data_; }
-
   bool has_read_problems() const {
     return read_error() || has_unavailable_data();
   }
diff --git a/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
index 97390bc..38b4bf9 100644
--- a/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
@@ -169,7 +169,7 @@
   auto validator = pdfium::MakeRetain<CPDF_ReadValidator>(file, &file_avail);
   validator->SetDownloadHints(&hints);
 
-  const CPDF_ReadValidator::Session read_session(validator.Get());
+  const CPDF_ReadValidator::Session read_session(validator);
   ASSERT_FALSE(validator->has_read_problems());
 
   // Data is unavailable
@@ -180,7 +180,7 @@
   EXPECT_FALSE(validator->read_error());
 
   {
-    const CPDF_ReadValidator::Session read_subsession(validator.Get());
+    const CPDF_ReadValidator::Session read_subsession(validator);
     // The read problems should be hidden.
     EXPECT_FALSE(validator->has_read_problems());
 
@@ -207,7 +207,7 @@
   auto validator = pdfium::MakeRetain<CPDF_ReadValidator>(file, &file_avail);
   validator->SetDownloadHints(&hints);
 
-  const CPDF_ReadValidator::Session read_session(validator.Get());
+  const CPDF_ReadValidator::Session read_session(validator);
   ASSERT_FALSE(validator->has_read_problems());
 
   // Data is unavailable
@@ -218,7 +218,7 @@
   EXPECT_FALSE(validator->read_error());
 
   {
-    const CPDF_ReadValidator::Session read_subsession(validator.Get());
+    const CPDF_ReadValidator::Session read_subsession(validator);
     // The read problems should be hidden.
     EXPECT_FALSE(validator->has_read_problems());
 
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index 18d4b0a..ae844bd 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -389,7 +389,7 @@
 }
 
 ByteString CPDF_SyntaxParser::GetNextWord(bool* bIsNumber) {
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   GetNextWordInternal(bIsNumber);
   ByteString ret;
   if (!GetValidator()->has_read_problems())
@@ -412,7 +412,7 @@
 
 std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetObjectBody(
     CPDF_IndirectObjectHolder* pObjList) {
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   auto result = GetObjectBodyInternal(pObjList, ParseType::kLoose);
   if (GetValidator()->has_read_problems())
     return nullptr;
@@ -533,7 +533,7 @@
 std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetIndirectObject(
     CPDF_IndirectObjectHolder* pObjList,
     ParseType parse_type) {
-  const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+  const CPDF_ReadValidator::Session read_session(GetValidator());
   const FX_FILESIZE saved_pos = GetPos();
   bool is_number = false;
   ByteString word = GetNextWord(&is_number);
@@ -667,7 +667,7 @@
   // Note, we allow zero length streams as we need to pass them through when we
   // are importing pages into a new document.
   if (len >= 0) {
-    const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+    const CPDF_ReadValidator::Session read_session(GetValidator());
     m_Pos += ReadEOLMarkers(GetPos());
     memset(m_WordBuffer, 0, kEndStreamStr.GetLength() + 1);
     GetNextWordInternal(nullptr);
diff --git a/core/fxcrt/retain_ptr.h b/core/fxcrt/retain_ptr.h
index edd2663..e6b8ac7 100644
--- a/core/fxcrt/retain_ptr.h
+++ b/core/fxcrt/retain_ptr.h
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/unowned_ptr.h"
 
 namespace fxcrt {
 
@@ -51,6 +52,7 @@
   }
 
   T* Get() const { return m_pObj.get(); }
+  UnownedPtr<T> BackPointer() const { return UnownedPtr<T>(Get()); }
   void Swap(RetainPtr& that) { m_pObj.swap(that.m_pObj); }
 
   // Useful for passing notion of object ownership across a C API.