Check for cycles in CountNamesInternal().
Prevent infinite loops in name tree objects that reference themselves.
Bug: pdfium:1838
Change-Id: I4ec399f2b3b16d33b729a600e18627f75eec9477
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94311
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 58a2371..bfcc267 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -6,6 +6,7 @@
#include "core/fpdfdoc/cpdf_nametree.h"
+#include <set>
#include <utility>
#include <vector>
@@ -319,10 +320,16 @@
}
// Get the total number of key-value pairs in the tree with root |pNode|.
-size_t CountNamesInternal(const CPDF_Dictionary* pNode, int nLevel) {
+size_t CountNamesInternal(const CPDF_Dictionary* pNode,
+ int nLevel,
+ std::set<const CPDF_Dictionary*>& seen) {
if (nLevel > kNameTreeMaxRecursion)
return 0;
+ const bool inserted = seen.insert(pNode).second;
+ if (!inserted)
+ return 0;
+
const CPDF_Array* pNames = pNode->GetArrayFor("Names");
if (pNames)
return pNames->size() / 2;
@@ -337,7 +344,7 @@
if (!pKid)
continue;
- nCount += CountNamesInternal(pKid, nLevel + 1);
+ nCount += CountNamesInternal(pKid, nLevel + 1, seen);
}
return nCount;
}
@@ -434,7 +441,8 @@
}
size_t CPDF_NameTree::GetCount() const {
- return CountNamesInternal(m_pRoot.Get(), 0);
+ std::set<const CPDF_Dictionary*> seen;
+ return CountNamesInternal(m_pRoot.Get(), 0, seen);
}
bool CPDF_NameTree::AddValueAndName(RetainPtr<CPDF_Object> pObj,