summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfapi/parser/cpdf_parser.cpp89
-rw-r--r--core/fpdfapi/parser/cpdf_parser.h10
2 files changed, 55 insertions, 44 deletions
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index b2bde8d242..841bf2778a 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -52,14 +52,14 @@ int32_t GetStreamFirst(const CFX_RetainPtr<CPDF_StreamAcc>& pObjStream) {
} // namespace
CPDF_Parser::CPDF_Parser()
- : m_bHasParsed(false),
+ : m_pSyntax(pdfium::MakeUnique<CPDF_SyntaxParser>()),
+ m_bHasParsed(false),
m_bXRefStream(false),
m_bVersionUpdated(false),
m_FileVersion(0),
m_pEncryptDict(nullptr),
- m_dwXrefStartObjNum(0) {
- m_pSyntax = pdfium::MakeUnique<CPDF_SyntaxParser>();
-}
+ m_TrailerPos(CPDF_Parser::kInvalidPos),
+ m_dwXrefStartObjNum(0) {}
CPDF_Parser::~CPDF_Parser() {
ReleaseEncryptHandler();
@@ -219,12 +219,13 @@ CPDF_Parser::Error CPDF_Parser::StartParse(
}
return SUCCESS;
}
+
CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() {
ReleaseEncryptHandler();
- if (!m_pTrailer)
+ if (!GetTrailer())
return FORMAT_ERROR;
- CPDF_Object* pEncryptObj = m_pTrailer->GetObjectFor("Encrypt");
+ CPDF_Object* pEncryptObj = GetTrailer()->GetObjectFor("Encrypt");
if (pEncryptObj) {
if (CPDF_Dictionary* pEncryptDict = pEncryptObj->AsDictionary()) {
SetEncryptDictionary(pEncryptDict);
@@ -304,11 +305,13 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
if (!LoadCrossRefV4(xrefpos, 0, true))
return false;
- m_pTrailer = LoadTrailerV4();
- if (!m_pTrailer)
+ std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+ if (!trailer)
return false;
- int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size");
+ m_Trailers.push_back(std::move(trailer));
+ m_TrailerPos = m_Trailers.size() - 1;
+ int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size");
if (xrefsize > 0 && xrefsize <= kMaxXRefSize)
ShrinkObjectMap(xrefsize);
@@ -317,12 +320,12 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
std::set<FX_FILESIZE> seen_xrefpos;
CrossRefList.push_back(xrefpos);
- XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm"));
+ XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm"));
seen_xrefpos.insert(xrefpos);
- // When |m_pTrailer| doesn't have Prev entry or Prev entry value is not
+ // When the trailer doesn't have Prev entry or Prev entry value is not
// numerical, GetDirectInteger() returns 0. Loading will end.
- xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev");
+ xrefpos = GetDirectInteger(GetTrailer(), "Prev");
while (xrefpos) {
// Check for circular references.
if (pdfium::ContainsKey(seen_xrefpos, xrefpos))
@@ -360,14 +363,13 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos,
if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount))
return false;
- if (m_pTrailer)
- m_Trailers.push_back(std::move(m_pTrailer));
-
- m_pTrailer = LoadTrailerV4();
- if (!m_pTrailer)
+ std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+ if (!trailer)
return false;
- int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size");
+ m_Trailers.push_back(std::move(trailer));
+ m_TrailerPos = m_Trailers.size() - 1;
+ int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size");
if (xrefsize == 0)
return false;
@@ -376,10 +378,10 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos,
std::set<FX_FILESIZE> seen_xrefpos;
CrossRefList.push_back(xrefpos);
- XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm"));
+ XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm"));
seen_xrefpos.insert(xrefpos);
- xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev");
+ xrefpos = GetDirectInteger(GetTrailer(), "Prev");
while (xrefpos) {
// Check for circular references.
if (pdfium::ContainsKey(seen_xrefpos, xrefpos))
@@ -568,7 +570,8 @@ bool CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) {
bool CPDF_Parser::RebuildCrossRef() {
m_ObjectInfo.clear();
m_SortedOffset.clear();
- m_pTrailer.reset();
+ m_Trailers.clear();
+ m_TrailerPos = CPDF_Parser::kInvalidPos;
ParserState state = ParserState::kDefault;
int32_t inside_index = 0;
@@ -729,7 +732,8 @@ bool CPDF_Parser::RebuildCrossRef() {
CPDF_Object* pRoot = pDict->GetObjectFor("Root");
if (pRoot && pRoot->GetDict() &&
pRoot->GetDict()->GetObjectFor("Pages")) {
- m_pTrailer = ToDictionary(pDict->Clone());
+ m_Trailers.push_back(ToDictionary(pDict->Clone()));
+ m_TrailerPos = m_Trailers.size() - 1;
}
}
}
@@ -785,7 +789,7 @@ bool CPDF_Parser::RebuildCrossRef() {
CPDF_Stream* pStream = pObj->AsStream();
if (CPDF_Dictionary* pTrailer =
pStream ? pStream->GetDict() : pObj->AsDictionary()) {
- if (m_pTrailer) {
+ if (GetTrailer()) {
CPDF_Object* pRoot = pTrailer->GetObjectFor("Root");
CPDF_Reference* pRef = ToReference(pRoot);
if (!pRoot ||
@@ -799,19 +803,19 @@ bool CPDF_Parser::RebuildCrossRef() {
uint32_t dwObjNum =
pElement ? pElement->GetObjNum() : 0;
if (dwObjNum) {
- m_pTrailer->SetNewFor<CPDF_Reference>(
+ GetTrailer()->SetNewFor<CPDF_Reference>(
key, m_pDocument.Get(), dwObjNum);
} else {
- m_pTrailer->SetFor(key, pElement->Clone());
+ GetTrailer()->SetFor(key, pElement->Clone());
}
}
}
} else {
- if (pObj->IsStream()) {
- m_pTrailer = ToDictionary(pTrailer->Clone());
- } else {
- m_pTrailer = ToDictionary(std::move(pObj));
- }
+ if (pObj->IsStream())
+ m_Trailers.push_back(ToDictionary(pTrailer->Clone()));
+ else
+ m_Trailers.push_back(ToDictionary(std::move(pObj)));
+ m_TrailerPos = m_Trailers.size() - 1;
FX_FILESIZE dwSavePos = m_pSyntax->GetPos();
CFX_ByteString strWord = m_pSyntax->GetKeyword();
@@ -915,7 +919,7 @@ bool CPDF_Parser::RebuildCrossRef() {
last_trailer = m_pSyntax->m_FileLen;
m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset);
- return m_pTrailer && !m_ObjectInfo.empty();
+ return GetTrailer() && !m_ObjectInfo.empty();
}
bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
@@ -951,7 +955,8 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
std::unique_ptr<CPDF_Dictionary> pNewTrailer = ToDictionary(pDict->Clone());
if (bMainXRef) {
- m_pTrailer = std::move(pNewTrailer);
+ m_Trailers.push_back(std::move(pNewTrailer));
+ m_TrailerPos = m_Trailers.size() - 1;
ShrinkObjectMap(size);
for (auto& it : m_ObjectInfo)
it.second.type = 0;
@@ -1060,10 +1065,10 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
}
CPDF_Array* CPDF_Parser::GetIDArray() {
- if (!m_pTrailer)
+ if (!GetTrailer())
return nullptr;
- CPDF_Object* pID = m_pTrailer->GetObjectFor("ID");
+ CPDF_Object* pID = GetTrailer()->GetObjectFor("ID");
if (!pID)
return nullptr;
@@ -1074,19 +1079,19 @@ CPDF_Array* CPDF_Parser::GetIDArray() {
std::unique_ptr<CPDF_Object> pNewObj =
ParseIndirectObject(nullptr, pRef->GetRefObjNum());
pID = pNewObj.get();
- m_pTrailer->SetFor("ID", std::move(pNewObj));
+ GetTrailer()->SetFor("ID", std::move(pNewObj));
return ToArray(pID);
}
uint32_t CPDF_Parser::GetRootObjNum() {
CPDF_Reference* pRef =
- ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Root") : nullptr);
+ ToReference(GetTrailer() ? GetTrailer()->GetObjectFor("Root") : nullptr);
return pRef ? pRef->GetRefObjNum() : 0;
}
uint32_t CPDF_Parser::GetInfoObjNum() {
CPDF_Reference* pRef =
- ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Info") : nullptr);
+ ToReference(GetTrailer() ? GetTrailer()->GetObjectFor("Info") : nullptr);
if (pRef)
return pRef->GetRefObjNum();
@@ -1488,11 +1493,13 @@ CPDF_Parser::Error CPDF_Parser::StartLinearizedParse(
}
if (bLoadV4) {
- m_pTrailer = LoadTrailerV4();
- if (!m_pTrailer)
+ std::unique_ptr<CPDF_Dictionary> trailer = LoadTrailerV4();
+ if (!trailer)
return SUCCESS;
- int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size");
+ m_Trailers.push_back(std::move(trailer));
+ m_TrailerPos = m_Trailers.size() - 1;
+ int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size");
if (xrefsize > 0)
ShrinkObjectMap(xrefsize);
}
@@ -1559,8 +1566,6 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) {
CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() {
uint32_t dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum;
m_pSyntax->m_MetadataObjnum = 0;
- if (m_pTrailer)
- m_Trailers.push_back(std::move(m_pTrailer));
m_pSyntax->SetPos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset);
uint8_t ch = 0;
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 8f55ddb325..efe10555f7 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -7,6 +7,7 @@
#ifndef CORE_FPDFAPI_PARSER_CPDF_PARSER_H_
#define CORE_FPDFAPI_PARSER_CPDF_PARSER_H_
+#include <limits>
#include <map>
#include <memory>
#include <set>
@@ -41,6 +42,8 @@ class CPDF_Parser {
// are higher, but this may be large enough in practice.
static const uint32_t kMaxObjectNumber = 1048576;
+ static const size_t kInvalidPos = std::numeric_limits<size_t>::max();
+
CPDF_Parser();
~CPDF_Parser();
@@ -51,7 +54,10 @@ class CPDF_Parser {
void SetPassword(const char* password) { m_Password = password; }
CFX_ByteString GetPassword() { return m_Password; }
- CPDF_Dictionary* GetTrailer() const { return m_pTrailer.get(); }
+ CPDF_Dictionary* GetTrailer() const {
+ return m_TrailerPos == kInvalidPos ? nullptr
+ : m_Trailers[m_TrailerPos].get();
+ }
FX_FILESIZE GetLastXRefOffset() const { return m_LastXRefOffset; }
uint32_t GetPermissions() const;
@@ -161,8 +167,8 @@ class CPDF_Parser {
std::unique_ptr<CPDF_SecurityHandler> m_pSecurityHandler;
CFX_ByteString m_Password;
std::set<FX_FILESIZE> m_SortedOffset;
- std::unique_ptr<CPDF_Dictionary> m_pTrailer;
std::vector<std::unique_ptr<CPDF_Dictionary>> m_Trailers;
+ size_t m_TrailerPos;
std::unique_ptr<CPDF_LinearizedHeader> m_pLinearized;
uint32_t m_dwXrefStartObjNum;