xref: /aosp_15_r20/external/pdfium/core/fpdfapi/parser/cpdf_stream_acc.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2016 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
8 
9 #include <utility>
10 
11 #include "core/fdrm/fx_crypt.h"
12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
13 #include "core/fpdfapi/parser/cpdf_stream.h"
14 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
15 #include "core/fxcrt/data_vector.h"
16 #include "third_party/base/check_op.h"
17 
CPDF_StreamAcc(RetainPtr<const CPDF_Stream> pStream)18 CPDF_StreamAcc::CPDF_StreamAcc(RetainPtr<const CPDF_Stream> pStream)
19     : m_pStream(std::move(pStream)) {}
20 
21 CPDF_StreamAcc::~CPDF_StreamAcc() = default;
22 
LoadAllData(bool bRawAccess,uint32_t estimated_size,bool bImageAcc)23 void CPDF_StreamAcc::LoadAllData(bool bRawAccess,
24                                  uint32_t estimated_size,
25                                  bool bImageAcc) {
26   if (bRawAccess) {
27     DCHECK(!estimated_size);
28     DCHECK(!bImageAcc);
29   }
30 
31   if (!m_pStream)
32     return;
33 
34   bool bProcessRawData = bRawAccess || !m_pStream->HasFilter();
35   if (bProcessRawData)
36     ProcessRawData();
37   else
38     ProcessFilteredData(estimated_size, bImageAcc);
39 }
40 
LoadAllDataFiltered()41 void CPDF_StreamAcc::LoadAllDataFiltered() {
42   LoadAllData(false, 0, false);
43 }
44 
LoadAllDataFilteredWithEstimatedSize(uint32_t estimated_size)45 void CPDF_StreamAcc::LoadAllDataFilteredWithEstimatedSize(
46     uint32_t estimated_size) {
47   LoadAllData(false, estimated_size, false);
48 }
49 
LoadAllDataImageAcc(uint32_t estimated_size)50 void CPDF_StreamAcc::LoadAllDataImageAcc(uint32_t estimated_size) {
51   LoadAllData(false, estimated_size, true);
52 }
53 
LoadAllDataRaw()54 void CPDF_StreamAcc::LoadAllDataRaw() {
55   LoadAllData(true, 0, false);
56 }
57 
GetStream() const58 RetainPtr<const CPDF_Stream> CPDF_StreamAcc::GetStream() const {
59   return m_pStream;
60 }
61 
GetLength1ForTest() const62 int CPDF_StreamAcc::GetLength1ForTest() const {
63   return m_pStream->GetDict()->GetIntegerFor("Length1");
64 }
65 
GetImageParam() const66 RetainPtr<const CPDF_Dictionary> CPDF_StreamAcc::GetImageParam() const {
67   return m_pImageParam;
68 }
69 
GetSize() const70 uint32_t CPDF_StreamAcc::GetSize() const {
71   return GetSpan().size();
72 }
73 
GetSpan() const74 pdfium::span<const uint8_t> CPDF_StreamAcc::GetSpan() const {
75   if (is_owned())
76     return absl::get<DataVector<uint8_t>>(m_Data);
77   if (m_pStream && m_pStream->IsMemoryBased())
78     return m_pStream->GetInMemoryRawData();
79   return {};
80 }
81 
KeyForCache() const82 uint64_t CPDF_StreamAcc::KeyForCache() const {
83   return m_pStream ? m_pStream->KeyForCache() : 0;
84 }
85 
ComputeDigest() const86 ByteString CPDF_StreamAcc::ComputeDigest() const {
87   uint8_t digest[20];
88   pdfium::span<const uint8_t> span = GetSpan();
89   CRYPT_SHA1Generate(span.data(), span.size(), digest);
90   return ByteString(digest, 20);
91 }
92 
DetachData()93 DataVector<uint8_t> CPDF_StreamAcc::DetachData() {
94   if (is_owned())
95     return std::move(absl::get<DataVector<uint8_t>>(m_Data));
96 
97   auto span = absl::get<pdfium::span<const uint8_t>>(m_Data);
98   return DataVector<uint8_t>(span.begin(), span.end());
99 }
100 
ProcessRawData()101 void CPDF_StreamAcc::ProcessRawData() {
102   if (m_pStream->IsUninitialized())
103     return;
104 
105   uint32_t dwSrcSize = m_pStream->GetRawSize();
106   if (dwSrcSize == 0)
107     return;
108 
109   if (m_pStream->IsMemoryBased()) {
110     m_Data = m_pStream->GetInMemoryRawData();
111     return;
112   }
113 
114   DataVector<uint8_t> data = ReadRawStream();
115   if (data.empty())
116     return;
117 
118   m_Data = std::move(data);
119 }
120 
ProcessFilteredData(uint32_t estimated_size,bool bImageAcc)121 void CPDF_StreamAcc::ProcessFilteredData(uint32_t estimated_size,
122                                          bool bImageAcc) {
123   if (m_pStream->IsUninitialized())
124     return;
125 
126   uint32_t dwSrcSize = m_pStream->GetRawSize();
127   if (dwSrcSize == 0)
128     return;
129 
130   absl::variant<pdfium::span<const uint8_t>, DataVector<uint8_t>> src_data;
131   pdfium::span<const uint8_t> src_span;
132   if (m_pStream->IsMemoryBased()) {
133     src_span = m_pStream->GetInMemoryRawData();
134     src_data = src_span;
135   } else {
136     DataVector<uint8_t> temp_src_data = ReadRawStream();
137     if (temp_src_data.empty())
138       return;
139 
140     src_span = pdfium::make_span(temp_src_data);
141     src_data = std::move(temp_src_data);
142   }
143 
144   std::unique_ptr<uint8_t, FxFreeDeleter> pDecodedData;
145   uint32_t dwDecodedSize = 0;
146 
147   absl::optional<DecoderArray> decoder_array =
148       GetDecoderArray(m_pStream->GetDict());
149   if (!decoder_array.has_value() || decoder_array.value().empty() ||
150       !PDF_DataDecode(src_span, estimated_size, bImageAcc,
151                       decoder_array.value(), &pDecodedData, &dwDecodedSize,
152                       &m_ImageDecoder, &m_pImageParam)) {
153     m_Data = std::move(src_data);
154     return;
155   }
156 
157   if (pDecodedData) {
158     DCHECK_NE(pDecodedData.get(), src_span.data());
159     // TODO(crbug.com/pdfium/1872): Avoid copying.
160     m_Data = DataVector<uint8_t>(pDecodedData.get(),
161                                  pDecodedData.get() + dwDecodedSize);
162   } else {
163     m_Data = std::move(src_data);
164   }
165 }
166 
ReadRawStream() const167 DataVector<uint8_t> CPDF_StreamAcc::ReadRawStream() const {
168   DCHECK(m_pStream);
169   DCHECK(m_pStream->IsFileBased());
170   return m_pStream->ReadAllRawData();
171 }
172