// Check circular bookmarks will not cause infinite loop. TEST_F(FPDFDocEmbedderTest, FindBookmarks_bug420) { // Open a file with circular bookmarks. EXPECT_TRUE(OpenDocument("bookmarks_circular.pdf")); // Try to find a title. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L"anything"); EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), title.get())); }
TEST_F(FPDFDocEmbedderTest, NoBookmarks) { // Open a file with no bookmarks. EXPECT_TRUE(OpenDocument("named_dests.pdf")); // The non-existent top-level bookmark has no title. unsigned short buf[128]; EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf))); // NULL argument cases. EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(nullptr, nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(nullptr, nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_Find(nullptr, nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetDest(nullptr, nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetDest(document(), nullptr)); EXPECT_EQ(nullptr, FPDFBookmark_GetAction(nullptr)); }
TEST_F(FPDFDocEmbedderTest, FindBookmarks) { // Open a file with two bookmarks. EXPECT_TRUE(OpenDocument("bookmarks.pdf")); // Find the first one, based on its known title. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L"A Good Beginning"); FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get()); EXPECT_TRUE(child); // Check that the string matches. unsigned short buf[128]; EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf))); EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16)); // Check that it is them same as the one returned by GetFirstChild. EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr)); // Try to find one using a non-existent title. std::unique_ptr<unsigned short, pdfium::FreeDeleter> bad_title = GetFPDFWideString(L"A BAD Beginning"); EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get())); }
TEST_F(PDFDocTest, FindBookmark) { { // No bookmark information. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L""); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); title = GetFPDFWideString(L"Preface"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); } { // Empty bookmark tree. m_pRootObj->SetNewFor<CPDF_Dictionary>("Outlines"); std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L""); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); title = GetFPDFWideString(L"Preface"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); } { // Check on a regular bookmark tree. auto bookmarks = CreateDictObjs(3); bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1"); bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs, bookmarks[2].num); bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2"); bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[2].obj->SetNewFor<CPDF_Reference>("Prev", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines"); bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2); bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs, bookmarks[2].num); m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs, bookmarks[0].num); // Title with no match. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L"Chapter 3"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); // Title with partial match only. title = GetFPDFWideString(L"Chapter"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); // Title with a match. title = GetFPDFWideString(L"Chapter 2"); EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get())); // Title match is case insensitive. title = GetFPDFWideString(L"cHaPter 2"); EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get())); } { // Circular bookmarks in depth. auto bookmarks = CreateDictObjs(3); bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1"); bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[1].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs, bookmarks[2].num); bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2"); bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[1].num); bookmarks[2].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines"); bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2); bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs, bookmarks[2].num); m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs, bookmarks[0].num); // Title with no match. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L"Chapter 3"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); // Title with a match. title = GetFPDFWideString(L"Chapter 2"); EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get())); } { // Circular bookmarks in breadth. auto bookmarks = CreateDictObjs(4); bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1"); bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs, bookmarks[2].num); bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2"); bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[2].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs, bookmarks[3].num); bookmarks[3].obj->SetNewFor<CPDF_String>("Title", L"Chapter 3"); bookmarks[3].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs, bookmarks[0].num); bookmarks[3].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines"); bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2); bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs, bookmarks[1].num); bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs, bookmarks[2].num); m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs, bookmarks[0].num); // Title with no match. std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = GetFPDFWideString(L"Chapter 8"); EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get())); // Title with a match. title = GetFPDFWideString(L"Chapter 3"); EXPECT_EQ(bookmarks[3].obj, FPDFBookmark_Find(m_pDoc.get(), title.get())); } }