summaryrefslogtreecommitdiff
path: root/core/fpdfapi/parser/cpdf_linearized_header.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/parser/cpdf_linearized_header.cpp')
-rw-r--r--core/fpdfapi/parser/cpdf_linearized_header.cpp40
1 files changed, 35 insertions, 5 deletions
diff --git a/core/fpdfapi/parser/cpdf_linearized_header.cpp b/core/fpdfapi/parser/cpdf_linearized_header.cpp
index 98cdcc450f..ce22c55f48 100644
--- a/core/fpdfapi/parser/cpdf_linearized_header.cpp
+++ b/core/fpdfapi/parser/cpdf_linearized_header.cpp
@@ -12,10 +12,13 @@
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_number.h"
+#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
#include "third_party/base/ptr_util.h"
namespace {
+constexpr FX_FILESIZE kLinearizedHeaderOffset = 9;
+
template <class T>
bool IsValidNumericDictionaryValue(const CPDF_Dictionary* pDict,
const char* key,
@@ -32,21 +35,48 @@ bool IsValidNumericDictionaryValue(const CPDF_Dictionary* pDict,
return static_cast<T>(raw_value) >= min_value;
}
+bool IsLinearizedHeaderValid(const CPDF_LinearizedHeader* header,
+ FX_FILESIZE file_size) {
+ ASSERT(header);
+ return header->GetFileSize() == file_size &&
+ header->GetMainXRefTableFirstEntryOffset() < file_size &&
+ header->GetPageCount() > 0 &&
+ header->GetFirstPageEndOffset() < file_size &&
+ header->GetLastXRefOffset() < file_size &&
+ header->GetHintStart() < file_size;
+}
+
} // namespace
// static
-std::unique_ptr<CPDF_LinearizedHeader> CPDF_LinearizedHeader::CreateForObject(
- std::unique_ptr<CPDF_Object> pObj) {
- auto pDict = ToDictionary(std::move(pObj));
+std::unique_ptr<CPDF_LinearizedHeader> CPDF_LinearizedHeader::Parse(
+ CPDF_SyntaxParser* parser) {
+ parser->SetPos(kLinearizedHeaderOffset);
+
+ const auto pDict = ToDictionary(
+ parser->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose));
+
if (!pDict || !pDict->KeyExist("Linearized") ||
!IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "L", 1) ||
!IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "P", 0, false) ||
!IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "T", 1) ||
!IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "N", 0) ||
!IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "E", 1) ||
- !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "O", 1))
+ !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "O", 1)) {
return nullptr;
- return pdfium::WrapUnique(new CPDF_LinearizedHeader(pDict.get()));
+ }
+ // Move parser to the start of the xref table for the documents first page.
+ // (skpping endobj keyword)
+ if (parser->GetNextWord(nullptr) != "endobj")
+ return nullptr;
+
+ auto result = pdfium::WrapUnique(new CPDF_LinearizedHeader(pDict.get()));
+ result->m_szLastXRefOffset = parser->GetPos();
+
+ return IsLinearizedHeaderValid(result.get(),
+ parser->GetFileAccess()->GetSize())
+ ? std::move(result)
+ : nullptr;
}
CPDF_LinearizedHeader::CPDF_LinearizedHeader(const CPDF_Dictionary* pDict) {