Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
4.5.0
-
None
-
ce4522cb341340e98427d678664ea84761e3ca07
Description
QMainWindow::restore() can fill a dock area with QDockAreaLayoutInfo that have neither a subinfo, nor a widgetItem. This happens when the dock widgets do not exist yet when QMainWindow::restore() is called.
The code of QDockAreaLayoutInfo::insertGap() call the function widget() on the widgetItem, even if it is null. :
QDockAreaLayoutInfo *subinfo = item.subinfo; QLayoutItem *widgetItem = item.widgetItem; QRect r = subinfo == 0 ? dockedGeometry(widgetItem->widget()) : subinfo->rect;
The following code reproduce the initial conditions of the crash, but is unable to reproduce the crash (the condition path.count() > 1 is not respected in QDockAreaLayoutInfo::insertGap()). Set a breakpoint in QDockAreaLayoutInfo::insertGap() to see that the QDockAreaLayoutInfo in the item_list have (subinfo == 0 && widgetItem ==0).
#include <QtGui> int main(int argc, char *argv[]) { QApplication app(argc, argv); QDockWidget *customDockWidget = new QDockWidget(); customDockWidget->setObjectName("customDockWidget"); QDockWidget *customDockWidget1 = new QDockWidget(); customDockWidget1->setObjectName("customDockWidget1"); QDockWidget *customDockWidget2 = new QDockWidget(); customDockWidget2->setObjectName("customDockWidget2"); QMainWindow window; window.setDockOptions(QMainWindow::AnimatedDocks); window.setDockNestingEnabled(true); window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget, Qt::Vertical); window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget1, Qt::Horizontal); window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget2, Qt::Horizontal); window.show(); app.exec(); QByteArray state = window.saveState(); QMainWindow otherWindow; otherWindow.setDockOptions(QMainWindow::AnimatedDocks); otherWindow.restoreState(state); otherWindow.addDockWidget(Qt::RightDockWidgetArea, new QDockWidget(), Qt::Horizontal); otherWindow.setCentralWidget(new QPushButton("move the the left")); otherWindow.show(); return app.exec(); }
Here is a trace of the crash in Valgrind:
==17364== Invalid read of size 8
==17364== at 0xF0BD91F: QDockAreaLayoutInfo::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:1330)
==17364== by 0xF0BDC41: QDockAreaLayout::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:2706)
==17364== by 0xF0E0AF0: QMainWindowLayoutState::insertGap(QList<int>, QLayoutItem*) (qmainwindowlayout.cpp:446)
==17364== by 0xF0E5B7E: QMainWindowLayout::hover(QLayoutItem*, QPoint const&) (qmainwindowlayout.cpp:1925)
==17364== by 0xF0AC6E5: QDockWidgetPrivate::mouseMoveEvent(QMouseEvent*) (qdockwidget.cpp:876)
==17364== by 0xF0AE9B9: QDockWidget::event(QEvent*) (qdockwidget.cpp:1437)
==17364== by 0xED083CD: QApplicationPrivate::notify_helper(QObject*, QEvent*) (qapplication.cpp:4056)
==17364== by 0xED0D88A: QApplication::notify(QObject*, QEvent*) (qapplication.cpp:3758)
==17364== by 0x7D4CC95: QTestApplication::notify(QObject*, QEvent*) (QTestApplication.cpp:79)
==17364== by 0xE8470B2: QCoreApplication::notifyInternal(QObject*, QEvent*) (qcoreapplication.cpp:610)
==17364== by 0xED0CC30: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&) (qcoreapplication.h:216)
==17364== by 0xED70C4C: QETWidget::translateMouseEvent(_XEvent const*) (qapplication_x11.cpp:4409)
==17364== by 0xED6F1EC: QApplication::x11ProcessEvent(_XEvent*) (qapplication_x11.cpp:3550)
==17364== by 0xED95C92: x11EventSourceDispatch(_GSource*, int (void*), void*) (qguieventdispatcher_glib.cpp:146)
==17364== by 0x3C8DE2EF52: g_main_context_dispatch (in /lib64/libglib-2.0.so.0.1400.6)
==17364== by 0x3C8DE3224C: ??? (in /lib64/libglib-2.0.so.0.1400.6)
==17364== by 0x3C8DE3277D: g_main_context_iteration (in /lib64/libglib-2.0.so.0.1400.6)
==17364== by 0xE870D0D: QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qeventdispatcher_glib.cpp:327)
==17364== by 0xED95AAE: QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qguieventdispatcher_glib.cpp:202)
==17364== by 0xE8464A4: QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qeventloop.cpp:149)
==17364== by 0xE84670B: QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (qeventloop.cpp:201)
==17364== by 0xE848378: QCoreApplication::exec() (qcoreapplication.cpp:888)
==17364== by 0x7D49694: Tapplication::start() (Tapplication.cpp:684)
==17364== by 0x40D4E1: appmain() (TTestApp.cpp:1333)
==17364== by 0x41BDE0: main (main.cpp:74)
==17364== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==17364==
==17364== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==17364== Access not within mapped region at address 0x0
==17364== at 0xF0BD91F: QDockAreaLayoutInfo::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:1330)
==17364== by 0xF0BDC41: QDockAreaLayout::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:2706)
==17364== by 0xF0E0AF0: QMainWindowLayoutState::insertGap(QList<int>, QLayoutItem*) (qmainwindowlayout.cpp:446)
==17364== by 0xF0E5B7E: QMainWindowLayout::hover(QLayoutItem*, QPoint const&) (qmainwindowlayout.cpp:1925)
==17364== by 0xF0AC6E5: QDockWidgetPrivate::mouseMoveEvent(QMouseEvent*) (qdockwidget.cpp:876)
==17364== by 0xF0AE9B9: QDockWidget::event(QEvent*) (qdockwidget.cpp:1437)
==17364== by 0xED083CD: QApplicationPrivate::notify_helper(QObject*, QEvent*) (qapplication.cpp:4056)
==17364== by 0xED0D88A: QApplication::notify(QObject*, QEvent*) (qapplication.cpp:3758)
==17364== by 0x7D4CC95: QTestApplication::notify(QObject*, QEvent*) (QTestApplication