Stop vending dictionary pointers from CPDF_FlateEncoder

Moving code from CPDF_Stream to CPDF_FlateEncoder better encapsulates
the dictionary members.

Change-Id: I887d6e39b160dea58cac971b480d074c3e078332
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98717
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_flateencoder.cpp b/core/fpdfapi/parser/cpdf_flateencoder.cpp
index 49d5bf8..7b6bdb8 100644
--- a/core/fpdfapi/parser/cpdf_flateencoder.cpp
+++ b/core/fpdfapi/parser/cpdf_flateencoder.cpp
@@ -51,20 +51,22 @@
 
 CPDF_FlateEncoder::~CPDF_FlateEncoder() = default;
 
-void CPDF_FlateEncoder::CloneDict() {
-  if (m_pClonedDict) {
-    DCHECK(!m_pDict);
+void CPDF_FlateEncoder::UpdateLength(size_t size) {
+  if (static_cast<size_t>(GetDict()->GetIntegerFor("Length")) == size)
     return;
-  }
 
-  m_pClonedDict = ToDictionary(m_pDict->Clone());
+  if (!m_pClonedDict) {
+    m_pClonedDict = ToDictionary(m_pDict->Clone());
+    m_pDict.Reset();
+  }
   DCHECK(m_pClonedDict);
-  m_pDict.Reset();
+  DCHECK(!m_pDict);
+  m_pClonedDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
 }
 
-CPDF_Dictionary* CPDF_FlateEncoder::GetClonedDict() {
-  DCHECK(!m_pDict);
-  return m_pClonedDict.Get();
+bool CPDF_FlateEncoder::WriteDictTo(IFX_ArchiveStream* archive,
+                                    const CPDF_Encryptor* encryptor) const {
+  return GetDict()->WriteTo(archive, encryptor);
 }
 
 const CPDF_Dictionary* CPDF_FlateEncoder::GetDict() const {
@@ -72,7 +74,6 @@
     DCHECK(!m_pDict);
     return m_pClonedDict.Get();
   }
-
   return m_pDict.Get();
 }
 
diff --git a/core/fpdfapi/parser/cpdf_flateencoder.h b/core/fpdfapi/parser/cpdf_flateencoder.h
index 7e6c797..3d412e2 100644
--- a/core/fpdfapi/parser/cpdf_flateencoder.h
+++ b/core/fpdfapi/parser/cpdf_flateencoder.h
@@ -15,25 +15,28 @@
 #include "third_party/base/span.h"
 
 class CPDF_Dictionary;
+class CPDF_Encryptor;
 class CPDF_Stream;
 class CPDF_StreamAcc;
+class IFX_ArchiveStream;
 
 class CPDF_FlateEncoder {
  public:
   CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream, bool bFlateEncode);
   ~CPDF_FlateEncoder();
 
-  void CloneDict();
-  CPDF_Dictionary* GetClonedDict();
-
-  // Returns |m_pClonedDict| if it is valid. Otherwise returns |m_pDict|.
-  const CPDF_Dictionary* GetDict() const;
+  void UpdateLength(size_t size);
+  bool WriteDictTo(IFX_ArchiveStream* archive,
+                   const CPDF_Encryptor* encryptor) const;
 
   pdfium::span<const uint8_t> GetSpan() const;
 
  private:
   bool is_owned() const { return m_Data.index() == 1; }
 
+  // Returns |m_pClonedDict| if it is valid. Otherwise returns |m_pDict|.
+  const CPDF_Dictionary* GetDict() const;
+
   // Must outlive `m_Data`.
   RetainPtr<CPDF_StreamAcc> const m_pAcc;
 
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 341e6ac..763f5e0 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -193,20 +193,13 @@
 
   DataVector<uint8_t> encrypted_data;
   pdfium::span<const uint8_t> data = encoder.GetSpan();
-
   if (encryptor && !is_metadata) {
     encrypted_data = encryptor->Encrypt(data);
     data = encrypted_data;
   }
 
-  const size_t size = data.size();
-  if (static_cast<size_t>(encoder.GetDict()->GetIntegerFor("Length")) != size) {
-    encoder.CloneDict();
-    encoder.GetClonedDict()->SetNewFor<CPDF_Number>("Length",
-                                                    static_cast<int>(size));
-  }
-
-  if (!encoder.GetDict()->WriteTo(archive, encryptor))
+  encoder.UpdateLength(data.size());
+  if (!encoder.WriteDictTo(archive, encryptor))
     return false;
 
   if (!archive->WriteString("stream\r\n"))