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 "core/fxcrt/check.h"
13#include "core/fxcrt/containers/contains.h"
14#include "core/fxcrt/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::kCrossRefTableItemCheck:
49 check_result = CheckCrossRefTableItem();
51 case State::kCrossRefTableTrailerCheck:
52 check_result = CheckCrossRefTableTrailer();
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) ? CheckCrossRefTable()
87 : CheckCrossRefStream();
90 cross_refs_for_check_.pop();
96 const ByteString keyword = parser_->GetKeyword();
97 if (CheckReadProblems())
100 if (keyword
!= kCrossRefKeyword) {
105 state_ = State::kCrossRefTableItemCheck;
106 offset_ = parser_->GetPos();
111 parser_->SetPos(offset_);
112 const ByteString keyword = parser_->GetKeyword();
113 if (CheckReadProblems())
116 if (keyword.IsEmpty()) {
121 if (keyword
== kTrailerKeyword)
122 state_ = State::kCrossRefTableTrailerCheck;
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);
150 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(xrefpos));
153 const int32_t stream_xref_offset =
154 trailer->GetDirectIntegerFor(kPrevCrossRefStreamOffsetFieldKey);
155 if (stream_xref_offset > 0 &&
157 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(stream_xref_offset));
161 state_ = State::kCrossRefCheck;
167 parser_->GetIndirectObject(
nullptr, CPDF_SyntaxParser::ParseType::kLoose);
168 if (CheckReadProblems())
172 cross_ref && cross_ref->IsStream() ? cross_ref->GetDict() :
nullptr;
178 if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
183 if (trailer->GetNameFor(kTypeFieldKey) == kXRefKeyword) {
184 const int32_t xrefpos = trailer->GetIntegerFor(kPrevCrossRefFieldKey);
187 AddCrossRefForCheck(
static_cast<
FX_FILESIZE>(xrefpos));
191 state_ = State::kCrossRefCheck;
196 if (pdfium::Contains(registered_crossrefs_, crossref_offset))
199 cross_refs_for_check_.push(crossref_offset);
200 registered_crossrefs_.insert(crossref_offset);
204 return parser_->GetValidator();
fxcrt::ByteString ByteString
CPDF_CrossRefAvail(CPDF_SyntaxParser *parser, FX_FILESIZE last_crossref_offset)
CPDF_DataAvail::DocAvailStatus CheckAvail()
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
bool operator==(const char *ptr) const
bool operator!=(const char *ptr) const