From c0a47773d6dadeb8a39a6ced4ebbb1795e2e411f Mon Sep 17 00:00:00 2001 From: art-snake Date: Wed, 9 Nov 2016 15:20:59 -0800 Subject: Fix receiving page, if it have not obj num. In some PDF's the page may not have the obj num. For example: testing\corpus\fx\other\jetman_std.pdf in pdfium repository. And CPDF_Document::GetPage failed on second call for this page. Restart the traversing of pages, to fix this Also added test. Review-Url: https://codereview.chromium.org/2491583002 --- core/fpdfapi/parser/cpdf_document.cpp | 11 ++++++++- core/fpdfapi/parser/cpdf_document_unittest.cpp | 33 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp index 1c73ce1015..6788394118 100644 --- a/core/fpdfapi/parser/cpdf_document.cpp +++ b/core/fpdfapi/parser/cpdf_document.cpp @@ -492,9 +492,18 @@ CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { if (!pPages) return nullptr; + if (iPage - m_iNextPageToTraverse + 1 <= 0) { + // This can happen when the page does not have an object number. On repeated + // calls to this function for the same page index, this condition causes + // TraversePDFPages() to incorrectly return nullptr. + // Example "testing/corpus/fx/other/jetman_std.pdf" + // We should restart traversing in this case. + // TODO(art-snake): optimize this. + ResetTraversal(); + } + int nPagesToGo = iPage - m_iNextPageToTraverse + 1; if (m_pTreeTraversal.empty()) m_pTreeTraversal.push_back(std::make_pair(pPages, 0)); - int nPagesToGo = iPage - m_iNextPageToTraverse + 1; CPDF_Dictionary* pPage = TraversePDFPages(iPage, &nPagesToGo, 0); m_iNextPageToTraverse = iPage + 1; return pPage; diff --git a/core/fpdfapi/parser/cpdf_document_unittest.cpp b/core/fpdfapi/parser/cpdf_document_unittest.cpp index 7b5ab43b5c..f27e7403f6 100644 --- a/core/fpdfapi/parser/cpdf_document_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_document_unittest.cpp @@ -76,6 +76,27 @@ class CPDF_TestDocumentForPages : public CPDF_Document { std::unique_ptr m_pOwnedRootDict; }; +class CPDF_TestDocumentWithPageWithoutPageNum : public CPDF_Document { + public: + CPDF_TestDocumentWithPageWithoutPageNum() : CPDF_Document(nullptr) { + // Set up test + CPDF_Array* allPages = new CPDF_Array(); + allPages->AddReference(this, AddIndirectObject(CreateNumberedPage(0))); + allPages->AddReference(this, AddIndirectObject(CreateNumberedPage(1))); + // Page without pageNum. + allPages->Add(CreateNumberedPage(2)); + CPDF_Dictionary* pagesDict = CreatePageTreeNode(allPages, this, 3); + + m_pOwnedRootDict.reset(new CPDF_Dictionary()); + m_pOwnedRootDict->SetReferenceFor("Pages", this, pagesDict->GetObjNum()); + m_pRootDict = m_pOwnedRootDict.get(); + m_PageList.SetSize(3); + } + + private: + std::unique_ptr m_pOwnedRootDict; +}; + class TestLinearized : public CPDF_LinearizedHeader { public: explicit TestLinearized(CPDF_Dictionary* dict) @@ -105,6 +126,18 @@ TEST_F(cpdf_document_test, GetPages) { EXPECT_FALSE(page); } +TEST_F(cpdf_document_test, GetPageWithoutObjNumTwice) { + std::unique_ptr document = + pdfium::MakeUnique(); + const CPDF_Dictionary* page = document->GetPage(2); + ASSERT_TRUE(page); + // This is page without obj num. + ASSERT_EQ(0ul, page->GetObjNum()); + const CPDF_Dictionary* second_call_page = document->GetPage(2); + EXPECT_TRUE(second_call_page); + EXPECT_EQ(page, second_call_page); +} + TEST_F(cpdf_document_test, GetPagesReverseOrder) { std::unique_ptr document = pdfium::MakeUnique(); -- cgit v1.2.3