QGraphicsProxyWidget: Don't crash within setWidget() when a child proxy has no assigned widget

QGraphicsProxyWidget::setWidget() is checking if the newly assigned
widget is already assigned to a child proxy widget without checking if
the child has a widget assigned at all which lead to a nullptr reference
if it is not the case.
Therefore check if the assigned widget is a valid pointer.

Fixes: QTBUG-15442
Change-Id: I006877f99895ca01975bdcad071cfcf90bea22ad
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Christian Ehrlicher 2018-11-17 14:58:15 +01:00
parent d0fadae79f
commit 794140fb86
2 changed files with 19 additions and 4 deletions

View File

@ -607,20 +607,20 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
for (QGraphicsItem *child : childItems) {
if (child->d_ptr->isProxyWidget()) {
QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child);
QWidget * parent = childProxy->widget();
while (parent->parentWidget() != 0) {
QWidget *parent = childProxy->widget();
while (parent && parent->parentWidget()) {
if (parent == widget)
break;
parent = parent->parentWidget();
}
if (!childProxy->widget() || parent != widget)
continue;
childProxy->setWidget(0);
childProxy->setWidget(nullptr);
delete childProxy;
}
}
widget = 0;
widget = nullptr;
#ifndef QT_NO_CURSOR
q->unsetCursor();
#endif

View File

@ -140,6 +140,7 @@ private slots:
void palettePropagation();
void fontPropagation();
void dontCrashWhenDie();
void dontCrashNoParent();
void createProxyForChildWidget();
#ifndef QT_NO_CONTEXTMENU
void actionsContextMenu();
@ -2964,6 +2965,20 @@ void tst_QGraphicsProxyWidget::dontCrashWhenDie()
qDeleteAll(QApplication::topLevelWidgets());
}
void tst_QGraphicsProxyWidget::dontCrashNoParent() // QTBUG-15442
{
QGraphicsProxyWidget *parent(new QGraphicsProxyWidget);
QGraphicsProxyWidget *child(new QGraphicsProxyWidget);
QScopedPointer<QLabel> label0(new QLabel);
QScopedPointer<QLabel> label1(new QLabel);
child->setParentItem(parent);
// Set the first label as the proxied widget.
parent->setWidget(label0.data());
// If we attempt to change the proxied widget we get a crash.
parent->setWidget(label1.data());
}
void tst_QGraphicsProxyWidget::createProxyForChildWidget()
{
QGraphicsScene scene;