diff options
author | Wei Li <weili@chromium.org> | 2016-03-03 11:28:06 -0800 |
---|---|---|
committer | Wei Li <weili@chromium.org> | 2016-03-03 11:28:06 -0800 |
commit | 0e2e5d7554af277cfb312294378c2cd862a349d5 (patch) | |
tree | 34cf0f04ef734f7bd08cdd91204e8dd249ffeb63 /fpdfsdk/src | |
parent | d8741afa1c3f31723ec62131d1bb8a78081cd1e4 (diff) | |
download | pdfium-0e2e5d7554af277cfb312294378c2cd862a349d5.tar.xz |
Fix infinite loop for bookmark search
BUG=pdfium:420
R=tsepez@chromium.org
Review URL: https://codereview.chromium.org/1757373002 .
Diffstat (limited to 'fpdfsdk/src')
-rw-r--r-- | fpdfsdk/src/fpdfdoc.cpp | 25 | ||||
-rw-r--r-- | fpdfsdk/src/fpdfdoc_embeddertest.cpp | 11 |
2 files changed, 29 insertions, 7 deletions
diff --git a/fpdfsdk/src/fpdfdoc.cpp b/fpdfsdk/src/fpdfdoc.cpp index 50f3e2c904..4b5da2ffc3 100644 --- a/fpdfsdk/src/fpdfdoc.cpp +++ b/fpdfsdk/src/fpdfdoc.cpp @@ -6,7 +6,10 @@ #include "public/fpdf_doc.h" +#include <set> + #include "fpdfsdk/include/fsdk_define.h" +#include "third_party/base/stl_util.h" namespace { @@ -14,17 +17,24 @@ int THISMODULE = 0; CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, CPDF_Bookmark bookmark, - const CFX_WideString& title) { + const CFX_WideString& title, + std::set<CPDF_Dictionary*>* visited) { + // Return if already checked to avoid circular calling. + if (pdfium::ContainsKey(*visited, bookmark.GetDict())) + return CPDF_Bookmark(); + visited->insert(bookmark.GetDict()); + if (bookmark.GetDict() && bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) { - // First check this item + // First check this item. return bookmark; } - // go into children items + + // Go into children items. CPDF_Bookmark child = tree.GetFirstChild(bookmark); - while (child.GetDict()) { - // check if this item - CPDF_Bookmark found = FindBookmark(tree, child, title); + while (child.GetDict() && !pdfium::ContainsKey(*visited, child.GetDict())) { + // Check this item and its children. + CPDF_Bookmark found = FindBookmark(tree, child, title, visited); if (found.GetDict()) return found; child = tree.GetNextSibling(child); @@ -101,7 +111,8 @@ DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, CPDF_BookmarkTree tree(pDoc); FX_STRSIZE len = CFX_WideString::WStringLength(title); CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len); - return FindBookmark(tree, CPDF_Bookmark(), encodedTitle).GetDict(); + std::set<CPDF_Dictionary*> visited; + return FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict(); } DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, diff --git a/fpdfsdk/src/fpdfdoc_embeddertest.cpp b/fpdfsdk/src/fpdfdoc_embeddertest.cpp index a789dade36..0ca6a48ca7 100644 --- a/fpdfsdk/src/fpdfdoc_embeddertest.cpp +++ b/fpdfsdk/src/fpdfdoc_embeddertest.cpp @@ -125,3 +125,14 @@ TEST_F(FPDFDocEmbeddertest, FindBookmarks) { GetFPDFWideString(L"A BAD Beginning"); EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get())); } + +// 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())); +} |