diff options
author | Albert Astals Cid <aacid@kde.org> | 2023-09-20 22:20:13 +0200 |
---|---|---|
committer | Albert Astals Cid <aacid@kde.org> | 2023-09-20 22:20:13 +0200 |
commit | 8ba682b1a5d53efe975849a260e78715da74263c (patch) | |
tree | 23cbbdcf7e26058a7f3abd2db71a2b8e7f6ff3d0 | |
parent | 77573e1a706f861ca4677ea36dbdcc0a9fb50a99 (diff) |
Introduce RefRecursionChecker
-rw-r--r-- | poppler/Annot.cc | 17 | ||||
-rw-r--r-- | poppler/FontInfo.cc | 15 | ||||
-rw-r--r-- | poppler/FontInfo.h | 2 | ||||
-rw-r--r-- | poppler/Object.h | 22 | ||||
-rw-r--r-- | poppler/PageLabelInfo.cc | 14 | ||||
-rw-r--r-- | poppler/PageLabelInfo.h | 2 |
6 files changed, 37 insertions, 35 deletions
diff --git a/poppler/Annot.cc b/poppler/Annot.cc index aebcffcd..d62ba890 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -5314,19 +5314,8 @@ bool AnnotAppearanceBuilder::drawFormFieldChoice(const FormFieldChoice *fieldCho return true; } -static bool insertIfNotAlreadyPresent(Ref r, std::set<int> *alreadySeenDicts) -{ - if (r == Ref::INVALID()) { - return true; - } - - // std::pair<iterator,bool> - const auto insertResult = alreadySeenDicts->insert(r.num); - return insertResult.second; -} - // Should we also merge Arrays? -static void recursiveMergeDicts(Dict *primary, const Dict *secondary, std::set<int> *alreadySeenDicts) +static void recursiveMergeDicts(Dict *primary, const Dict *secondary, RefRecursionChecker *alreadySeenDicts) { for (int i = 0; i < secondary->getLength(); ++i) { const char *key = secondary->getKey(i); @@ -5339,7 +5328,7 @@ static void recursiveMergeDicts(Dict *primary, const Dict *secondary, std::set<i Ref secondaryRef; Object secondaryObj = secondary->lookup(key, &secondaryRef); if (secondaryObj.isDict()) { - if (!insertIfNotAlreadyPresent(primaryRef, alreadySeenDicts) || !insertIfNotAlreadyPresent(secondaryRef, alreadySeenDicts)) { + if (!alreadySeenDicts->insert(primaryRef) || !alreadySeenDicts->insert(secondaryRef)) { // bad PDF return; } @@ -5352,7 +5341,7 @@ static void recursiveMergeDicts(Dict *primary, const Dict *secondary, std::set<i static void recursiveMergeDicts(Dict *primary, const Dict *secondary) { - std::set<int> alreadySeenDicts; + RefRecursionChecker alreadySeenDicts; recursiveMergeDicts(primary, secondary, &alreadySeenDicts); } diff --git a/poppler/FontInfo.cc b/poppler/FontInfo.cc index 0be38923..551b98a1 100644 --- a/poppler/FontInfo.cc +++ b/poppler/FontInfo.cc @@ -134,21 +134,16 @@ void FontInfoScanner::scanFonts(XRef *xrefA, Dict *resDict, std::vector<FontInfo for (int i = 0; i < objDict.dictGetLength(); ++i) { Ref obj2Ref; const Object obj2 = objDict.getDict()->getVal(i, &obj2Ref); - if (obj2Ref != Ref::INVALID()) { - // check for an already-seen object - if (!visitedObjects.insert(obj2Ref.num).second) { - continue; - } + // check for an already-seen object + if (!visitedObjects.insert(obj2Ref)) { + continue; } if (obj2.isStream()) { Ref resourcesRef; const Object resObj = obj2.streamGetDict()->lookup("Resources", &resourcesRef); - - if (resourcesRef != Ref::INVALID()) { - if (!visitedObjects.insert(resourcesRef.num).second) { - continue; - } + if (!visitedObjects.insert(resourcesRef)) { + continue; } if (resObj.isDict() && resObj.getDict() != resDict) { diff --git a/poppler/FontInfo.h b/poppler/FontInfo.h index d13ae978..24903cdb 100644 --- a/poppler/FontInfo.h +++ b/poppler/FontInfo.h @@ -101,7 +101,7 @@ private: PDFDoc *doc; int currentPage; std::unordered_set<int> fonts; - std::unordered_set<int> visitedObjects; + RefRecursionChecker visitedObjects; void scanFonts(XRef *xrefA, Dict *resDict, std::vector<FontInfo *> *fontsList); }; diff --git a/poppler/Object.h b/poppler/Object.h index d0975100..10fffc04 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -113,6 +113,28 @@ inline bool operator<(const Ref lhs, const Ref rhs) noexcept return lhs.gen < rhs.gen; } +struct RefRecursionChecker +{ + RefRecursionChecker() { } + + RefRecursionChecker(const RefRecursionChecker &) = delete; + RefRecursionChecker &operator=(const RefRecursionChecker &) = delete; + + bool insert(Ref ref) + { + if (ref == Ref::INVALID()) { + return true; + } + + // insert returns std::pair<iterator,bool> + // where the bool is whether the insert succeeded + return alreadySeenRefs.insert(ref.num).second; + } + +private: + std::set<int> alreadySeenRefs; +}; + namespace std { template<> diff --git a/poppler/PageLabelInfo.cc b/poppler/PageLabelInfo.cc index 40a6e7fc..9b67b455 100644 --- a/poppler/PageLabelInfo.cc +++ b/poppler/PageLabelInfo.cc @@ -60,7 +60,7 @@ PageLabelInfo::Interval::Interval(Object *dict, int baseA) PageLabelInfo::PageLabelInfo(Object *tree, int numPages) { - std::set<int> alreadyParsedRefs; + RefRecursionChecker alreadyParsedRefs; parse(tree, alreadyParsedRefs); if (intervals.empty()) { @@ -74,7 +74,7 @@ PageLabelInfo::PageLabelInfo(Object *tree, int numPages) curr->length = std::max(0, numPages - curr->base); } -void PageLabelInfo::parse(const Object *tree, std::set<int> &alreadyParsedRefs) +void PageLabelInfo::parse(const Object *tree, RefRecursionChecker &alreadyParsedRefs) { // leaf node Object nums = tree->dictLookup("Nums"); @@ -103,13 +103,9 @@ void PageLabelInfo::parse(const Object *tree, std::set<int> &alreadyParsedRefs) for (int i = 0; i < kidsArray->getLength(); ++i) { Ref ref; const Object kid = kidsArray->get(i, &ref); - if (ref != Ref::INVALID()) { - const int numObj = ref.num; - if (alreadyParsedRefs.find(numObj) != alreadyParsedRefs.end()) { - error(errSyntaxError, -1, "loop in PageLabelInfo (numObj: {0:d})", numObj); - continue; - } - alreadyParsedRefs.insert(numObj); + if (!alreadyParsedRefs.insert(ref)) { + error(errSyntaxError, -1, "loop in PageLabelInfo (ref.num: {0:d})", ref.num); + continue; } if (kid.isDict()) { parse(&kid, alreadyParsedRefs); diff --git a/poppler/PageLabelInfo.h b/poppler/PageLabelInfo.h index bec70d32..2cfec29a 100644 --- a/poppler/PageLabelInfo.h +++ b/poppler/PageLabelInfo.h @@ -37,7 +37,7 @@ public: bool indexToLabel(int index, GooString *label) const; private: - void parse(const Object *tree, std::set<int> &parsedRefs); + void parse(const Object *tree, RefRecursionChecker &parsedRefs); private: struct Interval |