Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_read_validator_unittest.cpp
Go to the documentation of this file.
1// Copyright 2017 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#include "core/fpdfapi/parser/cpdf_read_validator.h"
6
7#include <stdint.h>
8
9#include <limits>
10#include <utility>
11
12#include "core/fxcrt/cfx_read_only_span_stream.h"
13#include "core/fxcrt/cfx_read_only_vector_stream.h"
14#include "core/fxcrt/data_vector.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "testing/invalid_seekable_read_stream.h"
17
18namespace {
19
20constexpr uint32_t kTestDataSize = 64 * 1024 - 467;
21
22std::pair<FX_FILESIZE, FX_FILESIZE> MakeRange(uint32_t start, uint32_t end) {
23 return std::pair<FX_FILESIZE, FX_FILESIZE>(start, end);
24}
25
26class MockFileAvail final : public CPDF_DataAvail::FileAvail {
27 public:
28 MockFileAvail() : available_range_(0, 0) {}
29 ~MockFileAvail() override = default;
30
31 bool IsDataAvail(FX_FILESIZE offset, size_t size) override {
32 return available_range_.first <= offset &&
33 available_range_.second >= static_cast<FX_FILESIZE>(offset + size);
34 }
35
36 void SetAvailableRange(const std::pair<FX_FILESIZE, FX_FILESIZE>& range) {
37 available_range_ = range;
38 }
39
40 void SetAvailableRange(uint32_t start, uint32_t end) {
41 SetAvailableRange(MakeRange(start, end));
42 }
43
44 private:
45 std::pair<FX_FILESIZE, FX_FILESIZE> available_range_;
46};
47
48class MockDownloadHints final : public CPDF_DataAvail::DownloadHints {
49 public:
50 MockDownloadHints() : last_requested_range_(0, 0) {}
51 ~MockDownloadHints() override = default;
52
53 void AddSegment(FX_FILESIZE offset, size_t size) override {
54 last_requested_range_.first = offset;
55 last_requested_range_.second = offset + size;
56 }
57
58 const std::pair<FX_FILESIZE, FX_FILESIZE>& GetLastRequstedRange() const {
59 return last_requested_range_;
60 }
61
62 void Reset() { last_requested_range_ = MakeRange(0, 0); }
63
64 private:
65 std::pair<FX_FILESIZE, FX_FILESIZE> last_requested_range_;
66};
67
68} // namespace
69
71 DataVector<uint8_t> test_data(kTestDataSize);
72 auto file =
73 pdfium::MakeRetain<CFX_ReadOnlyVectorStream>(std::move(test_data));
74 MockFileAvail file_avail;
75 auto validator =
76 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
77
78 DataVector<uint8_t> read_buffer(100);
79 EXPECT_FALSE(validator->ReadBlockAtOffset(read_buffer, 5000));
80 EXPECT_FALSE(validator->read_error());
81 EXPECT_TRUE(validator->has_unavailable_data());
82
83 validator->ResetErrors();
84 file_avail.SetAvailableRange(5000, 5000 + read_buffer.size());
85 EXPECT_TRUE(validator->ReadBlockAtOffset(read_buffer, 5000));
86 EXPECT_FALSE(validator->read_error());
87 EXPECT_FALSE(validator->has_unavailable_data());
88}
89
91 DataVector<uint8_t> test_data(kTestDataSize);
92 auto file =
93 pdfium::MakeRetain<CFX_ReadOnlyVectorStream>(std::move(test_data));
94 MockFileAvail file_avail;
95 auto validator =
96 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
97
98 MockDownloadHints hints;
99 validator->SetDownloadHints(&hints);
100
101 DataVector<uint8_t> read_buffer(100);
102 EXPECT_FALSE(validator->ReadBlockAtOffset(read_buffer, 5000));
103 EXPECT_FALSE(validator->read_error());
104 EXPECT_TRUE(validator->has_unavailable_data());
105
106 // Requested range should be enlarged and aligned.
107 EXPECT_EQ(MakeRange(4608, 5120), hints.GetLastRequstedRange());
108
109 file_avail.SetAvailableRange(hints.GetLastRequstedRange());
110 hints.Reset();
111
112 validator->ResetErrors();
113 EXPECT_TRUE(validator->ReadBlockAtOffset(read_buffer, 5000));
114 // No new request on already available data.
115 EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange());
116 EXPECT_FALSE(validator->read_error());
117 EXPECT_FALSE(validator->has_unavailable_data());
118
119 validator->ResetErrors();
120 // Try read unavailable data at file end.
121 EXPECT_FALSE(validator->ReadBlockAtOffset(
122 read_buffer, validator->GetSize() - read_buffer.size()));
123 // Should not enlarge request at file end.
124 EXPECT_EQ(validator->GetSize(), hints.GetLastRequstedRange().second);
125 EXPECT_FALSE(validator->read_error());
126 EXPECT_TRUE(validator->has_unavailable_data());
127
128 validator->SetDownloadHints(nullptr);
129}
130
132 auto file = pdfium::MakeRetain<InvalidSeekableReadStream>(kTestDataSize);
133 auto validator =
134 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), nullptr);
135
136 static const uint32_t kBufferSize = 3 * 1000;
137 DataVector<uint8_t> buffer(kBufferSize);
138
139 EXPECT_FALSE(
140 validator->ReadBlockAtOffset(pdfium::make_span(buffer).first(100), 5000));
141 EXPECT_TRUE(validator->read_error());
142 EXPECT_TRUE(validator->has_unavailable_data());
143}
144
146 DataVector<uint8_t> test_data(kTestDataSize);
147 auto file =
148 pdfium::MakeRetain<CFX_ReadOnlyVectorStream>(std::move(test_data));
149 MockFileAvail file_avail;
150 auto validator =
151 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
152
153 DataVector<uint8_t> read_buffer(100);
154
155 // If we have int overflow, this is equal reading after file end. This is not
156 // read_error, and in this case we have not unavailable data. It is just error
157 // of input params.
158 EXPECT_FALSE(validator->ReadBlockAtOffset(
159 read_buffer, std::numeric_limits<FX_FILESIZE>::max() - 1));
160 EXPECT_FALSE(validator->read_error());
161 EXPECT_FALSE(validator->has_unavailable_data());
162}
163
165 DataVector<uint8_t> test_data(kTestDataSize);
166
167 auto file = pdfium::MakeRetain<InvalidSeekableReadStream>(kTestDataSize);
168 MockFileAvail file_avail;
169 MockDownloadHints hints;
170 auto validator =
171 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
172 validator->SetDownloadHints(&hints);
173
174 CPDF_ReadValidator::ScopedSession read_session(validator);
175 ASSERT_FALSE(validator->has_read_problems());
176
177 // Data is unavailable
178 validator->ReadBlockAtOffset(pdfium::make_span(test_data).first(100), 0);
179 EXPECT_TRUE(validator->has_read_problems());
180 EXPECT_TRUE(validator->has_unavailable_data());
181 EXPECT_FALSE(validator->read_error());
182
183 {
184 CPDF_ReadValidator::ScopedSession read_subsession(validator);
185 // The read problems should be hidden.
186 EXPECT_FALSE(validator->has_read_problems());
187
188 file_avail.SetAvailableRange(0, 100);
189 // Read fail.
190 validator->ReadBlockAtOffset(pdfium::make_span(test_data).first(100), 0);
191 EXPECT_TRUE(validator->has_read_problems());
192 EXPECT_TRUE(validator->has_unavailable_data());
193 EXPECT_TRUE(validator->read_error());
194 }
195
196 // The problems should be merged
197 EXPECT_TRUE(validator->has_read_problems());
198 EXPECT_TRUE(validator->has_unavailable_data());
199 EXPECT_TRUE(validator->read_error());
200}
201
203 DataVector<uint8_t> test_data(kTestDataSize);
204
205 auto file = pdfium::MakeRetain<InvalidSeekableReadStream>(kTestDataSize);
206 MockFileAvail file_avail;
207 MockDownloadHints hints;
208 auto validator =
209 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
210 validator->SetDownloadHints(&hints);
211
212 CPDF_ReadValidator::ScopedSession read_session(validator);
213 ASSERT_FALSE(validator->has_read_problems());
214
215 // Data is unavailable
216 validator->ReadBlockAtOffset(pdfium::make_span(test_data).first(100), 0);
217 EXPECT_TRUE(validator->has_read_problems());
218 EXPECT_TRUE(validator->has_unavailable_data());
219 EXPECT_FALSE(validator->read_error());
220
221 {
222 CPDF_ReadValidator::ScopedSession read_subsession(validator);
223 // The read problems should be hidden.
224 EXPECT_FALSE(validator->has_read_problems());
225
226 file_avail.SetAvailableRange(0, 100);
227 // Read fail.
228 validator->ReadBlockAtOffset(pdfium::make_span(test_data).first(100), 0);
229 EXPECT_TRUE(validator->has_read_problems());
230 EXPECT_TRUE(validator->has_unavailable_data());
231 EXPECT_TRUE(validator->read_error());
232
233 // Reset session.
234 validator->ResetErrors();
235 EXPECT_FALSE(validator->has_read_problems());
236 }
237
238 // The problems should be restored.
239 EXPECT_TRUE(validator->has_read_problems());
240 EXPECT_TRUE(validator->has_unavailable_data());
241 EXPECT_FALSE(validator->read_error());
242}
243
245 DataVector<uint8_t> test_data(kTestDataSize);
246 auto file =
247 pdfium::MakeRetain<CFX_ReadOnlyVectorStream>(std::move(test_data));
248 MockFileAvail file_avail;
249 auto validator =
250 pdfium::MakeRetain<CPDF_ReadValidator>(std::move(file), &file_avail);
251
252 MockDownloadHints hints;
253 validator->SetDownloadHints(&hints);
254
255 EXPECT_FALSE(validator->CheckDataRangeAndRequestIfUnavailable(5000, 100));
256 EXPECT_FALSE(validator->read_error());
257 EXPECT_TRUE(validator->has_unavailable_data());
258
259 // Requested range should be enlarged and aligned.
260 EXPECT_EQ(MakeRange(4608, 5632), hints.GetLastRequstedRange());
261
262 file_avail.SetAvailableRange(hints.GetLastRequstedRange());
263 hints.Reset();
264
265 validator->ResetErrors();
266 EXPECT_TRUE(validator->CheckDataRangeAndRequestIfUnavailable(5000, 100));
267 // No new request on already available data.
268 EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange());
269 EXPECT_FALSE(validator->read_error());
270 EXPECT_FALSE(validator->has_unavailable_data());
271
272 DataVector<uint8_t> read_buffer(100);
273 EXPECT_TRUE(validator->ReadBlockAtOffset(read_buffer, 5000));
274 // No new request on already available data.
275 EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange());
276 EXPECT_FALSE(validator->read_error());
277 EXPECT_FALSE(validator->has_unavailable_data());
278
279 validator->ResetErrors();
280 // Try request unavailable data at file end.
281 EXPECT_FALSE(validator->CheckDataRangeAndRequestIfUnavailable(
282 validator->GetSize() - 100, 100));
283
284 // Should not enlarge request at file end.
285 EXPECT_EQ(validator->GetSize(), hints.GetLastRequstedRange().second);
286 EXPECT_FALSE(validator->read_error());
287 EXPECT_TRUE(validator->has_unavailable_data());
288
289 validator->ResetErrors();
290 // Offset > file size should yield |true| and not cause a fetch.
291 EXPECT_TRUE(
292 validator->CheckDataRangeAndRequestIfUnavailable(kTestDataSize + 1, 1));
293 // No new request on already available data.
294 EXPECT_FALSE(validator->read_error());
295 EXPECT_FALSE(validator->has_unavailable_data());
296
297 validator->SetDownloadHints(nullptr);
298}
TEST(FXCRYPT, MD5GenerateEmtpyData)
#define FX_FILESIZE
Definition fx_types.h:19