From 7749995ad62decd7e554e53a4efcfb12cbcc8f93 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 13 Jul 2024 13:40:42 +1000 Subject: [PATCH] Fix use-after-free in QgsVectorLayerCache iterators We need to gracefully handle the situation where the cache is deleted before the iterator, as these iterators require the cache object --- src/core/qgscachedfeatureiterator.cpp | 4 ++-- src/core/qgscachedfeatureiterator.h | 6 ++++-- tests/src/python/test_qgsvectorlayercache.py | 6 ++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/core/qgscachedfeatureiterator.cpp b/src/core/qgscachedfeatureiterator.cpp index 6ff40850f048..a914464659b9 100644 --- a/src/core/qgscachedfeatureiterator.cpp +++ b/src/core/qgscachedfeatureiterator.cpp @@ -99,7 +99,7 @@ bool QgsCachedFeatureIterator::fetchFeature( QgsFeature &f ) { f.setValid( false ); - if ( mClosed ) + if ( mClosed || !mVectorLayerCache ) return false; while ( mFeatureIdIterator != mFeatureIds.constEnd() ) @@ -174,7 +174,7 @@ QgsCachedFeatureWriterIterator::QgsCachedFeatureWriterIterator( QgsVectorLayerCa bool QgsCachedFeatureWriterIterator::fetchFeature( QgsFeature &f ) { - if ( mClosed ) + if ( mClosed || !mVectorLayerCache ) { f.setValid( false ); return false; diff --git a/src/core/qgscachedfeatureiterator.h b/src/core/qgscachedfeatureiterator.h index b7c6e0bd1056..68ee3148e49a 100644 --- a/src/core/qgscachedfeatureiterator.h +++ b/src/core/qgscachedfeatureiterator.h @@ -20,6 +20,8 @@ #include "qgsfeature.h" #include "qgsfeatureiterator.h" #include "qgscoordinatetransform.h" +#include "qgsvectorlayercache.h" +#include class QgsVectorLayerCache; @@ -84,7 +86,7 @@ class CORE_EXPORT QgsCachedFeatureIterator : public QgsAbstractFeatureIterator #endif QList< QgsFeatureId > mFeatureIds; - QgsVectorLayerCache *mVectorLayerCache = nullptr; + QPointer< QgsVectorLayerCache > mVectorLayerCache = nullptr; QList< QgsFeatureId >::ConstIterator mFeatureIdIterator; QgsCoordinateTransform mTransform; QgsRectangle mFilterRect; @@ -140,7 +142,7 @@ class CORE_EXPORT QgsCachedFeatureWriterIterator : public QgsAbstractFeatureIter private: QgsFeatureIterator mFeatIt; - QgsVectorLayerCache *mVectorLayerCache = nullptr; + QPointer< QgsVectorLayerCache > mVectorLayerCache; QgsFeatureIds mFids; QgsCoordinateTransform mTransform; QgsRectangle mFilterRect; diff --git a/tests/src/python/test_qgsvectorlayercache.py b/tests/src/python/test_qgsvectorlayercache.py index 03cdb4494a44..7d10d322646b 100644 --- a/tests/src/python/test_qgsvectorlayercache.py +++ b/tests/src/python/test_qgsvectorlayercache.py @@ -97,6 +97,12 @@ def testAllFeatureIds(self): """ pass + def testOpenIteratorAfterSourceRemoval(self): + """ + Skip this test -- the iterators from the cache CANNOT be used after the cache is deleted + """ + pass + if __name__ == '__main__': unittest.main()