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.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 <algorithm>
8#include <utility>
9
10#include "core/fpdfapi/parser/cpdf_stream.h"
11#include "core/fxcrt/fx_safe_types.h"
12#include "third_party/base/notreached.h"
13
14namespace {
15
16constexpr FX_FILESIZE kAlignBlockValue = CPDF_Stream::kFileBufSize;
17
18FX_FILESIZE AlignDown(FX_FILESIZE offset) {
19 return offset > 0 ? (offset - offset % kAlignBlockValue) : 0;
20}
21
22FX_FILESIZE AlignUp(FX_FILESIZE offset) {
23 FX_SAFE_FILESIZE safe_result = AlignDown(offset);
24 safe_result += kAlignBlockValue;
25 return safe_result.ValueOrDefault(offset);
26}
27
28} // namespace
29
37
39 validator_->read_error_ |= saved_read_error_;
40 validator_->has_unavailable_data_ |= saved_has_unavailable_data_;
41}
42
49
51
53 read_error_ = false;
54 has_unavailable_data_ = false;
55}
56
57bool CPDF_ReadValidator::ReadBlockAtOffset(pdfium::span<uint8_t> buffer,
58 FX_FILESIZE offset) {
59 if (offset < 0) {
60 NOTREACHED();
61 return false;
62 }
63
64 FX_SAFE_FILESIZE end_offset = offset;
65 end_offset += buffer.size();
66 if (!end_offset.IsValid() || end_offset.ValueOrDie() > file_size_)
67 return false;
68
69 if (!IsDataRangeAvailable(offset, buffer.size())) {
70 ScheduleDownload(offset, buffer.size());
71 return false;
72 }
73
74 if (file_read_->ReadBlockAtOffset(buffer, offset))
75 return true;
76
77 read_error_ = true;
78 ScheduleDownload(offset, buffer.size());
79 return false;
80}
81
83 return file_size_;
84}
85
86void CPDF_ReadValidator::ScheduleDownload(FX_FILESIZE offset, size_t size) {
87 has_unavailable_data_ = true;
88 if (!hints_ || size == 0)
89 return;
90
91 const FX_FILESIZE start_segment_offset = AlignDown(offset);
92 FX_SAFE_FILESIZE end_segment_offset = offset;
93 end_segment_offset += size;
94 if (!end_segment_offset.IsValid()) {
95 NOTREACHED();
96 return;
97 }
98 end_segment_offset =
99 std::min(file_size_, AlignUp(end_segment_offset.ValueOrDie()));
100
101 FX_SAFE_SIZE_T segment_size = end_segment_offset;
102 segment_size -= start_segment_offset;
103 if (!segment_size.IsValid()) {
104 NOTREACHED();
105 return;
106 }
107 hints_->AddSegment(start_segment_offset, segment_size.ValueOrDie());
108}
109
110bool CPDF_ReadValidator::IsDataRangeAvailable(FX_FILESIZE offset,
111 size_t size) const {
112 return whole_file_already_available_ || !file_avail_ ||
113 file_avail_->IsDataAvail(offset, size);
114}
115
117 const FX_SAFE_SIZE_T safe_size = file_size_;
118 whole_file_already_available_ =
119 whole_file_already_available_ ||
120 (safe_size.IsValid() && IsDataRangeAvailable(0, safe_size.ValueOrDie()));
121
122 return whole_file_already_available_;
123}
124
126 FX_FILESIZE offset,
127 size_t size) {
128 if (offset > file_size_)
129 return true;
130
131 FX_SAFE_FILESIZE end_segment_offset = offset;
132 end_segment_offset += size;
133 // Increase checked range to allow CPDF_SyntaxParser read whole buffer.
134 end_segment_offset += CPDF_Stream::kFileBufSize;
135 if (!end_segment_offset.IsValid()) {
136 NOTREACHED();
137 return false;
138 }
139 end_segment_offset = std::min(
140 file_size_, static_cast<FX_FILESIZE>(end_segment_offset.ValueOrDie()));
141 FX_SAFE_SIZE_T segment_size = end_segment_offset;
142 segment_size -= offset;
143 if (!segment_size.IsValid()) {
144 NOTREACHED();
145 return false;
146 }
147
148 if (IsDataRangeAvailable(offset, segment_size.ValueOrDie()))
149 return true;
150
151 ScheduleDownload(offset, segment_size.ValueOrDie());
152 return false;
153}
154
157 return true;
158
159 const FX_SAFE_SIZE_T safe_size = file_size_;
160 if (safe_size.IsValid())
161 ScheduleDownload(0, safe_size.ValueOrDie());
162
163 return false;
164}
ScopedSession(RetainPtr< CPDF_ReadValidator > validator)
CPDF_ReadValidator(RetainPtr< IFX_SeekableReadStream > file_read, CPDF_DataAvail::FileAvail *file_avail)
FX_FILESIZE GetSize() override
bool CheckDataRangeAndRequestIfUnavailable(FX_FILESIZE offset, size_t size)
~CPDF_ReadValidator() override
bool ReadBlockAtOffset(pdfium::span< uint8_t > buffer, FX_FILESIZE offset) override
static constexpr int kFileBufSize
Definition cpdf_stream.h:25
#define FX_FILESIZE
Definition fx_types.h:19