Avoid a potential copy in CPDF_ObjectStream.

CPDF_ObjectStream currently takes the data from CPDF_StreamAcc, which
can potentially trigger a copy. Instead, keep the CPDF_StreamAcc around,
and just use the data it holds. This means switching from
CFX_ReadOnlyMemoryStream to CFX_ReadOnlySpanStream. Then
CFX_ReadOnlyMemoryStream has no remaining users and can be deleted.

Bug: pdfium:1872
Change-Id: If554aa653d177403fd0822119a15c7bc4b445537
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97491
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_object_stream.cpp b/core/fpdfapi/parser/cpdf_object_stream.cpp
index c01d786..93bd12b 100644
--- a/core/fpdfapi/parser/cpdf_object_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_object_stream.cpp
@@ -14,7 +14,7 @@
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfapi/parser/cpdf_syntax_parser.h"
 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
-#include "core/fxcrt/cfx_read_only_memory_stream.h"
+#include "core/fxcrt/cfx_read_only_span_stream.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "third_party/base/check.h"
 #include "third_party/base/ptr_util.h"
@@ -63,7 +63,8 @@
 }
 
 CPDF_ObjectStream::CPDF_ObjectStream(const CPDF_Stream* obj_stream)
-    : first_object_offset_(obj_stream->GetDict()->GetIntegerFor("First")) {
+    : stream_acc_(pdfium::MakeRetain<CPDF_StreamAcc>(obj_stream)),
+      first_object_offset_(obj_stream->GetDict()->GetIntegerFor("First")) {
   DCHECK(IsObjectStream(obj_stream));
   Init(obj_stream);
 }
@@ -89,13 +90,9 @@
 }
 
 void CPDF_ObjectStream::Init(const CPDF_Stream* stream) {
-  {
-    auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(stream);
-    stream_acc->LoadAllDataFiltered();
-    const uint32_t data_size = stream_acc->GetSize();
-    data_stream_ = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(
-        stream_acc->DetachData(), data_size);
-  }
+  stream_acc_->LoadAllDataFiltered();
+  data_stream_ =
+      pdfium::MakeRetain<CFX_ReadOnlySpanStream>(stream_acc_->GetSpan());
 
   CPDF_SyntaxParser syntax(data_stream_);
   const int object_count = stream->GetDict()->GetIntegerFor("N");
diff --git a/core/fpdfapi/parser/cpdf_object_stream.h b/core/fpdfapi/parser/cpdf_object_stream.h
index bc09db3..9cdca39 100644
--- a/core/fpdfapi/parser/cpdf_object_stream.h
+++ b/core/fpdfapi/parser/cpdf_object_stream.h
@@ -13,6 +13,7 @@
 
 class CPDF_IndirectObjectHolder;
 class CPDF_Stream;
+class CPDF_StreamAcc;
 class IFX_SeekableReadStream;
 
 // Implementation of logic of PDF "Object Streams".
@@ -48,6 +49,8 @@
       CPDF_IndirectObjectHolder* pObjList,
       uint32_t object_offset) const;
 
+  // Must outlive `data_stream_`.
+  RetainPtr<CPDF_StreamAcc> const stream_acc_;
   RetainPtr<IFX_SeekableReadStream> data_stream_;
   int first_object_offset_ = 0;
   std::vector<ObjectInfo> object_info_;
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index aa5d94e..56e8622 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -23,8 +23,6 @@
     "cfx_bitstream.h",
     "cfx_datetime.cpp",
     "cfx_datetime.h",
-    "cfx_read_only_memory_stream.cpp",
-    "cfx_read_only_memory_stream.h",
     "cfx_read_only_span_stream.cpp",
     "cfx_read_only_span_stream.h",
     "cfx_read_only_string_stream.cpp",
diff --git a/core/fxcrt/cfx_read_only_memory_stream.cpp b/core/fxcrt/cfx_read_only_memory_stream.cpp
deleted file mode 100644
index cf208d9..0000000
--- a/core/fxcrt/cfx_read_only_memory_stream.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "core/fxcrt/cfx_read_only_memory_stream.h"
-
-#include <utility>
-
-#include "core/fxcrt/cfx_read_only_span_stream.h"
-#include "third_party/base/span.h"
-
-CFX_ReadOnlyMemoryStream::CFX_ReadOnlyMemoryStream(
-    std::unique_ptr<uint8_t, FxFreeDeleter> data,
-    size_t size)
-    : m_data(std::move(data)),
-      m_stream(pdfium::MakeRetain<CFX_ReadOnlySpanStream>(
-          pdfium::make_span(m_data.get(), size))) {}
-
-CFX_ReadOnlyMemoryStream::~CFX_ReadOnlyMemoryStream() = default;
-
-FX_FILESIZE CFX_ReadOnlyMemoryStream::GetSize() {
-  return m_stream->GetSize();
-}
-
-bool CFX_ReadOnlyMemoryStream::ReadBlockAtOffset(void* buffer,
-                                                 FX_FILESIZE offset,
-                                                 size_t size) {
-  return m_stream->ReadBlockAtOffset(buffer, offset, size);
-}
diff --git a/core/fxcrt/cfx_read_only_memory_stream.h b/core/fxcrt/cfx_read_only_memory_stream.h
deleted file mode 100644
index c4c9676..0000000
--- a/core/fxcrt/cfx_read_only_memory_stream.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef CORE_FXCRT_CFX_READ_ONLY_MEMORY_STREAM_H_
-#define CORE_FXCRT_CFX_READ_ONLY_MEMORY_STREAM_H_
-
-#include <memory>
-
-#include "core/fxcrt/fx_memory_wrappers.h"
-#include "core/fxcrt/fx_stream.h"
-#include "core/fxcrt/retain_ptr.h"
-
-class CFX_ReadOnlySpanStream;
-
-class CFX_ReadOnlyMemoryStream final : public IFX_SeekableReadStream {
- public:
-  CONSTRUCT_VIA_MAKE_RETAIN;
-
-  // IFX_SeekableReadStream:
-  FX_FILESIZE GetSize() override;
-  bool ReadBlockAtOffset(void* buffer,
-                         FX_FILESIZE offset,
-                         size_t size) override;
-
- private:
-  CFX_ReadOnlyMemoryStream(std::unique_ptr<uint8_t, FxFreeDeleter> data,
-                           size_t size);
-  ~CFX_ReadOnlyMemoryStream() override;
-
-  const std::unique_ptr<uint8_t, FxFreeDeleter> m_data;
-  const RetainPtr<CFX_ReadOnlySpanStream> m_stream;
-};
-
-#endif  // CORE_FXCRT_CFX_READ_ONLY_MEMORY_STREAM_H_