summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/thread/qfuture/tst_qfuture.cpp')
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 603d2eb21a..e109009d8a 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -228,6 +228,8 @@ private slots:
void createReadyFutures();
void continuationsDontLeak();
+ void cancelAfterFinishWithContinuations();
+
private:
using size_type = std::vector<int>::size_type;
@@ -3104,6 +3106,15 @@ void tst_QFuture::cancelContinuations()
QVERIFY(watcher2.isFinished());
QVERIFY(watcher2.isCanceled());
}
+
+ // Cancel continuations with context (QTBUG-108790)
+ {
+ // This test should pass with ASan
+ auto future = QtConcurrent::run([] {});
+ future.then(this, [] {});
+ future.waitForFinished();
+ future.cancel();
+ }
}
void tst_QFuture::continuationsWithContext()
@@ -4102,5 +4113,30 @@ void tst_QFuture::continuationsDontLeak()
QCOMPARE(InstanceCounter::count, 0);
}
+// This test checks that we do not get use-after-free
+void tst_QFuture::cancelAfterFinishWithContinuations()
+{
+ QFuture<void> future;
+ bool continuationIsRun = false;
+ bool cancelCalled = false;
+ {
+ QPromise<void> promise;
+ future = promise.future();
+
+ future.then([&continuationIsRun]() {
+ continuationIsRun = true;
+ }).onCanceled([&cancelCalled]() {
+ cancelCalled = true;
+ });
+
+ promise.start();
+ promise.finish();
+ }
+
+ QVERIFY(continuationIsRun);
+ future.cancel();
+ QVERIFY(!cancelCalled);
+}
+
QTEST_MAIN(tst_QFuture)
#include "tst_qfuture.moc"