QMdiArea: port Q_FOREACH to ranged-for, loop could call QCA::sendEvent()
Take a copy of the d->childWindows container because each loop body may end up directly/indirectly calling QCoreApplication::sendEvent() which means unbounded/unknown code could be invoked causing recursing into the class, leading to modifying the childWindows container while iterating over it. Task-number: QTBUG-115803 Change-Id: Ib62ba38700e8862940ba98fdeb663dd730ff125f Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit 875f988af5d9df6c85269959414014d6ef1417ad) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
5a171799cf
commit
2a70f6cccf
@ -671,7 +671,11 @@ void QMdiAreaPrivate::_q_deactivateAllWindows(QMdiSubWindow *aboutToActivate)
|
|||||||
aboutToBecomeActive = aboutToActivate;
|
aboutToBecomeActive = aboutToActivate;
|
||||||
Q_ASSERT(aboutToBecomeActive);
|
Q_ASSERT(aboutToBecomeActive);
|
||||||
|
|
||||||
foreach (QMdiSubWindow *child, childWindows) {
|
// Take a copy because child->showNormal() could indirectly call
|
||||||
|
// QCoreApplication::sendEvent(), which could call unknown code that e.g.
|
||||||
|
// recurses into the class modifying childWindows.
|
||||||
|
const auto subWindows = childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (!sanityCheck(child, "QMdiArea::deactivateAllWindows") || aboutToBecomeActive == child)
|
if (!sanityCheck(child, "QMdiArea::deactivateAllWindows") || aboutToBecomeActive == child)
|
||||||
continue;
|
continue;
|
||||||
// We don't want to handle signals caused by child->showNormal().
|
// We don't want to handle signals caused by child->showNormal().
|
||||||
@ -1324,7 +1328,11 @@ void QMdiAreaPrivate::scrollBarPolicyChanged(Qt::Orientation orientation, Qt::Sc
|
|||||||
const QMdiSubWindow::SubWindowOption option = orientation == Qt::Horizontal ?
|
const QMdiSubWindow::SubWindowOption option = orientation == Qt::Horizontal ?
|
||||||
QMdiSubWindow::AllowOutsideAreaHorizontally : QMdiSubWindow::AllowOutsideAreaVertically;
|
QMdiSubWindow::AllowOutsideAreaHorizontally : QMdiSubWindow::AllowOutsideAreaVertically;
|
||||||
const bool enable = policy != Qt::ScrollBarAlwaysOff;
|
const bool enable = policy != Qt::ScrollBarAlwaysOff;
|
||||||
foreach (QMdiSubWindow *child, childWindows) {
|
// Take a copy because child->setOption() may indirectly call QCoreApplication::sendEvent(),
|
||||||
|
// the latter could call unknown code that could e.g. recurse into the class
|
||||||
|
// modifying childWindows.
|
||||||
|
const auto subWindows = childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (!sanityCheck(child, "QMdiArea::scrollBarPolicyChanged"))
|
if (!sanityCheck(child, "QMdiArea::scrollBarPolicyChanged"))
|
||||||
continue;
|
continue;
|
||||||
child->setOption(option, enable);
|
child->setOption(option, enable);
|
||||||
@ -1526,7 +1534,12 @@ void QMdiAreaPrivate::setViewMode(QMdiArea::ViewMode mode)
|
|||||||
|
|
||||||
isSubWindowsTiled = false;
|
isSubWindowsTiled = false;
|
||||||
|
|
||||||
foreach (QMdiSubWindow *subWindow, childWindows)
|
// Take a copy as tabBar->addTab() will (indirectly) create a connection between
|
||||||
|
// the tab close button clicked() signal and the _q_closeTab() slot, which may
|
||||||
|
// indirectly call QCoreApplication::sendEvent(), the latter could result in
|
||||||
|
// invoking unknown code that could e.g. recurse into the class modifying childWindows.
|
||||||
|
const auto subWindows = childWindows;
|
||||||
|
for (QMdiSubWindow *subWindow : subWindows)
|
||||||
tabBar->addTab(subWindow->windowIcon(), tabTextFor(subWindow));
|
tabBar->addTab(subWindow->windowIcon(), tabTextFor(subWindow));
|
||||||
|
|
||||||
QMdiSubWindow *current = q->currentSubWindow();
|
QMdiSubWindow *current = q->currentSubWindow();
|
||||||
@ -1848,7 +1861,11 @@ void QMdiArea::closeAllSubWindows()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
d->isSubWindowsTiled = false;
|
d->isSubWindowsTiled = false;
|
||||||
foreach (QMdiSubWindow *child, d->childWindows) {
|
// Take a copy because the child->close() call below may end up indirectly calling
|
||||||
|
// QCoreApplication::send{Spontaneous}Event(), which may call unknown code that
|
||||||
|
// could e.g. recurse into the class modifying d->childWindows.
|
||||||
|
const auto subWindows = d->childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (!sanityCheck(child, "QMdiArea::closeAllSubWindows"))
|
if (!sanityCheck(child, "QMdiArea::closeAllSubWindows"))
|
||||||
continue;
|
continue;
|
||||||
child->close();
|
child->close();
|
||||||
@ -1987,7 +2004,11 @@ void QMdiArea::removeSubWindow(QWidget *widget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach (QMdiSubWindow *child, d->childWindows) {
|
// Take a copy because child->setWidget(nullptr) will indirectly
|
||||||
|
// QCoreApplication::sendEvent(); the latter could call unknown code that could
|
||||||
|
// e.g. recurse into the class modifying d->childWindows.
|
||||||
|
const auto subWindows = d->childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (!sanityCheck(child, "QMdiArea::removeSubWindow"))
|
if (!sanityCheck(child, "QMdiArea::removeSubWindow"))
|
||||||
continue;
|
continue;
|
||||||
if (child->widget() == widget) {
|
if (child->widget() == widget) {
|
||||||
@ -2268,7 +2289,11 @@ void QMdiArea::resizeEvent(QResizeEvent *resizeEvent)
|
|||||||
|
|
||||||
// Resize maximized views.
|
// Resize maximized views.
|
||||||
bool hasMaximizedSubWindow = false;
|
bool hasMaximizedSubWindow = false;
|
||||||
foreach (QMdiSubWindow *child, d->childWindows) {
|
// Take a copy because child->resize() may call QCoreApplication::sendEvent()
|
||||||
|
// which may invoke unknown code, that could e.g. recurse into the class
|
||||||
|
// modifying d->childWindows.
|
||||||
|
const auto subWindows = d->childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (sanityCheck(child, "QMdiArea::resizeEvent") && child->isMaximized()
|
if (sanityCheck(child, "QMdiArea::resizeEvent") && child->isMaximized()
|
||||||
&& child->size() != resizeEvent->size()) {
|
&& child->size() != resizeEvent->size()) {
|
||||||
auto realSize = resizeEvent->size();
|
auto realSize = resizeEvent->size();
|
||||||
@ -2484,12 +2509,16 @@ bool QMdiArea::event(QEvent *event)
|
|||||||
d->isSubWindowsTiled = true;
|
d->isSubWindowsTiled = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEvent::WindowIconChange:
|
case QEvent::WindowIconChange: {
|
||||||
foreach (QMdiSubWindow *window, d->childWindows) {
|
// Take a copy because QCoreApplication::sendEvent() may call unknown code,
|
||||||
|
// that may cause recursing into the class
|
||||||
|
const auto subWindows = d->childWindows;
|
||||||
|
for (QMdiSubWindow *window : subWindows) {
|
||||||
if (sanityCheck(window, "QMdiArea::WindowIconChange"))
|
if (sanityCheck(window, "QMdiArea::WindowIconChange"))
|
||||||
QCoreApplication::sendEvent(window, event);
|
QCoreApplication::sendEvent(window, event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case QEvent::Hide:
|
case QEvent::Hide:
|
||||||
d->setActive(d->active, false, false);
|
d->setActive(d->active, false, false);
|
||||||
d->setChildActivationEnabled(false);
|
d->setChildActivationEnabled(false);
|
||||||
@ -2644,7 +2673,10 @@ void QMdiArea::setupViewport(QWidget *viewport)
|
|||||||
Q_D(QMdiArea);
|
Q_D(QMdiArea);
|
||||||
if (viewport)
|
if (viewport)
|
||||||
viewport->setAttribute(Qt::WA_OpaquePaintEvent, d->background.isOpaque());
|
viewport->setAttribute(Qt::WA_OpaquePaintEvent, d->background.isOpaque());
|
||||||
foreach (QMdiSubWindow *child, d->childWindows) {
|
// Take a copy because the child->setParent() call below may call QCoreApplication::sendEvent()
|
||||||
|
// which may call unknown code that could e.g. recurse into the class modifying d->childWindows.
|
||||||
|
const auto subWindows = d->childWindows;
|
||||||
|
for (QMdiSubWindow *child : subWindows) {
|
||||||
if (!sanityCheck(child, "QMdiArea::setupViewport"))
|
if (!sanityCheck(child, "QMdiArea::setupViewport"))
|
||||||
continue;
|
continue;
|
||||||
child->setParent(viewport, child->windowFlags());
|
child->setParent(viewport, child->windowFlags());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user