Return const pointer from CPDF_Stream::GetInMemoryRawData().
Callers to CPDF_Stream::GetInMemoryRawData() do not need the non-const
pointer to the data. GetInMemoryRawData() was only returning a non-const
pointer because fxcrt::MaybeOwned required it for the owned-data case.
In CPDF_StreamAcc, replace its MaybeOwned usage with absl::variant. Then
the variant can store either a read-only span, or some kind of owned
memory. Then CPDF_StreamAcc no longer need to have separate data and
size members.
As part of this CL, also restrict when GetInMemoryRawData() can be
called, and update CPDF_StreamAcc to match that behavior. Update the
comments for GetInMemoryRawData() to better explain how it is intended
to be used.
Change-Id: I6a05e8b5314434447e45c44596c81771765756fb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97535
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 4bcd451..57ec20c 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -221,3 +221,8 @@
return true;
}
+
+const uint8_t* CPDF_Stream::GetInMemoryRawData() const {
+ DCHECK(IsMemoryBased());
+ return m_pDataBuf.get();
+}
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index b6e4966..5da2398 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -35,9 +35,10 @@
const CPDF_Encryptor* encryptor) const override;
size_t GetRawSize() const { return m_dwSize; }
- // Will be null in case when stream is not memory based.
- // Use CPDF_StreamAcc to data access in all cases.
- uint8_t* GetInMemoryRawData() const { return m_pDataBuf.get(); }
+ // Can only be called when stream is memory-based.
+ // This is meant to be used by CPDF_StreamAcc only.
+ // Other callers should use CPDF_StreamAcc to access data in all cases.
+ const uint8_t* GetInMemoryRawData() const;
// Copies span or stream into internally-owned buffer.
void SetData(pdfium::span<const uint8_t> pData);
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.cpp b/core/fpdfapi/parser/cpdf_stream_acc.cpp
index 485de02..27de211 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.cpp
+++ b/core/fpdfapi/parser/cpdf_stream_acc.cpp
@@ -13,7 +13,19 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
-#include "third_party/base/check.h"
+#include "third_party/base/check_op.h"
+
+CPDF_StreamAcc::OwnedData::OwnedData(
+ std::unique_ptr<uint8_t, FxFreeDeleter> buffer,
+ uint32_t size)
+ : buffer(std::move(buffer)), size(size) {}
+
+CPDF_StreamAcc::OwnedData::OwnedData(OwnedData&&) = default;
+
+CPDF_StreamAcc::OwnedData& CPDF_StreamAcc::OwnedData::operator=(OwnedData&&) =
+ default;
+
+CPDF_StreamAcc::OwnedData::~OwnedData() = default;
CPDF_StreamAcc::CPDF_StreamAcc(const CPDF_Stream* pStream)
: m_pStream(pStream) {}
@@ -60,14 +72,16 @@
}
const uint8_t* CPDF_StreamAcc::GetData() const {
- if (m_pData.IsOwned())
- return m_pData.Get();
- return m_pStream ? m_pStream->GetInMemoryRawData() : nullptr;
+ if (is_owned())
+ return absl::get<OwnedData>(m_Data).buffer.get();
+ return (m_pStream && m_pStream->IsMemoryBased())
+ ? m_pStream->GetInMemoryRawData()
+ : nullptr;
}
uint32_t CPDF_StreamAcc::GetSize() const {
- if (m_pData.IsOwned())
- return m_dwSize;
+ if (is_owned())
+ return absl::get<OwnedData>(m_Data).size;
return (m_pStream && m_pStream->IsMemoryBased()) ? m_pStream->GetRawSize()
: 0;
}
@@ -83,14 +97,16 @@
}
std::unique_ptr<uint8_t, FxFreeDeleter> CPDF_StreamAcc::DetachData() {
- if (m_pData.IsOwned()) {
- std::unique_ptr<uint8_t, FxFreeDeleter> p = m_pData.ReleaseAndClear();
- m_dwSize = 0;
- return p;
+ if (is_owned()) {
+ auto& data = absl::get<OwnedData>(m_Data);
+ data.size = 0;
+ return std::move(data.buffer);
}
- std::unique_ptr<uint8_t, FxFreeDeleter> p(FX_AllocUninit(uint8_t, m_dwSize));
- memcpy(p.get(), m_pData.Get(), m_dwSize);
- return p;
+ auto span = absl::get<pdfium::span<const uint8_t>>(m_Data);
+ std::unique_ptr<uint8_t, FxFreeDeleter> result(
+ FX_AllocUninit(uint8_t, span.size()));
+ memcpy(result.get(), span.data(), span.size());
+ return result;
}
void CPDF_StreamAcc::ProcessRawData() {
@@ -99,8 +115,7 @@
return;
if (m_pStream->IsMemoryBased()) {
- m_pData = m_pStream->GetInMemoryRawData();
- m_dwSize = dwSrcSize;
+ m_Data = pdfium::make_span(m_pStream->GetInMemoryRawData(), dwSrcSize);
return;
}
@@ -108,8 +123,7 @@
if (!pData)
return;
- m_pData = std::move(pData);
- m_dwSize = dwSrcSize;
+ m_Data.emplace<OwnedData>(std::move(pData), dwSrcSize);
}
void CPDF_StreamAcc::ProcessFilteredData(uint32_t estimated_size,
@@ -118,15 +132,18 @@
if (dwSrcSize == 0)
return;
- MaybeOwned<uint8_t, FxFreeDeleter> pSrcData;
+ absl::variant<pdfium::span<const uint8_t>, OwnedData> src_data;
+ pdfium::span<const uint8_t> src_span;
if (m_pStream->IsMemoryBased()) {
- pSrcData = m_pStream->GetInMemoryRawData();
+ src_span = pdfium::make_span(m_pStream->GetInMemoryRawData(), dwSrcSize);
+ src_data = src_span;
} else {
std::unique_ptr<uint8_t, FxFreeDeleter> pTempSrcData = ReadRawStream();
if (!pTempSrcData)
return;
- pSrcData = std::move(pTempSrcData);
+ src_span = pdfium::make_span(pTempSrcData.get(), dwSrcSize);
+ src_data.emplace<OwnedData>(std::move(pTempSrcData), dwSrcSize);
}
std::unique_ptr<uint8_t, FxFreeDeleter> pDecodedData;
@@ -135,21 +152,18 @@
absl::optional<std::vector<std::pair<ByteString, const CPDF_Object*>>>
decoder_array = GetDecoderArray(m_pStream->GetDict());
if (!decoder_array.has_value() || decoder_array.value().empty() ||
- !PDF_DataDecode({pSrcData.Get(), dwSrcSize}, estimated_size, bImageAcc,
+ !PDF_DataDecode(src_span, estimated_size, bImageAcc,
decoder_array.value(), &pDecodedData, &dwDecodedSize,
&m_ImageDecoder, &m_pImageParam)) {
- m_pData = std::move(pSrcData);
- m_dwSize = dwSrcSize;
+ m_Data = std::move(src_data);
return;
}
if (pDecodedData) {
- DCHECK(pDecodedData.get() != pSrcData.Get());
- m_pData = std::move(pDecodedData);
- m_dwSize = dwDecodedSize;
+ DCHECK_NE(pDecodedData.get(), src_span.data());
+ m_Data.emplace<OwnedData>(std::move(pDecodedData), dwDecodedSize);
} else {
- m_pData = std::move(pSrcData);
- m_dwSize = dwSrcSize;
+ m_Data = std::move(src_data);
}
}
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.h b/core/fpdfapi/parser/cpdf_stream_acc.h
index c6b71f1..3314a0e 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.h
+++ b/core/fpdfapi/parser/cpdf_stream_acc.h
@@ -13,8 +13,8 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_memory_wrappers.h"
-#include "core/fxcrt/maybe_owned.h"
#include "core/fxcrt/retain_ptr.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/base/span.h"
class CPDF_Dictionary;
@@ -43,6 +43,17 @@
std::unique_ptr<uint8_t, FxFreeDeleter> DetachData();
private:
+ // TODO(crbug.com/pdfium/1872): Replace with fxcrt::DataVector.
+ struct OwnedData {
+ OwnedData(std::unique_ptr<uint8_t, FxFreeDeleter> buffer, uint32_t size);
+ OwnedData(OwnedData&&);
+ OwnedData& operator=(OwnedData&&);
+ ~OwnedData();
+
+ std::unique_ptr<uint8_t, FxFreeDeleter> buffer;
+ uint32_t size;
+ };
+
explicit CPDF_StreamAcc(const CPDF_Stream* pStream);
~CPDF_StreamAcc() override;
@@ -54,8 +65,9 @@
// Reads the raw data from |m_pStream|, or return nullptr on failure.
std::unique_ptr<uint8_t, FxFreeDeleter> ReadRawStream() const;
- MaybeOwned<uint8_t, FxFreeDeleter> m_pData;
- uint32_t m_dwSize = 0;
+ bool is_owned() const { return m_Data.index() == 1; }
+
+ absl::variant<pdfium::span<const uint8_t>, OwnedData> m_Data;
ByteString m_ImageDecoder;
RetainPtr<const CPDF_Dictionary> m_pImageParam;
RetainPtr<const CPDF_Stream> const m_pStream;