From a5d2731b1ec56580a79784759307d3b3c21ab87f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 4 May 2018 13:29:45 +0200 Subject: Fix QQuickPopupPositioner This is a double-regression caused by commits bcd1bed and 03a8c88. Both of these changes caused dangling pointers being left on the list of item change listeners. First, bcd1bed made QQuickPopupPositioner use QQuickItem::isAncestorOf() without noticing the difference that the old self-made isAncestorOf() conveniently returned true for the item itself, whereas the new built-in QQuickItem::isAncestorOf() doesn't. This had a nasty side effect that when the popup's parent item was removed from its parent, QQuickPopupPositioner::itemChildRemoved() no longer removed the ancestor listeners. Then, 03a8c88 made things worse by changing the stack allocation of QQuickPopupPositioner to heap allocation without ever deleting the positioner object. Valgrind output for tst_tooltip: ==14391== Invalid read of size 8 ==14391== at 0x79EFB9A: QQuickItemPrivate::itemChange(QQuickItem::ItemChange, QQuickItem::ItemChangeData const&) (qquickitem.cpp:6206) ==14391== by 0x79F3D98: QQuickItem::setParentItem(QQuickItem*) (qquickitem.cpp:2791) ==14391== by 0x79F3E87: QQuickItem::~QQuickItem() (qquickitem.cpp:2385) ==14391== by 0x7A16073: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x7A16073: QQmlPrivate::QQmlElement::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x7A9CFEE: QQuickView::~QQuickView() (qquickview.cpp:218) ==14391== by 0x4038215: quick_test_main_with_setup(int, char**, char const*, char const*, QObject*) (quicktest.cpp:512) ==14391== by 0x4038CFF: quick_test_main(int, char**, char const*, char const*) (quicktest.cpp:330) ==14391== by 0x400BD7: main (tst_default.cpp:44) ==14391== Address 0x1f2d3f10 is 0 bytes inside a block of size 32 free'd ==14391== at 0x4C2F29C: operator delete(void*) (vg_replace_malloc.c:576) ==14391== by 0x29CA2641: QQuickPopupPositioner::~QQuickPopupPositioner() (qquickpopuppositioner.cpp:68) ==14391== by 0x29CA004C: QQuickPopup::~QQuickPopup() (qquickpopup.cpp:783) ==14391== by 0x2A1A4CEE: ~QQuickToolTip (qquicktooltip_p.h:59) ==14391== by 0x2A1A4CEE: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x2A1A4CEE: QQmlPrivate::QQmlElement::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x6397A65: QObjectPrivate::deleteChildren() (qobject.cpp:1997) ==14391== by 0x6398DDA: QObject::~QObject() (qobject.cpp:1025) ==14391== by 0x79F41FA: QQuickItem::~QQuickItem() (qquickitem.cpp:2378) ==14391== by 0x7A897D5: QQuickMouseArea::~QQuickMouseArea() (qquickmousearea.cpp:452) ==14391== by 0x7A1699D: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x7A1699D: QQmlPrivate::QQmlElement::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x639082D: qDeleteInEventHandler(QObject*) (qobject.cpp:4603) ==14391== by 0x6392478: QObject::event(QEvent*) (qobject.cpp:1242) ==14391== by 0x79F1D77: QQuickItem::event(QEvent*) (qquickitem.cpp:8006) ==14391== Block was alloc'd at ==14391== at 0x4C2E226: operator new(unsigned long) (vg_replace_malloc.c:334) ==14391== by 0x29C9F939: QQuickPopupPrivate::init() (qquickpopup.cpp:280) ==14391== by 0x29C9FD4E: QQuickPopup::QQuickPopup(QQuickPopupPrivate&, QObject*) (qquickpopup.cpp:771) ==14391== by 0x29CC6CBB: QQuickToolTip::QQuickToolTip(QQuickItem*) (qquicktooltip.cpp:171) ==14391== by 0x2A1A58DD: QQmlElement (qqmlprivate.h:98) ==14391== by 0x2A1A58DD: void QQmlPrivate::createInto(void*) (qqmlprivate.h:107) ==14391== by 0x5D0186D: QQmlType::create(QObject**, void**, unsigned long) const (qqmlmetatype.cpp:915) ==14391== by 0x5D81EFF: QQmlObjectCreator::createInstance(int, QObject*, bool) (qqmlobjectcreator.cpp:1163) ==14391== by 0x5D85AE2: QQmlObjectCreator::create(int, QObject*, QQmlInstantiationInterrupt*) (qqmlobjectcreator.cpp:203) ==14391== by 0x5D82230: QQmlObjectCreator::createInstance(int, QObject*, bool) (qqmlobjectcreator.cpp:1202) ==14391== by 0x5D82F65: QQmlObjectCreator::setPropertyBinding(QQmlPropertyData const*, QV4::CompiledData::Binding const*) (qqmlobjectcreator.cpp:825) ==14391== by 0x5D85105: QQmlObjectCreator::setupBindings(bool) (qqmlobjectcreator.cpp:777) ==14391== by 0x5D857C5: QQmlObjectCreator::populateInstance(int, QObject*, QObject*, QQmlPropertyData const*) (qqmlobjectcreator.cpp:1456) Change-Id: Id368e79146f4673708a84253a009fcdf24ab4a2c Reviewed-by: J-P Nurmi Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickpopup.cpp | 2 ++ src/quicktemplates2/qquickpopuppositioner.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index e3ab952d..a481805f 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -775,6 +775,8 @@ QQuickPopup::~QQuickPopup() d->popupItem->ungrabShortcut(); delete d->popupItem; d->popupItem = nullptr; + delete d->positioner; + d->positioner = nullptr; } /*! diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp index 2b67c85e..f2d02df1 100644 --- a/src/quicktemplates2/qquickpopuppositioner.cpp +++ b/src/quicktemplates2/qquickpopuppositioner.cpp @@ -248,7 +248,7 @@ void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent) void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child) { - if (child->isAncestorOf(m_parentItem)) + if (child == m_parentItem || child->isAncestorOf(m_parentItem)) removeAncestorListeners(item); } -- cgit v1.2.3