Change CPDF_Stream to store memory-based data in a DataVector.

Use DataVector instead of std::unique_ptr so there's just a single
container to pass around, instead of a container and a size variable.
Remove TakeDataInternal() and either merge its code into TakeData(), or
move it to SetLengthInDict().

Bug: pdfium:1872
Change-Id: Ia3a7cd08a5419283e47ff89fbfa01a97842f39dc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/96213
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 9ecae3a..4f7a809 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -36,13 +36,6 @@
 
 }  // namespace
 
-CPDF_Stream::OwnedData::OwnedData(
-    std::unique_ptr<uint8_t, FxFreeDeleter> buffer,
-    size_t size)
-    : buffer(std::move(buffer)), size(size) {}
-
-CPDF_Stream::OwnedData::~OwnedData() = default;
-
 CPDF_Stream::CPDF_Stream() = default;
 
 CPDF_Stream::CPDF_Stream(pdfium::span<const uint8_t> pData,
@@ -53,16 +46,18 @@
 
 CPDF_Stream::CPDF_Stream(DataVector<uint8_t> pData,
                          RetainPtr<CPDF_Dictionary> pDict)
-    : dict_(std::move(pDict)) {
-  // TODO(crbug.com/pdfium/1872): Avoid copying.
-  SetData(pData);
+    : data_(std::move(pData)), dict_(std::move(pDict)) {
+  SetLengthInDict(pdfium::base::checked_cast<int>(
+      absl::get<DataVector<uint8_t>>(data_).size()));
 }
 
 CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
                          size_t size,
                          RetainPtr<CPDF_Dictionary> pDict)
-    : dict_(std::move(pDict)) {
-  TakeDataInternal(std::move(pData), size);
+    : data_(DataVector<uint8_t>(pData.get(), pData.get() + size)),
+      dict_(std::move(pDict)) {
+  SetLengthInDict(pdfium::base::checked_cast<int>(
+      absl::get<DataVector<uint8_t>>(data_).size()));
 }
 
 CPDF_Stream::~CPDF_Stream() {
@@ -93,8 +88,7 @@
                                      RetainPtr<CPDF_Dictionary> pDict) {
   data_ = pFile;
   dict_ = std::move(pDict);
-  dict_->SetNewFor<CPDF_Number>(
-      "Length", pdfium::base::checked_cast<int>(pFile->GetSize()));
+  SetLengthInDict(pdfium::base::checked_cast<int>(pFile->GetSize()));
 }
 
 RetainPtr<CPDF_Object> CPDF_Stream::Clone() const {
@@ -138,28 +132,16 @@
 }
 
 void CPDF_Stream::SetData(pdfium::span<const uint8_t> pData) {
-  std::unique_ptr<uint8_t, FxFreeDeleter> data_copy;
-  if (!pData.empty()) {
-    data_copy.reset(FX_AllocUninit(uint8_t, pData.size()));
-    auto copy_span = pdfium::make_span(data_copy.get(), pData.size());
-    fxcrt::spancpy(copy_span, pData);
-  }
-  TakeDataInternal(std::move(data_copy), pData.size());
+  DataVector<uint8_t> data_copy(pData.begin(), pData.end());
+  TakeData(std::move(data_copy));
 }
 
 void CPDF_Stream::TakeData(DataVector<uint8_t> data) {
-  // TODO(crbug.com/pdfium/1872): Avoid copying.
-  SetData(data);
-}
-
-void CPDF_Stream::TakeDataInternal(
-    std::unique_ptr<uint8_t, FxFreeDeleter> pData,
-    size_t size) {
-  data_.emplace<OwnedData>(std::move(pData), size);
+  const size_t size = data.size();
+  data_ = std::move(data);
   if (!dict_)
     dict_ = pdfium::MakeRetain<CPDF_Dictionary>();
-  dict_->SetNewFor<CPDF_Number>("Length",
-                                pdfium::base::checked_cast<int>(size));
+  SetLengthInDict(pdfium::base::checked_cast<int>(size));
 }
 
 void CPDF_Stream::SetDataFromStringstream(fxcrt::ostringstream* stream) {
@@ -220,13 +202,16 @@
         absl::get<RetainPtr<IFX_SeekableReadStream>>(data_)->GetSize());
   }
   if (IsMemoryBased())
-    return absl::get<OwnedData>(data_).size;
+    return absl::get<DataVector<uint8_t>>(data_).size();
   DCHECK(IsUninitialized());
   return 0;
 }
 
 pdfium::span<const uint8_t> CPDF_Stream::GetInMemoryRawData() const {
   DCHECK(IsMemoryBased());
-  const auto& data = absl::get<OwnedData>(data_);
-  return pdfium::make_span(data.buffer.get(), data.size);
+  return absl::get<DataVector<uint8_t>>(data_);
+}
+
+void CPDF_Stream::SetLengthInDict(int length) {
+  dict_->SetNewFor<CPDF_Number>("Length", length);
 }
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index 783c617..812d4ae 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -67,15 +67,6 @@
   bool HasFilter() const;
 
  private:
-  // TODO(crbug.com/pdfium/1872): Replace with DataVector.
-  struct OwnedData {
-    OwnedData(std::unique_ptr<uint8_t, FxFreeDeleter> buffer, size_t size);
-    ~OwnedData();
-
-    std::unique_ptr<uint8_t, FxFreeDeleter> buffer;
-    size_t size;
-  };
-
   CPDF_Stream();
   CPDF_Stream(pdfium::span<const uint8_t> pData,
               RetainPtr<CPDF_Dictionary> pDict);
@@ -90,11 +81,11 @@
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const override;
 
-  // TODO(crbug.com/pdfium/1872): Replace with vector version.
-  void TakeDataInternal(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
-                        size_t size);
+  void SetLengthInDict(int length);
 
-  absl::variant<absl::monostate, RetainPtr<IFX_SeekableReadStream>, OwnedData>
+  absl::variant<absl::monostate,
+                RetainPtr<IFX_SeekableReadStream>,
+                DataVector<uint8_t>>
       data_;
   RetainPtr<CPDF_Dictionary> dict_;
 };