diff options
author | Jian Liang <jianliang79@gmail.com> | 2013-12-14 10:59:35 +0800 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-24 02:56:41 +0100 |
commit | 8fcab70408628f730860d3861a06fc519d069f5e (patch) | |
tree | eb0aa24e05cd717cecaa5f22bb932142e0e7de27 /src/widgets/kernel/qwidget_qpa.cpp | |
parent | 0e1ce36ae67de940b2d499ec7f23e520dce0f112 (diff) |
Avoid crash due to accessing deleted QWidgetWindow object
Change childWidget->windowHandle() to childWidget->internalWinId() in
q_createNativeChildrenAndSetParent() to determine whether should we call
childWidget->winId().
This is because in some circumstances Qt will crash due to accessing
deleted QWidgetWindow object if we use windowHandle(). Think about the
following scenario:
1) create a widget A without parent and add two child widgets B and C to A
2) create a native widget D as the child of B, note that when we set
Qt::WA_NativeWindow attribute to it, its QWidgetWindow will be created
which means its windowHandle() is not null.
3) create a top level widget E as the child of C and show it. This will
make Qt call createWinId() to A and then
q_createNativeChildrenAndSetParent() will be called to create A's native
children recursively and finally make D's QWidgetWindow object become a
child of A's QWidgetWindow object. Please note here that B will not become
a native widget just because at that moment windowHandle() of D is not
null and Qt will not call winId() to its parent B
4) Set A's parent to another widget which has been shown, setParent_sys()
will be called to A and then Qt will call destroy() to A. in destroy() Qt
will try to call destroy() to its children recursively with a condition that
the child has Qt::WA_NativeWindow been set. But D's parent B is not a native
widget right now so B and D is not destroyed. Qt will then deleted the
QWidgetWindow object of A, since E's QWidgetWindow object is a child of
A's QWidgetWindow object, it will also be deleted. Now E hold a deleted
pointer of QWidgetWindow object. This is the source of crash later.
Task-number: QTBUG-35600
Change-Id: I97a20a68e626ee62b15bb4eae580e26f8948923b
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/widgets/kernel/qwidget_qpa.cpp')
-rw-r--r-- | src/widgets/kernel/qwidget_qpa.cpp | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 3b6127e4e7..3281e0c6f7 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -70,7 +70,7 @@ void q_createNativeChildrenAndSetParent(const QWidget *parentWidget) const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i)); if (childWidget) { // should not be necessary if (childWidget->testAttribute(Qt::WA_NativeWindow)) { - if (!childWidget->windowHandle()) + if (!childWidget->internalWinId()) childWidget->winId(); if (childWidget->windowHandle()) { QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle(); |