aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2018-06-19 16:04:24 +0200
committerMitch Curtis <mitch.curtis@qt.io>2018-06-25 08:08:04 +0000
commit49c244e3c5a9138e6785515ebb64334705236ed4 (patch)
treed6012c5da4a4842469ad7611662b326534fb9954 /src
parent9999591e69a0908cd3fbe14646fb98881e32061b (diff)
QQuickPathViewPrivate: fix heap-use-after-free
The TabBar auto tests in Qt Quick Controls 2 repeats the following process very quickly for several data rows: 1. Creates a TabBar (PathView, when using the Universal style) 2. Moves items in its QQmlObjectModel 3. Deletes the TabBar When run with ASAN, this test would fail, because the TabButtons (which are child items of the PathView) would try to access a deleted QQuickItemChangeListener upon their destruction. The underlying issue is that QQuickPathView::modelUpdated() is called, and before a refill() can happen, the view is deleted. QQuickPathView::refill() was the only execution path that was releasing the cached items (QQuickPathViewPrivate::itemCache), and since part of releasing an item involves removing the QQuickPathView as a change listener from the item, the item would access the deleted view (listener) when the item was being destroyed. This patch fixes the issue by also releasing cached items in QQuickPathViewPrivate::clear(), which is always called by the destructor. Task-number: QTBUG-68964 Change-Id: Ic5bf0943be79948c86bf7c07ef13ecd1a7b971ba Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/qquickpathview.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 74c8eaa169..879db6284e 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -240,9 +240,13 @@ void QQuickPathViewPrivate::clear()
releaseItem(currentItem);
currentItem = nullptr;
}
+
for (QQuickItem *p : qAsConst(items))
releaseItem(p);
+ for (QQuickItem *p : qAsConst(itemCache))
+ releaseItem(p);
+
if (requestedIndex >= 0) {
if (model)
model->cancel(requestedIndex);
@@ -250,6 +254,7 @@ void QQuickPathViewPrivate::clear()
}
items.clear();
+ itemCache.clear();
tl.clear();
}