summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2017-04-18 16:52:19 +0200
committerOlivier Goffart (Woboq GmbH) <ogoffart@woboq.com>2017-04-19 13:25:14 +0000
commitcdb7e81572df726486fc0bdc648f732b797c7f84 (patch)
tree726bc8dbcaee46d01cd4eb085405800d579d60c8 /src
parentf368cd88687643d565763602721cae6e9602e34d (diff)
Fix UB in QLayout::childEvent
We can't just static_cast a child to QLayout, because the child might not be a QLayout, and even if it was, we might be called from the QObject destructor so we would not be a layout anymore. Instead we can just qobject_cast the deleted object to a QLayout and remove it from the layout with removeItem. This would not take in account the case where we would be called because the QLayout gets destroyed, so we handle this case from ~QLayout by removing ourself from the parent. Note that the comment in ~QLayout was wrong, as the layout gets destroyed explicitly from ~QWidget, not from ~QObject. Change-Id: I49c6f17a76f207b9d750b6e5d987469498b96b31 Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/widgets/kernel/qlayout.cpp31
1 files changed, 9 insertions, 22 deletions
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index f88ed350c7..129c12885a 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -641,21 +641,11 @@ void QLayout::childEvent(QChildEvent *e)
if (!d->enabled)
return;
- if (e->type() == QEvent::ChildRemoved) {
- QChildEvent *c = (QChildEvent*)e;
- int i = 0;
-
- QLayoutItem *item;
- while ((item = itemAt(i))) {
- if (item == static_cast<QLayout*>(c->child())) {
- takeAt(i);
- invalidate();
- break;
- } else {
- ++i;
- }
- }
- }
+ if (e->type() != QEvent::ChildRemoved)
+ return;
+
+ if (QLayout *childLayout = qobject_cast<QLayout *>(e->child()))
+ removeItem(childLayout);
}
/*!
@@ -766,13 +756,10 @@ QSize QLayout::totalMaximumSize() const
QLayout::~QLayout()
{
Q_D(QLayout);
- /*
- This function may be called during the QObject destructor,
- when the parent no longer is a QWidget.
- */
- if (d->topLevel && parent() && parent()->isWidgetType() &&
- ((QWidget*)parent())->layout() == this)
- ((QWidget*)parent())->d_func()->layout = 0;
+ if (d->topLevel && parent() && parent()->isWidgetType() && parentWidget()->layout() == this)
+ parentWidget()->d_func()->layout = 0;
+ else if (QLayout *parentLayout = qobject_cast<QLayout *>(parent()))
+ parentLayout->removeItem(this);
}