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_