From accc833e556ba54038d1cc7e261a936492145240 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 25 Aug 2022 14:11:23 +0200 Subject: [PATCH] QComboBox: Prevent recursion in hidePopup With styles that want the selected combobox item to flash, QComboBox runs a modal event loop in hidePopup. This might result in reentrancy if a mouseReleaseEvent is processed during the 60 ms of flashing. Since mouseReleaseEvent calls hidePopup again, we end up reentrancy and possibly undefined behavior which has caused crashes with Qt Creator on macOS. Prevent the reentrancy of hidePopup using a boolean flag. Since QBoolBlocker (or QScopedValueRollback) cannot be used with a bit flag, use a QScopeGuard to reset the flag reliably. Fixes: QTBUG-105951 Change-Id: Iaa5df47b93217fc8dff621764ac4005bbc3459b7 Reviewed-by: Eike Ziller (cherry picked from commit 2af64c4577e42fecfeab9611c15fa8526bb09988) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qcombobox.cpp | 10 +++++++++- src/widgets/widgets/qcombobox_p.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 9caac239f9..e754d02f2a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -58,7 +58,8 @@ QComboBoxPrivate::QComboBoxPrivate() shownOnce(false), duplicatesEnabled(false), frame(true), - inserting(false) + inserting(false), + hidingPopup(false) { } @@ -2805,6 +2806,13 @@ void QComboBox::showPopup() void QComboBox::hidePopup() { Q_D(QComboBox); + if (d->hidingPopup) + return; + d->hidingPopup = true; + // can't use QBoolBlocker on a bitfield + auto resetHidingPopup = qScopeGuard([d]{ + d->hidingPopup = false; + }); if (d->container && d->container->isVisible()) { #if QT_CONFIG(effects) QSignalBlocker modelBlocker(d->model); diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index d725624d6d..a26f3a34d4 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -395,6 +395,7 @@ public: bool duplicatesEnabled : 1; bool frame : 1; bool inserting : 1; + bool hidingPopup : 1; }; QT_END_NAMESPACE