diff options
author | Albert Astals Cid <aacid@kde.org> | 2024-04-22 10:17:03 +0200 |
---|---|---|
committer | Albert Astals Cid <aacid@kde.org> | 2024-04-22 12:23:16 +0000 |
commit | 06e0b89c2f64580eaac5e09a729b52668b09c106 (patch) | |
tree | 5efc568e0f6b4d8f74d7e6422e4c48d365e2f0af | |
parent | fd98a72b6a72bb6e395ef70ae2527477496db6f5 (diff) |
Fix crash in broken files
oss-fuzz/57874
-rw-r--r-- | poppler/Object.h | 18 | ||||
-rw-r--r-- | poppler/XRef.cc | 12 | ||||
-rw-r--r-- | poppler/XRef.h | 4 |
3 files changed, 31 insertions, 3 deletions
diff --git a/poppler/Object.h b/poppler/Object.h index 02209d8e..e70a9749 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -15,7 +15,7 @@ // // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org> // Copyright (C) 2008 Kees Cook <kees@outflux.net> -// Copyright (C) 2008, 2010, 2017-2021, 2023 Albert Astals Cid <aacid@kde.org> +// Copyright (C) 2008, 2010, 2017-2021, 2023, 2024 Albert Astals Cid <aacid@kde.org> // Copyright (C) 2009 Jakub Wilk <jwilk@jwilk.net> // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it> // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de> @@ -132,10 +132,26 @@ struct RefRecursionChecker return alreadySeenRefs.insert(ref.num).second; } + void remove(Ref ref) { alreadySeenRefs.erase(ref.num); } + private: std::set<int> alreadySeenRefs; }; +struct RefRecursionCheckerRemover +{ + // Removes ref from c when this object is removed + RefRecursionCheckerRemover(RefRecursionChecker &c, Ref r) : checker(c), ref(r) { } + ~RefRecursionCheckerRemover() { checker.remove(ref); } + + RefRecursionCheckerRemover(const RefRecursionCheckerRemover &) = delete; + RefRecursionCheckerRemover &operator=(const RefRecursionCheckerRemover &) = delete; + +private: + RefRecursionChecker &checker; + Ref ref; +}; + namespace std { template<> diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 903b3283..e97a00cc 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -15,7 +15,7 @@ // // Copyright (C) 2005 Dan Sheridan <dan.sheridan@postman.org.uk> // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net> -// Copyright (C) 2006, 2008, 2010, 2012-2014, 2016-2023 Albert Astals Cid <aacid@kde.org> +// Copyright (C) 2006, 2008, 2010, 2012-2014, 2016-2024 Albert Astals Cid <aacid@kde.org> // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org> // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org> // Copyright (C) 2009, 2010 Ilya Gorenbein <igorenbein@finjan.com> @@ -1187,6 +1187,16 @@ Object XRef::fetch(int num, int gen, int recursion, Goffset *endPos) Object obj1, obj2, obj3; xrefLocker(); + + const Ref ref = { num, gen }; + + if (!refsBeingFetched.insert(ref)) { + return Object(objNull); + } + + // Will remove ref from refsBeingFetched once it's destroyed, i.e. the function returns + RefRecursionCheckerRemover remover(refsBeingFetched, ref); + // check for bogus ref - this can happen in corrupted PDF files if (num < 0 || num >= size) { goto err; diff --git a/poppler/XRef.h b/poppler/XRef.h index 8c401f55..739b87bb 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -14,7 +14,7 @@ // under GPL version 2 or later // // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net> -// Copyright (C) 2006, 2008, 2010-2013, 2017-2022 Albert Astals Cid <aacid@kde.org> +// Copyright (C) 2006, 2008, 2010-2013, 2017-2022, 2024 Albert Astals Cid <aacid@kde.org> // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org> // Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org> // Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com> @@ -269,6 +269,8 @@ private: mutable std::recursive_mutex mutex; std::function<void()> xrefReconstructedCb; + RefRecursionChecker refsBeingFetched; + int reserve(int newSize); int resize(int newSize); bool readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::vector<int> *xrefStreamObjsNum); |