From 6c3275d17e3134497873b9ae10b6471656170da0 Mon Sep 17 00:00:00 2001 From: Jian Liang Date: Fri, 21 Sep 2012 10:48:00 +0800 Subject: Avoid crash caused by drag and drop and winId() Task-number: QTBUG-27263 QWExtra object pointer is not guaranteed to be valid in QWidget::unregisterOldDnd() since commit f6bf4b2baa91e55f40596bf3f2823b119fdfa5e0. To avoid crash we have to check QWExtra object pointer of the native parent widget before access it, and if the pointer is not valid we should check its native parent widget recursively. Change-Id: I764fea4a0826cff751dd74a0fb67e0d2971c1d49 Reviewed-by: Miikka Heikkinen Reviewed-by: Friedemann Kleint --- src/gui/kernel/qwidget_win.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index d15a447..c965871 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1799,18 +1799,28 @@ void QWidgetPrivate::unregisterOleDnd(QWidget *widget, QOleDropTarget *dropTarge Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); if (!widget->internalWinId()) { QWidget *nativeParent = widget->nativeParentWidget(); - Q_ASSERT(nativeParent); - QWExtra *nativeExtra = nativeParent->d_func()->extra; - Q_ASSERT(nativeExtra); - nativeExtra->oleDropWidgets.removeAll(widget); - nativeExtra->oleDropWidgets.removeAll(static_cast(0)); - if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget + while (nativeParent) { + QWExtra *nativeExtra = nativeParent->d_func()->extra; + if (!nativeExtra) { + nativeParent = nativeParent->nativeParentWidget(); + continue; + } + + const int removeCounter = nativeExtra->oleDropWidgets.removeAll(widget); + nativeExtra->oleDropWidgets.removeAll(static_cast(0)); + if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget && !nativeParent->testAttribute(Qt::WA_DropSiteRegistered)) { #ifndef Q_OS_WINCE - CoLockObjectExternal(nativeExtra->dropTarget, false, true); + CoLockObjectExternal(nativeExtra->dropTarget, false, true); #endif - RevokeDragDrop(nativeParent->internalWinId()); - nativeExtra->dropTarget = 0; + RevokeDragDrop(nativeParent->internalWinId()); + nativeExtra->dropTarget = 0; + } + + if (removeCounter) + break; + + nativeParent = nativeParent->nativeParentWidget(); } } else { #ifndef Q_OS_WINCE -- cgit v0.12