diff options
-rw-r--r-- | core/fpdfapi/parser/cpdf_data_avail.cpp | 369 |
1 files changed, 189 insertions, 180 deletions
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp index 64eaf2a43b..40134a021a 100644 --- a/core/fpdfapi/parser/cpdf_data_avail.cpp +++ b/core/fpdfapi/parser/cpdf_data_avail.cpp @@ -135,7 +135,8 @@ bool CPDF_DataAvail::AreObjectsAvailable(std::vector<CPDF_Object*>& obj_array, CPDF_Array* pArray = pObj->AsArray(); for (size_t k = 0; k < pArray->GetCount(); ++k) new_obj_array.push_back(pArray->GetObjectAt(k)); - } break; + break; + } case CPDF_Object::STREAM: pObj = pObj->GetDict(); case CPDF_Object::DICTIONARY: { @@ -147,7 +148,8 @@ bool CPDF_DataAvail::AreObjectsAvailable(std::vector<CPDF_Object*>& obj_array, if (it.first != "Parent") new_obj_array.push_back(it.second.get()); } - } break; + break; + } case CPDF_Object::REFERENCE: { CPDF_Reference* pRef = pObj->AsReference(); uint32_t dwNum = pRef->GetRefObjNum(); @@ -167,7 +169,8 @@ bool CPDF_DataAvail::AreObjectsAvailable(std::vector<CPDF_Object*>& obj_array, if (pReferred) new_obj_array.push_back(pReferred); } - } break; + break; + } } } @@ -522,7 +525,8 @@ bool CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) { if (CPDF_Reference* pRef = ToReference(pKidsArray->GetObjectAt(i))) m_PageObjList.push_back(pRef->GetRefObjNum()); } - } break; + break; + } default: m_docStatus = PDF_DATAAVAIL_ERROR; return false; @@ -560,22 +564,21 @@ bool CPDF_DataAvail::CheckHeader(DownloadHints* pHints) { ASSERT(m_dwFileLen >= 0); const uint32_t kReqSize = std::min(static_cast<uint32_t>(m_dwFileLen), 1024U); - if (m_pFileAvail->IsDataAvail(0, kReqSize)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, 0, kReqSize); - - if (IsLinearizedFile(buffer, kReqSize)) { - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; - } else { - if (m_docStatus == PDF_DATAAVAIL_ERROR) - return false; - m_docStatus = PDF_DATAAVAIL_END; - } - return true; + if (!m_pFileAvail->IsDataAvail(0, kReqSize)) { + pHints->AddSegment(0, kReqSize); + return false; } - pHints->AddSegment(0, kReqSize); - return false; + uint8_t buffer[1024]; + m_pFileRead->ReadBlock(buffer, 0, kReqSize); + if (IsLinearizedFile(buffer, kReqSize)) { + m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; + } else { + if (m_docStatus == PDF_DATAAVAIL_ERROR) + return false; + m_docStatus = PDF_DATAAVAIL_END; + } + return true; } bool CPDF_DataAvail::CheckFirstPage(DownloadHints* pHints) { @@ -746,43 +749,43 @@ bool CPDF_DataAvail::CheckEnd(DownloadHints* pHints) { uint32_t req_pos = (uint32_t)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0); uint32_t dwSize = (uint32_t)(m_dwFileLen - req_pos); - if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, req_pos, dwSize); + if (!m_pFileAvail->IsDataAvail(req_pos, dwSize)) { + pHints->AddSegment(req_pos, dwSize); + return false; + } - CFX_RetainPtr<IFX_MemoryStream> file = - IFX_MemoryStream::Create(buffer, (size_t)dwSize, false); - m_syntaxParser.InitParser(file, 0); - m_syntaxParser.RestorePos(dwSize - 1); + uint8_t buffer[1024]; + m_pFileRead->ReadBlock(buffer, req_pos, dwSize); - if (m_syntaxParser.SearchWord("startxref", true, false, dwSize)) { - m_syntaxParser.GetNextWord(nullptr); + CFX_RetainPtr<IFX_MemoryStream> file = + IFX_MemoryStream::Create(buffer, (size_t)dwSize, false); + m_syntaxParser.InitParser(file, 0); + m_syntaxParser.RestorePos(dwSize - 1); - bool bNumber; - CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(&bNumber); - if (!bNumber) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; - } + if (!m_syntaxParser.SearchWord("startxref", true, false, dwSize)) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return true; + } - m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str.c_str()); - if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } + m_syntaxParser.GetNextWord(nullptr); - m_dwLastXRefOffset = m_dwXRefOffset; - SetStartOffset(m_dwXRefOffset); - m_docStatus = PDF_DATAAVAIL_CROSSREF; - return true; - } + bool bNumber; + CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(&bNumber); + if (!bNumber) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + } + m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str.c_str()); + if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return true; } - pHints->AddSegment(req_pos, dwSize); - return false; + m_dwLastXRefOffset = m_dwXRefOffset; + SetStartOffset(m_dwXRefOffset); + m_docStatus = PDF_DATAAVAIL_CROSSREF; + return true; } int32_t CPDF_DataAvail::CheckCrossRefStream(DownloadHints* pHints, @@ -791,42 +794,43 @@ int32_t CPDF_DataAvail::CheckCrossRefStream(DownloadHints* pHints, uint32_t req_size = (uint32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { - int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); + if (!m_pFileAvail->IsDataAvail(m_Pos, req_size)) { + pHints->AddSegment(m_Pos, req_size); + return 0; + } - m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); + int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); + CFX_BinaryBuf buf(iSize); + uint8_t* pBuf = buf.GetBuffer(); - CFX_RetainPtr<IFX_MemoryStream> file = - IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); - m_parser.m_pSyntax->InitParser(file, 0); + m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); - bool bNumber; - CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber); - if (!bNumber) - return -1; + CFX_RetainPtr<IFX_MemoryStream> file = + IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); + m_parser.m_pSyntax->InitParser(file, 0); - uint32_t objNum = FXSYS_atoui(objnum.c_str()); - std::unique_ptr<CPDF_Object> pObj = - m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); + bool bNumber; + CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber); + if (!bNumber) + return -1; - if (!pObj) { - m_Pos += m_parser.m_pSyntax->SavePos(); - return 0; - } + uint32_t objNum = FXSYS_atoui(objnum.c_str()); + std::unique_ptr<CPDF_Object> pObj = + m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); - CPDF_Dictionary* pDict = pObj->GetDict(); - CPDF_Name* pName = ToName(pDict ? pDict->GetObjectFor("Type") : nullptr); - if (pName && pName->GetString() == "XRef") { - m_Pos += m_parser.m_pSyntax->SavePos(); - xref_offset = pObj->GetDict()->GetIntegerFor("Prev"); - return 1; - } - return -1; + if (!pObj) { + m_Pos += m_parser.m_pSyntax->SavePos(); + return 0; } - pHints->AddSegment(m_Pos, req_size); - return 0; + + CPDF_Dictionary* pDict = pObj->GetDict(); + CPDF_Name* pName = ToName(pDict ? pDict->GetObjectFor("Type") : nullptr); + if (pName && pName->GetString() == "XRef") { + m_Pos += m_parser.m_pSyntax->SavePos(); + xref_offset = pObj->GetDict()->GetIntegerFor("Prev"); + return 1; + } + return -1; } void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) { @@ -960,14 +964,13 @@ bool CPDF_DataAvail::CheckCrossRefItem(DownloadHints* pHints) { bool CPDF_DataAvail::CheckAllCrossRefStream(DownloadHints* pHints) { FX_FILESIZE xref_offset = 0; - int32_t nRet = CheckCrossRefStream(pHints, xref_offset); if (nRet == 1) { - if (!xref_offset) { - m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; - } else { + if (xref_offset) { m_dwCurrentXRefSteam = xref_offset; m_Pos = xref_offset; + } else { + m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; } return true; } @@ -986,26 +989,25 @@ bool CPDF_DataAvail::CheckCrossRef(DownloadHints* pHints) { return false; } - if (token == "xref") { - while (1) { - if (!GetNextToken(token)) { - iSize = - (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; - return false; - } - - if (token == "trailer") { - m_dwTrailerOffset = m_Pos; - m_docStatus = PDF_DATAAVAIL_TRAILER; - return true; - } - } - } else { + if (token != "xref") { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return true; } + + while (1) { + if (!GetNextToken(token)) { + iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + pHints->AddSegment(m_Pos, iSize); + m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; + return false; + } + + if (token == "trailer") { + m_dwTrailerOffset = m_Pos; + m_docStatus = PDF_DATAAVAIL_TRAILER; + return true; + } + } return false; } @@ -1033,62 +1035,65 @@ bool CPDF_DataAvail::CheckTrailerAppend(DownloadHints* pHints) { bool CPDF_DataAvail::CheckTrailer(DownloadHints* pHints) { int32_t iTrailerSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { - int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); - if (!pBuf) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; - } + if (!m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { + pHints->AddSegment(m_Pos, iTrailerSize); + return false; + } - if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) - return false; + int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); + CFX_BinaryBuf buf(iSize); + uint8_t* pBuf = buf.GetBuffer(); + if (!pBuf) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + } - CFX_RetainPtr<IFX_MemoryStream> file = - IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); - m_syntaxParser.InitParser(file, 0); + if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) + return false; - std::unique_ptr<CPDF_Object> pTrailer( - m_syntaxParser.GetObject(nullptr, 0, 0, true)); - if (!pTrailer) { - m_Pos += m_syntaxParser.SavePos(); - pHints->AddSegment(m_Pos, iTrailerSize); - return false; - } + CFX_RetainPtr<IFX_MemoryStream> file = + IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); + m_syntaxParser.InitParser(file, 0); + + std::unique_ptr<CPDF_Object> pTrailer( + m_syntaxParser.GetObject(nullptr, 0, 0, true)); + if (!pTrailer) { + m_Pos += m_syntaxParser.SavePos(); + pHints->AddSegment(m_Pos, iTrailerSize); + return false; + } - if (!pTrailer->IsDictionary()) - return false; + if (!pTrailer->IsDictionary()) + return false; - CPDF_Dictionary* pTrailerDict = pTrailer->GetDict(); - CPDF_Object* pEncrypt = pTrailerDict->GetObjectFor("Encrypt"); - if (ToReference(pEncrypt)) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } + CPDF_Dictionary* pTrailerDict = pTrailer->GetDict(); + CPDF_Object* pEncrypt = pTrailerDict->GetObjectFor("Encrypt"); + if (ToReference(pEncrypt)) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return true; + } - uint32_t xrefpos = GetDirectInteger(pTrailerDict, "Prev"); - if (xrefpos) { - m_dwPrevXRefOffset = GetDirectInteger(pTrailerDict, "XRefStm"); - if (m_dwPrevXRefOffset) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - m_dwPrevXRefOffset = xrefpos; - if (m_dwPrevXRefOffset >= m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - SetStartOffset(m_dwPrevXRefOffset); - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; - } - } - return true; - } + uint32_t xrefpos = GetDirectInteger(pTrailerDict, "Prev"); + if (!xrefpos) { m_dwPrevXRefOffset = 0; m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; return true; } - pHints->AddSegment(m_Pos, iTrailerSize); - return false; + + m_dwPrevXRefOffset = GetDirectInteger(pTrailerDict, "XRefStm"); + if (m_dwPrevXRefOffset) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return true; + } + + m_dwPrevXRefOffset = xrefpos; + if (m_dwPrevXRefOffset >= m_dwFileLen) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + } else { + SetStartOffset(m_dwPrevXRefOffset); + m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; + } + return true; } bool CPDF_DataAvail::CheckPage(uint32_t dwPage, DownloadHints* pHints) { @@ -1172,42 +1177,47 @@ bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, pPageNode->m_dwPageNo = dwPageNo; CPDF_Dictionary* pDict = pPage->GetDict(); - CFX_ByteString type = pDict->GetStringFor("Type"); - if (type == "Pages") { - pPageNode->m_type = PDF_PAGENODE_PAGES; - CPDF_Object* pKids = pDict->GetObjectFor("Kids"); - if (!pKids) { - m_docStatus = PDF_DATAAVAIL_PAGE; - return true; + const CFX_ByteString type = pDict->GetStringFor("Type"); + if (type == "Page") { + pPageNode->m_type = PDF_PAGENODE_PAGE; + return true; + } + + if (type != "Pages") { + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + } + + pPageNode->m_type = PDF_PAGENODE_PAGES; + CPDF_Object* pKids = pDict->GetObjectFor("Kids"); + if (!pKids) { + m_docStatus = PDF_DATAAVAIL_PAGE; + return true; + } + + switch (pKids->GetType()) { + case CPDF_Object::REFERENCE: { + CPDF_Reference* pKid = pKids->AsReference(); + auto pNode = pdfium::MakeUnique<PageNode>(); + pNode->m_dwPageNo = pKid->GetRefObjNum(); + pPageNode->m_ChildNodes.push_back(std::move(pNode)); + break; } + case CPDF_Object::ARRAY: { + CPDF_Array* pKidsArray = pKids->AsArray(); + for (size_t i = 0; i < pKidsArray->GetCount(); ++i) { + CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i)); + if (!pKid) + continue; - switch (pKids->GetType()) { - case CPDF_Object::REFERENCE: { - CPDF_Reference* pKid = pKids->AsReference(); auto pNode = pdfium::MakeUnique<PageNode>(); pNode->m_dwPageNo = pKid->GetRefObjNum(); pPageNode->m_ChildNodes.push_back(std::move(pNode)); - } break; - case CPDF_Object::ARRAY: { - CPDF_Array* pKidsArray = pKids->AsArray(); - for (size_t i = 0; i < pKidsArray->GetCount(); ++i) { - CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i)); - if (!pKid) - continue; - - auto pNode = pdfium::MakeUnique<PageNode>(); - pNode->m_dwPageNo = pKid->GetRefObjNum(); - pPageNode->m_ChildNodes.push_back(std::move(pNode)); - } - } break; - default: - break; + } + break; } - } else if (type == "Page") { - pPageNode->m_type = PDF_PAGENODE_PAGE; - } else { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; + default: + break; } return true; } @@ -1469,21 +1479,20 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( return GetPage(dwPage) ? DataAvailable : DataError; } - if (m_bMainXRefLoadedOK) { - if (m_bTotalLoadPageTree) { - if (!LoadPages(pHints)) - return DataNotAvailable; - } else { - if (!m_bCurPageDictLoadOK && !CheckPage(dwPage, pHints)) - return DataNotAvailable; - } - } else { + if (!m_bMainXRefLoadedOK) { if (!LoadAllFile(pHints)) return DataNotAvailable; m_pDocument->GetParser()->RebuildCrossRef(); ResetFirstCheck(dwPage); return DataAvailable; } + if (m_bTotalLoadPageTree) { + if (!LoadPages(pHints)) + return DataNotAvailable; + } else { + if (!m_bCurPageDictLoadOK && !CheckPage(dwPage, pHints)) + return DataNotAvailable; + } } else { if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK && !CheckPage(dwPage, pHints)) { |