Restructure CPDF_Object methods to avoid analyzer warnings

Add new internal methods to return raw objects thus avoiding
calling Get() on invisible temporary retained object results
under the covers. Avoids some ref-churn as an additional
benefit.

Change-Id: I6df11bb1cc03be9a45f2294ad93f9d2ef458947e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/100673
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index 224487f..bf6f593 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -42,10 +42,6 @@
   return kDictionary;
 }
 
-RetainPtr<const CPDF_Dictionary> CPDF_Dictionary::GetDict() const {
-  return pdfium::WrapRetain(this);
-}
-
 CPDF_Dictionary* CPDF_Dictionary::AsMutableDictionary() {
   return this;
 }
@@ -91,7 +87,7 @@
 const CPDF_Object* CPDF_Dictionary::GetDirectObjectForInternal(
     const ByteString& key) const {
   const CPDF_Object* p = GetObjectForInternal(key);
-  return p ? const_cast<CPDF_Object*>(p)->GetMutableDirect().Get() : nullptr;
+  return p ? p->GetDirectInternal() : nullptr;
 }
 
 RetainPtr<const CPDF_Object> CPDF_Dictionary::GetDirectObjectFor(
@@ -119,7 +115,7 @@
 WideString CPDF_Dictionary::GetUnicodeTextFor(const ByteString& key) const {
   const CPDF_Object* p = GetObjectForInternal(key);
   if (const CPDF_Reference* pRef = ToReference(p))
-    p = pRef->GetDirect().Get();
+    p = pRef->GetDirectInternal();
   return p ? p->GetUnicodeText() : WideString();
 }
 
@@ -154,16 +150,14 @@
   return p ? p->GetNumber() : 0;
 }
 
+const CPDF_Dictionary* CPDF_Dictionary::GetDictInternal() const {
+  return this;
+}
+
 const CPDF_Dictionary* CPDF_Dictionary::GetDictForInternal(
     const ByteString& key) const {
   const CPDF_Object* p = GetDirectObjectForInternal(key);
-  if (!p)
-    return nullptr;
-  if (const CPDF_Dictionary* pDict = p->AsDictionary())
-    return pDict;
-  if (const CPDF_Stream* pStream = p->AsStream())
-    return pStream->GetDict().Get();
-  return nullptr;
+  return p ? p->GetDictInternal() : nullptr;
 }
 
 RetainPtr<const CPDF_Dictionary> CPDF_Dictionary::GetDictFor(
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index f60f685..34be276 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -35,7 +35,6 @@
   // CPDF_Object:
   Type GetType() const override;
   RetainPtr<CPDF_Object> Clone() const override;
-  RetainPtr<const CPDF_Dictionary> GetDict() const override;
   CPDF_Dictionary* AsMutableDictionary() override;
   bool WriteTo(IFX_ArchiveStream* archive,
                const CPDF_Encryptor* encryptor) const override;
@@ -139,6 +138,7 @@
                               RetainPtr<CPDF_Object> pObj);
 
   ByteString MaybeIntern(const ByteString& str);
+  const CPDF_Dictionary* GetDictInternal() const override;
   RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* visited) const override;
diff --git a/core/fpdfapi/parser/cpdf_object.cpp b/core/fpdfapi/parser/cpdf_object.cpp
index d80f096..3916392 100644
--- a/core/fpdfapi/parser/cpdf_object.cpp
+++ b/core/fpdfapi/parser/cpdf_object.cpp
@@ -33,11 +33,15 @@
 }
 
 RetainPtr<CPDF_Object> CPDF_Object::GetMutableDirect() {
-  return pdfium::WrapRetain(this);
+  return pdfium::WrapRetain(const_cast<CPDF_Object*>(GetDirectInternal()));
 }
 
 RetainPtr<const CPDF_Object> CPDF_Object::GetDirect() const {
-  return const_cast<CPDF_Object*>(this)->GetMutableDirect();
+  return pdfium::WrapRetain(GetDirectInternal());
+}
+
+const CPDF_Object* CPDF_Object::GetDirectInternal() const {
+  return this;
 }
 
 RetainPtr<CPDF_Object> CPDF_Object::CloneObjectNonCyclic(bool bDirect) const {
@@ -71,11 +75,15 @@
   return 0;
 }
 
-RetainPtr<CPDF_Dictionary> CPDF_Object::GetMutableDict() {
-  return pdfium::WrapRetain(const_cast<CPDF_Dictionary*>(GetDict().Get()));
+RetainPtr<const CPDF_Dictionary> CPDF_Object::GetDict() const {
+  return pdfium::WrapRetain(GetDictInternal());
 }
 
-RetainPtr<const CPDF_Dictionary> CPDF_Object::GetDict() const {
+RetainPtr<CPDF_Dictionary> CPDF_Object::GetMutableDict() {
+  return pdfium::WrapRetain(const_cast<CPDF_Dictionary*>(GetDictInternal()));
+}
+
+const CPDF_Dictionary* CPDF_Object::GetDictInternal() const {
   return nullptr;
 }
 
diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h
index fc3f661..11ead2e 100644
--- a/core/fpdfapi/parser/cpdf_object.h
+++ b/core/fpdfapi/parser/cpdf_object.h
@@ -59,12 +59,10 @@
   // copied to the object it points to directly.
   virtual RetainPtr<CPDF_Object> CloneDirectObject() const;
 
-  virtual RetainPtr<CPDF_Object> GetMutableDirect();
   virtual ByteString GetString() const;
   virtual WideString GetUnicodeText() const;
   virtual float GetNumber() const;
   virtual int GetInteger() const;
-  virtual RetainPtr<const CPDF_Dictionary> GetDict() const;
 
   virtual void SetString(const ByteString& str);
 
@@ -96,8 +94,10 @@
   virtual RetainPtr<CPDF_Reference> MakeReference(
       CPDF_IndirectObjectHolder* holder) const;
 
-  RetainPtr<const CPDF_Object> GetDirect() const;  // Wraps virtual method.
-  RetainPtr<CPDF_Dictionary> GetMutableDict();     // Wraps virtual method.
+  RetainPtr<const CPDF_Object> GetDirect() const;    // Wraps virtual method.
+  RetainPtr<CPDF_Object> GetMutableDirect();         // Wraps virtual method.
+  RetainPtr<const CPDF_Dictionary> GetDict() const;  // Wraps virtual method.
+  RetainPtr<CPDF_Dictionary> GetMutableDict();       // Wraps virtual method.
 
   // Const methods wrapping non-const virtual As*() methods.
   const CPDF_Array* AsArray() const;
@@ -122,10 +122,15 @@
   bool IsString() const { return !!AsString(); }
 
  protected:
+  friend class CPDF_Dictionary;
+  friend class CPDF_Reference;
+
   CPDF_Object() = default;
   CPDF_Object(const CPDF_Object& src) = delete;
   ~CPDF_Object() override;
 
+  virtual const CPDF_Object* GetDirectInternal() const;
+  virtual const CPDF_Dictionary* GetDictInternal() const;
   RetainPtr<CPDF_Object> CloneObjectNonCyclic(bool bDirect) const;
 
   uint32_t m_ObjNum = 0;
diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp
index 1a48faf..8baa6b6 100644
--- a/core/fpdfapi/parser/cpdf_reference.cpp
+++ b/core/fpdfapi/parser/cpdf_reference.cpp
@@ -36,9 +36,9 @@
   return obj ? obj->GetInteger() : 0;
 }
 
-RetainPtr<const CPDF_Dictionary> CPDF_Reference::GetDict() const {
+const CPDF_Dictionary* CPDF_Reference::GetDictInternal() const {
   const CPDF_Object* obj = FastGetDirect();
-  return obj ? obj->GetDict() : nullptr;
+  return obj ? obj->GetDictInternal() : nullptr;
 }
 
 CPDF_Reference* CPDF_Reference::AsMutableReference() {
@@ -75,8 +75,8 @@
   m_RefObjNum = objnum;
 }
 
-RetainPtr<CPDF_Object> CPDF_Reference::GetMutableDirect() {
-  return m_pObjList ? m_pObjList->GetOrParseIndirectObject(m_RefObjNum)
+const CPDF_Object* CPDF_Reference::GetDirectInternal() const {
+  return m_pObjList ? m_pObjList->GetOrParseIndirectObjectInternal(m_RefObjNum)
                     : nullptr;
 }
 
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index d14c3af..df24458 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -22,11 +22,9 @@
   // CPDF_Object:
   Type GetType() const override;
   RetainPtr<CPDF_Object> Clone() const override;
-  RetainPtr<CPDF_Object> GetMutableDirect() override;
   ByteString GetString() const override;
   float GetNumber() const override;
   int GetInteger() const override;
-  RetainPtr<const CPDF_Dictionary> GetDict() const override;
   CPDF_Reference* AsMutableReference() override;
   bool WriteTo(IFX_ArchiveStream* archive,
                const CPDF_Encryptor* encryptor) const override;
@@ -37,9 +35,13 @@
   void SetRef(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum);
 
  private:
+  friend class CPDF_Dictionary;
+
   CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum);
   ~CPDF_Reference() override;
 
+  const CPDF_Object* GetDirectInternal() const override;
+  const CPDF_Dictionary* GetDictInternal() const override;
   RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 89a34c9..12cfcf2 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -58,8 +58,8 @@
   return kStream;
 }
 
-RetainPtr<const CPDF_Dictionary> CPDF_Stream::GetDict() const {
-  return dict_;
+const CPDF_Dictionary* CPDF_Stream::GetDictInternal() const {
+  return dict_.Get();
 }
 
 CPDF_Stream* CPDF_Stream::AsMutableStream() {
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index 85fbb14..a3974b2 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -29,7 +29,6 @@
   // CPDF_Object:
   Type GetType() const override;
   RetainPtr<CPDF_Object> Clone() const override;
-  RetainPtr<const CPDF_Dictionary> GetDict() const override;
   WideString GetUnicodeText() const override;
   CPDF_Stream* AsMutableStream() override;
   bool WriteTo(IFX_ArchiveStream* archive,
@@ -65,6 +64,8 @@
   bool HasFilter() const;
 
  private:
+  friend class CPDF_Dictionary;
+
   // Uninitialized.
   CPDF_Stream();
 
@@ -74,6 +75,7 @@
   CPDF_Stream(DataVector<uint8_t> pData, RetainPtr<CPDF_Dictionary> pDict);
   ~CPDF_Stream() override;
 
+  const CPDF_Dictionary* GetDictInternal() const override;
   RetainPtr<CPDF_Object> CloneNonCyclic(
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;