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 <eike.ziller@qt.io>
(cherry picked from commit 2af64c4577e42fecfeab9611c15fa8526bb09988)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2022-08-25 14:11:23 +02:00 committed by Qt Cherry-pick Bot
parent 50bb5f8282
commit accc833e55
2 changed files with 10 additions and 1 deletions

View File

@ -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);

View File

@ -395,6 +395,7 @@ public:
bool duplicatesEnabled : 1;
bool frame : 1;
bool inserting : 1;
bool hidingPopup : 1;
};
QT_END_NAMESPACE