summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread/qfuturesynchronizer
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-06-21 10:38:00 +0200
committerMarc Mutz <marc.mutz@qt.io>2023-06-21 14:20:42 +0000
commite8dcbaaaf61ee2164db61e70a5d61d7a5b849371 (patch)
treed4d56a2fb6cc1d01b733242953cfcbf12dfcf54d /tests/auto/corelib/thread/qfuturesynchronizer
parent77f7c3a45d83ed14dbe92ed7ae2f8ccc95d2eed1 (diff)
QFutureSynchronizer: fix aliasing problem in setFuture()
When setFuture() was handed an element of m_futures, it would hold the reference to past the clear(), which invalidates said reference. Fix by taking the future by value instead of by cref. While append() is not affected, as QList::append() already guards against aliasing, do the same change there, both for consistency as well as to optimize the common case of passing rvalues. It also means we can use the rvalue overload of QList::append(), skipping the alias analysis in the lvalue QList::append(). [ChangeLog][QtConcurrent][QFutureSynchronizer] Fixed a crash in setFuture() if the argument was already a member of QFutureSynchronizer::futures(). Pick-to: 6.6 6.5 6.2 Change-Id: Ic0b212b9f265a746df9a6beb6272a5415d131442 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'tests/auto/corelib/thread/qfuturesynchronizer')
-rw-r--r--tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp23
1 files changed, 23 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp
index fe84ec1ae4..b2efd6473b 100644
--- a/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp
+++ b/tests/auto/corelib/thread/qfuturesynchronizer/tst_qfuturesynchronizer.cpp
@@ -13,6 +13,7 @@ class tst_QFutureSynchronizer : public QObject
private Q_SLOTS:
void construction();
+ void setFutureAliasingExistingMember();
void addFuture();
void cancelOnWait();
void clearFutures();
@@ -33,6 +34,28 @@ void tst_QFutureSynchronizer::construction()
QCOMPARE(synchronizerWithFuture.futures().size(), 1);
}
+void tst_QFutureSynchronizer::setFutureAliasingExistingMember()
+{
+ //
+ // GIVEN: a QFutureSynchronizer with one QFuture:
+ //
+ QFutureSynchronizer synchronizer(QtFuture::makeReadyValueFuture(42));
+
+ //
+ // WHEN: calling setFuture() with an alias of the QFuture already in `synchronizer`:
+ //
+ for (int i = 0; i < 2; ++i) {
+ const auto &f = synchronizer.futures().constFirst();
+ synchronizer.setFuture(f);
+ }
+
+ //
+ // THEN: it didn't crash
+ //
+ QCOMPARE(synchronizer.futures().size(), 1);
+ QCOMPARE(synchronizer.futures().constFirst().result(), 42);
+}
+
void tst_QFutureSynchronizer::addFuture()
{
QFutureSynchronizer<void> synchronizer;