summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pena <npm@chromium.org>2017-01-03 14:33:20 -0500
committerChromium commit bot <commit-bot@chromium.org>2017-01-03 19:50:39 +0000
commit83c5eaca106f4afed6cceb1b3f336d0146cb10d7 (patch)
tree2973a1ea01ee822806b3a2f30225ec678a0f98d6
parent05f541279ec01dfdc76ad6b8b142fa5f04cd544c (diff)
downloadpdfium-83c5eaca106f4afed6cceb1b3f336d0146cb10d7.tar.xz
Force stop of page tree traversal when max level reached
The previous implementation, FindPDFPage, was already doing this since the recursive call was always with return. Currently, we were trying to keep going even after reaching max level. The problem is that if the page tree is not a tree, we might loop forever. This could also be solved by keeping track of the dictionaries that have been visited, but this solution takes much less space. BUG=672172 Change-Id: Ia37aea58e92b6068de69f26736c612aa6a0ff4b3 Reviewed-on: https://pdfium-review.googlesource.com/2138 Commit-Queue: Nicolás Peña <npm@chromium.org> Commit-Queue: dsinclair <dsinclair@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org>
-rw-r--r--core/fpdfapi/parser/cpdf_document.cpp10
-rw-r--r--core/fpdfapi/parser/cpdf_document.h1
2 files changed, 8 insertions, 3 deletions
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 411091ced5..a728bf5795 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -343,6 +343,7 @@ CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser)
m_pRootDict(nullptr),
m_pInfoDict(nullptr),
m_iNextPageToTraverse(0),
+ m_bReachedMaxPageLevel(false),
m_bLinearized(false),
m_iFirstPageNo(0),
m_dwFirstPageObjNum(0),
@@ -399,7 +400,7 @@ void CPDF_Document::LoadPages() {
CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage,
int* nPagesToGo,
size_t level) {
- if (*nPagesToGo < 0)
+ if (*nPagesToGo < 0 || m_bReachedMaxPageLevel)
return nullptr;
CPDF_Dictionary* pPages = m_pTreeTraversal[level].first;
CPDF_Array* pKidList = pPages->GetArrayFor("Kids");
@@ -412,6 +413,7 @@ CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage,
if (level >= FX_MAX_PAGE_LEVEL) {
m_pTreeTraversal.pop_back();
+ m_bReachedMaxPageLevel = true;
return nullptr;
}
@@ -447,8 +449,9 @@ CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage,
// Check if child was completely processed, i.e. it popped itself out
if (m_pTreeTraversal.size() == level + 1)
m_pTreeTraversal[level].second++;
- // If child did not finish or if no pages to go, we are done
- if (m_pTreeTraversal.size() != level + 1 || *nPagesToGo == 0) {
+ // If child did not finish, no pages to go, or max level reached, end
+ if (m_pTreeTraversal.size() != level + 1 || *nPagesToGo == 0 ||
+ m_bReachedMaxPageLevel) {
page = pageKid;
break;
}
@@ -461,6 +464,7 @@ CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage,
void CPDF_Document::ResetTraversal() {
m_iNextPageToTraverse = 0;
+ m_bReachedMaxPageLevel = false;
m_pTreeTraversal.clear();
}
diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h
index 59154d3ab3..0da6577360 100644
--- a/core/fpdfapi/parser/cpdf_document.h
+++ b/core/fpdfapi/parser/cpdf_document.h
@@ -138,6 +138,7 @@ class CPDF_Document : public CPDF_IndirectObjectHolder {
std::vector<std::pair<CPDF_Dictionary*, size_t>> m_pTreeTraversal;
// Index of the next page that will be traversed from the page tree.
int m_iNextPageToTraverse;
+ bool m_bReachedMaxPageLevel;
bool m_bLinearized;
int m_iFirstPageNo;
uint32_t m_dwFirstPageObjNum;