summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2023-02-20 11:23:09 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2023-02-20 18:07:16 +0100
commitb124171309b259d429bd064fe3bfdec148869ef4 (patch)
treef21d9e77f9cae46f7a6215a612e67c2367bb4bab /tests/auto/corelib/kernel
parent7b1ba955a6da3d4414fa206ec1c06c1fc6e16161 (diff)
QObjectBindableProperty: Avoid use-after-free in notifyObservers
We so far refetched the first observer after evaluating bindings, as binding evaluating might change the list of observers. However, that approach did not take into account that the 'this' pointer might no longer be valid after binding evaluation: In case of a QObjectBindableProperty (or a QObjectCompatProperty), binding evaluation might cause a reallocation of the binding storage, and consequently the invalidation of the QPropertyBindingData. Fix this by refetching the QPropertyBindingData from the storage (if a storage has been provided, which is always the case for the affected classes). Fixes: QTBUG-111268 Pick-to: 6.5 6.4 6.2 Change-Id: Ie7e143a0bbb18f1c3f88a81dd9b31e6af463584f Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tests/auto/corelib/kernel')
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index f849cfa770..8e9192c27e 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -67,6 +67,7 @@ private slots:
void quntypedBindableApi();
void readonlyConstQBindable();
void qobjectBindableManualNotify();
+ void qobjectBindableReallocatedBindingStorage();
void qobjectBindableSignalTakingNewValue();
void testNewStuff();
@@ -1188,6 +1189,23 @@ void tst_QProperty::qobjectBindableManualNotify()
QCOMPARE(object.foo(), 1);
}
+
+struct ReallocObject : QObject {
+ ReallocObject()
+ { v.setBinding([this] { return x.value() + y.value() + z.value(); }); }
+ Q_OBJECT_BINDABLE_PROPERTY(ReallocObject, int, v)
+ Q_OBJECT_BINDABLE_PROPERTY(ReallocObject, int, x)
+ Q_OBJECT_BINDABLE_PROPERTY(ReallocObject, int, y)
+ Q_OBJECT_BINDABLE_PROPERTY(ReallocObject, int, z)
+};
+
+void tst_QProperty::qobjectBindableReallocatedBindingStorage()
+{
+ ReallocObject object;
+ object.x = 1;
+ QCOMPARE(object.v.value(), 1);
+}
+
void tst_QProperty::qobjectBindableSignalTakingNewValue()
{
// Given an object of type MyQObject,