Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qt6-declarative for openSUSE:Factory 
checked in at 2026-11-05 18:28:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qt6-declarative (Old)
 and      /work/SRC/openSUSE:Factory/.qt6-declarative.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qt6-declarative"

Thu Nov  5 18:28:19 2026 rev:67 rq:1394772 version:6.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/qt6-declarative/qt6-declarative.changes  
2026-10-29 18:18:11.764283351 +0100
+++ 
/work/SRC/openSUSE:Factory/.qt6-declarative.new.3759290/qt6-declarative.changes 
    2026-11-05 18:28:19.637738158 +0100
@@ -1,0 +2,6 @@
+Tue Nov  3 19:38:57 UTC 2026 - Christophe Marin <[email protected]>
+
+- Add upstream change (boo#1287613, QTBUG-150769)
+  * 0001-QQuickItemView-don-t-leave-dangling-entries-in-unreq.patch
+
+-------------------------------------------------------------------

New:
----
  0001-QQuickItemView-don-t-leave-dangling-entries-in-unreq.patch

----------(New B)----------
  New:- Add upstream change (boo#1287613, QTBUG-150769)
  * 0001-QQuickItemView-don-t-leave-dangling-entries-in-unreq.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qt6-declarative.spec ++++++
--- /var/tmp/diff_new_pack.kCglTn/_old  2026-11-05 18:28:20.604778369 +0100
+++ /var/tmp/diff_new_pack.kCglTn/_new  2026-11-05 18:28:20.606778452 +0100
@@ -43,6 +43,8 @@
 Patch0:         0001-qmlimportscanner-Include-module-versions-again.patch
 # PATCH-FIX-UPSTREAM
 Patch1:         0001-Fix-teardown-hang-with-QuickPixmapReader.patch
+# PATCH-FIX-UPSTREAM
+Patch2:         0001-QQuickItemView-don-t-leave-dangling-entries-in-unreq.patch
 BuildRequires:  memory-constraints
 BuildRequires:  pkgconfig
 BuildRequires:  python3-base

++++++ 0001-QQuickItemView-don-t-leave-dangling-entries-in-unreq.patch ++++++
>From d6f5246394d8fee96a1fc91cf2fb79c21173f658 Mon Sep 17 00:00:00 2001
From: Vladimir Belyavsky <[email protected]>
Date: Thu, 24 Sep 2026 12:06:00 +0300
Subject: [PATCH] QQuickItemView: don't leave dangling entries in
 unrequestedItems

b0b1c1de68a1cc15f6304bb85d0c57a49499f866 ("QQuickItemView: register
Destroyed listener when storing an item") added a loop at the end of
~QQuickItemView that walks unrequestedItems and dereferences the stored
raw pointers to remove our Destroyed listener from each item. This is
only safe while every entry points at a live item. The listener is what
keeps that true: when the item is deleted, it calls itemDestroyed(),
which removes the entry from the hash.

releaseItem() can break that invariant. An item stored with isClearing
== false gets both the entry and the listener. Releasing it again while
the view is being cleared (isClearing == true) removes the listener but
leaves the entry, so itemDestroyed() never runs for it and the entry is
never dropped. Once the item is freed, the destructor loop dereferences
a dangling pointer, causing a use-after-free crash.

For instance, deactivating a Loader that hosts a ListView invalidates
the delegate contexts synchronously while the deferred delete is still
pending: the delegate ends up in unrequestedItems, and its
currentItem/visibleItems twin is released again during clear(true).

Remove the entry from unrequestedItems whenever the listener is removed,
keeping the two in sync so the destructor never walks a freed pointer.

Fixes: QTBUG-150769
Change-Id: Ide32473f3fea373749197c969eaff6d13869c32d
Reviewed-by: Mitch Curtis <[email protected]>
Reviewed-by: Richard Moe Gustavsen <[email protected]>
(cherry picked from commit 83d091dcb160d3f0c4a8bc9df8b8a9a934ac82a1)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
---
 src/quick/items/qquickitemview.cpp            |  4 ++-
 .../data/destroyWithInvalidatedContexts.qml   | 28 +++++++++++++++++++
 .../qquicklistview/tst_qquicklistview.cpp     | 12 ++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 
tests/auto/quick/qquicklistview/data/destroyWithInvalidatedContexts.qml

diff --git a/src/quick/items/qquickitemview.cpp 
b/src/quick/items/qquickitemview.cpp
index 956b4a46b4..cf4475e00a 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -2681,8 +2681,10 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem 
*item, QQmlInstanceModel::Reu
             }
         }
 
-        if (removeItemChangeListener)
+        if (removeItemChangeListener) {
+            unrequestedItems.remove(quickItem);
             QQuickItemPrivate::get(quickItem)->removeItemChangeListener(this, 
itemChangeListenerTypes);
+        }
 #if QT_CONFIG(quick_viewtransitions)
         delete item->transitionableItem;
         item->transitionableItem = nullptr;
diff --git 
a/tests/auto/quick/qquicklistview/data/destroyWithInvalidatedContexts.qml 
b/tests/auto/quick/qquicklistview/data/destroyWithInvalidatedContexts.qml
new file mode 100644
index 0000000000..a2b86444a9
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/destroyWithInvalidatedContexts.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Item {
+    id: root
+    width: 320
+    height: 240
+
+    // Set to true once the deactivated Loader subtree has been deleted, i.e.
+    // after ~QQuickItemView has run.
+    property bool viewDestroyed: false
+
+    Loader {
+        id: loader
+        anchors.fill: parent
+
+        sourceComponent: ListView {
+            model: 40
+            delegate: Item { height: 24 }
+            Component.onDestruction: root.viewDestroyed = true
+        }
+    }
+
+    Component.onCompleted: {
+        const view = loader.item;
+        loader.active = false;
+        view.contentY = 1000;
+    }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp 
b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index ee90b5451b..c30f5e5660 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -266,6 +266,7 @@ private slots:
     void QTBUG_66163_setModelViewPortSizeChange();
     void itemFiltered();
     void releaseItems();
+    void destroyWithInvalidatedContexts();
 
     void QTBUG_34576_velocityZero();
     void QTBUG_61537_modelChangesAsync();
@@ -9789,6 +9790,17 @@ void tst_QQuickListView::releaseItems()
     listview->setModel(123);
 }
 
+void tst_QQuickListView::destroyWithInvalidatedContexts()
+{
+    QScopedPointer<QQuickView> window(createView());
+    window->setSource(testFileUrl("destroyWithInvalidatedContexts.qml"));
+
+    // Wait for the deactivated Loader subtree's deferred delete to be 
delivered.
+    // Once the ListView is gone its ~QQuickItemView has run; it must not have
+    // dereferenced a freed delegate left in unrequestedItems (don't crash).
+    QTRY_VERIFY(window->rootObject()->property("viewDestroyed").toBool());
+}
+
 void tst_QQuickListView::QTBUG_34576_velocityZero()
 {
     QScopedPointer<QQuickView> window(new QQuickView(nullptr));
-- 
2.56.0

Reply via email to