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_object_avail.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_object_avail.h"
6
7#include <utility>
8
9#include "core/fpdfapi/parser/cpdf_dictionary.h"
10#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
11#include "core/fpdfapi/parser/cpdf_object_walker.h"
12#include "core/fpdfapi/parser/cpdf_read_validator.h"
13#include "core/fpdfapi/parser/cpdf_reference.h"
14#include "third_party/base/check.h"
15#include "third_party/base/containers/contains.h"
16
19 RetainPtr<const CPDF_Object> root)
23 DCHECK(validator_);
24 DCHECK(holder);
25 DCHECK(root_);
26 if (!root_->IsInline())
27 parsed_objnums_.insert(root_->GetObjNum());
28}
29
32 uint32_t obj_num)
36 DCHECK(validator_);
37 DCHECK(holder);
38}
39
41
43 if (!LoadRootObject())
44 return CPDF_DataAvail::kDataNotAvailable;
45
46 if (CheckObjects()) {
47 CleanMemory();
48 return CPDF_DataAvail::kDataAvailable;
49 }
50 return CPDF_DataAvail::kDataNotAvailable;
51}
52
53bool CPDF_ObjectAvail::LoadRootObject() {
54 if (!non_parsed_objects_.empty())
55 return true;
56
57 while (root_ && root_->IsReference()) {
58 const uint32_t ref_obj_num = root_->AsReference()->GetRefObjNum();
59 if (HasObjectParsed(ref_obj_num)) {
60 root_ = nullptr;
61 return true;
62 }
63
64 CPDF_ReadValidator::ScopedSession parse_session(validator_);
65 RetainPtr<CPDF_Object> direct =
66 holder_->GetOrParseIndirectObject(ref_obj_num);
67 if (validator_->has_read_problems())
68 return false;
69
70 parsed_objnums_.insert(ref_obj_num);
71 root_ = std::move(direct);
72 }
73 std::stack<uint32_t> non_parsed_objects_in_root;
74 if (AppendObjectSubRefs(root_, &non_parsed_objects_in_root)) {
75 non_parsed_objects_ = std::move(non_parsed_objects_in_root);
76 return true;
77 }
78 return false;
79}
80
81bool CPDF_ObjectAvail::CheckObjects() {
82 std::set<uint32_t> checked_objects;
83 std::stack<uint32_t> objects_to_check = std::move(non_parsed_objects_);
84 non_parsed_objects_ = std::stack<uint32_t>();
85 while (!objects_to_check.empty()) {
86 const uint32_t obj_num = objects_to_check.top();
87 objects_to_check.pop();
88
89 if (HasObjectParsed(obj_num))
90 continue;
91
92 if (!checked_objects.insert(obj_num).second)
93 continue;
94
95 CPDF_ReadValidator::ScopedSession parse_session(validator_);
96 RetainPtr<const CPDF_Object> direct =
97 holder_->GetOrParseIndirectObject(obj_num);
98 if (direct == root_)
99 continue;
100
101 if (validator_->has_read_problems() ||
102 !AppendObjectSubRefs(std::move(direct), &objects_to_check)) {
103 non_parsed_objects_.push(obj_num);
104 continue;
105 }
106 parsed_objnums_.insert(obj_num);
107 }
108 return non_parsed_objects_.empty();
109}
110
111bool CPDF_ObjectAvail::AppendObjectSubRefs(RetainPtr<const CPDF_Object> object,
112 std::stack<uint32_t>* refs) const {
113 DCHECK(refs);
114 if (!object)
115 return true;
116
117 CPDF_ObjectWalker walker(std::move(object));
118 while (RetainPtr<const CPDF_Object> obj = walker.GetNext()) {
119 CPDF_ReadValidator::ScopedSession parse_session(validator_);
120
121 // Skip if this object if it's an inlined root, the parent object or
122 // explicitily excluded.
123 const bool skip = (walker.GetParent() && obj == root_) ||
124 walker.dictionary_key() == "Parent" ||
125 (obj != root_ && ExcludeObject(obj.Get()));
126
127 // We need to parse the object before we can do the exclusion check.
128 // This is because the exclusion check may check against a referenced
129 // field of the object which we need to make sure is loaded.
130 if (validator_->has_read_problems())
131 return false;
132
133 if (skip) {
135 continue;
136 }
137
138 if (obj->IsReference())
139 refs->push(obj->AsReference()->GetRefObjNum());
140 }
141 return true;
142}
143
144void CPDF_ObjectAvail::CleanMemory() {
145 root_.Reset();
146 parsed_objnums_.clear();
147}
148
149bool CPDF_ObjectAvail::ExcludeObject(const CPDF_Object* object) const {
150 return false;
151}
152
153bool CPDF_ObjectAvail::HasObjectParsed(uint32_t obj_num) const {
154 return pdfium::Contains(parsed_objnums_, obj_num);
155}
CPDF_DataAvail::DocAvailStatus CheckAvail()
CPDF_ObjectAvail(RetainPtr< CPDF_ReadValidator > validator, CPDF_IndirectObjectHolder *holder, RetainPtr< const CPDF_Object > root)
virtual ~CPDF_ObjectAvail()
virtual bool ExcludeObject(const CPDF_Object *object) const
CPDF_ObjectAvail(RetainPtr< CPDF_ReadValidator > validator, CPDF_IndirectObjectHolder *holder, uint32_t obj_num)