QToolButton: Don't crash if deleted while in event handler

If QToolButton::mouseReleaseEvent triggers its deletion then it
will crash when dereferencing its d pointer.

qabstractbutton.cpp already uses QPointer guards in many places but
qtoolbutton.cpp was missing this one.

While deleteLater() is still our recommendation, we shouldn't crash.
It's not always obvious what led to the button's destruction,
as the chain of indirections can be long.

Change-Id: I4a33447fa4e90953370277eb57a161398ded9a9c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
(cherry picked from commit 97d227acc74c6034615dc05d9d94ee5cad7c5f50)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Sergio Martins 2024-04-04 17:43:59 +01:00 committed by Qt Cherry-pick Bot
parent 50c49a6979
commit 9e4e2ea2ad
2 changed files with 21 additions and 1 deletions

View File

@ -584,8 +584,10 @@ void QToolButton::mousePressEvent(QMouseEvent *e)
void QToolButton::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QToolButton);
QPointer<QAbstractButton> guard(this);
QAbstractButton::mouseReleaseEvent(e);
d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
if (guard)
d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
}
/*!

View File

@ -34,6 +34,7 @@ private slots:
void qtbug_26956_popupTimerDone();
void qtbug_34759_sizeHintResetWhenSettingMenu();
void defaultActionSynced();
void deleteInHandler();
protected slots:
void sendMouseClick();
@ -316,5 +317,22 @@ void tst_QToolButton::defaultActionSynced()
QCOMPARE(bSpy.size(), ++bToggledCount);
}
void tst_QToolButton::deleteInHandler()
{
// Tests that if something deletes the button
// while its event handler is still on the callstack, we don't crash
QPointer<QToolButton> tb = new QToolButton();
tb->show();
QVERIFY(QTest::qWaitForWindowActive(tb));
connect(tb, &QToolButton::clicked, this, [tb] {
delete tb;
});
QTest::mouseClick(tb, Qt::LeftButton);
QVERIFY(!tb);
}
QTEST_MAIN(tst_QToolButton)
#include "tst_qtoolbutton.moc"