5#include "core/fpdfapi/parser/cpdf_cross_ref_avail.h"
7#include "core/fpdfapi/parser/cpdf_dictionary.h"
8#include "core/fpdfapi/parser/cpdf_read_validator.h"
9#include "core/fpdfapi/parser/cpdf_reference.h"
10#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
11#include "core/fpdfapi/parser/fpdf_parser_utility.h"
12#include "third_party/base/check.h"
13#include "third_party/base/containers/contains.h"
14#include "third_party/base/numerics/safe_conversions.h"
18constexpr char kCrossRefKeyword[] =
"xref";
19constexpr char kTrailerKeyword[] =
"trailer";
20constexpr char kPrevCrossRefFieldKey[] =
"Prev";
21constexpr char kTypeFieldKey[] =
"Type";
22constexpr char kPrevCrossRefStreamOffsetFieldKey[] =
"XRefStm";
23constexpr char kXRefKeyword[] =
"XRef";
24constexpr char kEncryptKey[] =
"Encrypt";
30 :
parser_(
parser), last_crossref_offset_(last_crossref_offset) {
32 AddCrossRefForCheck(last_crossref_offset);
43 bool check_result =
false;
45 case State::kCrossRefCheck:
46 check_result = CheckCrossRef();
48 case State::kCrossRefV4ItemCheck:
49 check_result = CheckCrossRefV4Item();
51 case State::kCrossRefV4TrailerCheck:
52 check_result = CheckCrossRefV4Trailer();
60 DCHECK(!GetValidator()->has_read_problems());
66 if (GetValidator()->read_error()) {
70 return GetValidator()->has_unavailable_data();
74 if (cross_refs_for_check_.empty()) {
76 state_ = State::kDone;
80 parser_->SetPos(cross_refs_for_check_.front());
82 const ByteString first_word = parser_->PeekNextWord();
83 if (CheckReadProblems())
86 const bool result = (first_word
== kCrossRefKeyword) ? CheckCrossRefV4()
87 : CheckCrossRefStream();
90 cross_refs_for_check_.pop();
96 const ByteString keyword = parser_->GetKeyword();
97 if (CheckReadProblems())
100 if (keyword
!= kCrossRefKeyword) {
105 state_ = State::kCrossRefV4ItemCheck;
106 offset_ = parser_->GetPos();
111 parser_->SetPos(offset_);
112 const ByteString keyword = parser_->GetKeyword();
113 if (CheckReadProblems())
121 if (keyword
== kTrailerKeyword)
122 state_ = State::kCrossRefV4TrailerCheck;
125 offset_ = parser_->GetPos();
130 parser_->SetPos(offset_);
133 ToDictionary(parser_->GetObjectBody(
nullptr));
134 if (CheckReadProblems())
142 if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
147 const int32_t xrefpos = trailer->GetDirectIntegerFor(kPrevCrossRefFieldKey);
149 pdfium::base::IsValueInRangeForNumericType<
FX_FILESIZE>(xrefpos))
150 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(xrefpos));
152 const int32_t stream_xref_offset =
153 trailer->GetDirectIntegerFor(kPrevCrossRefStreamOffsetFieldKey);
154 if (stream_xref_offset > 0 &&
155 pdfium::base::IsValueInRangeForNumericType<
FX_FILESIZE>(
157 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(stream_xref_offset));
160 state_ = State::kCrossRefCheck;
166 parser_->GetIndirectObject(
nullptr, CPDF_SyntaxParser::ParseType::kLoose);
167 if (CheckReadProblems())
170 RetainPtr<
const CPDF_Dictionary> trailer =
171 cross_ref && cross_ref->IsStream() ? cross_ref->GetDict() :
nullptr;
177 if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
182 if (trailer->GetNameFor(kTypeFieldKey) == kXRefKeyword) {
183 const int32_t xrefpos = trailer->GetIntegerFor(kPrevCrossRefFieldKey);
185 pdfium::base::IsValueInRangeForNumericType<
FX_FILESIZE>(xrefpos)) {
186 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(xrefpos));
190 state_ = State::kCrossRefCheck;
195 if (pdfium::Contains(registered_crossrefs_, crossref_offset))
198 cross_refs_for_check_.push(crossref_offset);
199 registered_crossrefs_.insert(crossref_offset);
203 return parser_->GetValidator();
CPDF_CrossRefAvail(CPDF_SyntaxParser *parser, FX_FILESIZE last_crossref_offset)
CPDF_DataAvail::DocAvailStatus CheckAvail()
bool operator==(const char *ptr) const
bool operator!=(const char *ptr) const