From 83c5eaca106f4afed6cceb1b3f336d0146cb10d7 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Tue, 3 Jan 2017 14:33:20 -0500 Subject: Force stop of page tree traversal when max level reached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Commit-Queue: dsinclair Reviewed-by: Tom Sepez Reviewed-by: dsinclair --- core/fpdfapi/parser/cpdf_document.cpp | 10 +++++++--- core/fpdfapi/parser/cpdf_document.h | 1 + 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 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> 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; -- cgit v1.2.3