Skip to content

Fix double delete crash (QObject/KTextEdit)

Mladen Milinkovic requested to merge work/fix-delete-crash into master

THis fixes following crash scenario:

  • Application shutdown triggers setReadOnly() on KTextEdit
  • setReadOnly() which triggers delete d->decorator
  • QObject parent/child chain tries to access deleted d->decorator

Here's the valgrind output

Invalid read of size 8
  in QObjectPrivate::setParent_helper(QObject*) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  1: QObjectPrivate::setParent_helper(QObject*) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  2: QObject::~QObject() in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  3: Sonnet::Highlighter::~Highlighter() in /home/max/kde/usr/lib/libKF5SonnetUi.so.5.99.0
  4: Sonnet::Highlighter::~Highlighter() in /home/max/kde/usr/lib/libKF5SonnetUi.so.5.99.0
  5: QObjectPrivate::deleteChildren() in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  6: QObject::~QObject() in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  7: Sonnet::SpellCheckDecorator::~SpellCheckDecorator() in /home/max/kde/usr/lib/libKF5SonnetUi.so.5.99.0
  8: KTextDecorator::~KTextDecorator() in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  9: KTextDecorator::~KTextDecorator() in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  10: KTextEdit::setReadOnly(bool) in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  11: SubtitleComposer::CurrentLineWidget::setCurrentLine(SubtitleComposer::SubtitleLine*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  12: SubtitleComposer::CurrentLineWidget::setSubtitle(SubtitleComposer::Subtitle*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  13: SubtitleComposer::Application::init()::{lambda()#7}::operator()() const in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  14: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, SubtitleComposer::Application::init()::{lambda()#7}>::call({lambda()#7}&, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  15: void QtPrivate::Functor<SubtitleComposer::Application::init()::{lambda()#7}, 0>::call<QtPrivate::List<>, void>({lambda()#7}&, void*, {lambda()#7}&*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  16: QtPrivate::QFunctorSlotObject<SubtitleComposer::Application::init()::{lambda()#7}, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  17: void doActivate<false>(QObject*, int, void**) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  18: SubtitleComposer::Application::subtitleClosed() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  19: SubtitleComposer::Application::closeSubtitle() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  20: SubtitleComposer::MainWindow::queryClose() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  21: KMainWindow::closeEvent(QCloseEvent*) in /home/max/kde/usr/lib/libKF5XmlGui.so.5.99.0
  22: QWidget::event(QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  23: KMainWindow::event(QEvent*) in /home/max/kde/usr/lib/libKF5XmlGui.so.5.99.0
  24: KXmlGuiWindow::event(QEvent*) in /home/max/kde/usr/lib/libKF5XmlGui.so.5.99.0
  25: QApplicationPrivate::notify_helper(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
Address 0x30ee7568 is 8 bytes inside a block of size 32 free'd
  1: operator delete(void*, unsigned long) in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
  2: KTextEdit::setReadOnly(bool) in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  3: SubtitleComposer::CurrentLineWidget::setCurrentLine(SubtitleComposer::SubtitleLine*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  4: QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<SubtitleComposer::SubtitleLine*>, void, void (SubtitleComposer::CurrentLineWidget::*)(SubtitleComposer::SubtitleLine*)>::call(void (SubtitleComposer::CurrentLineWidget::*)(SubtitleComposer::SubtitleLine*), SubtitleComposer::CurrentLineWidget*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  5: void QtPrivate::FunctionPointer<void (SubtitleComposer::CurrentLineWidget::*)(SubtitleComposer::SubtitleLine*)>::call<QtPrivate::List<SubtitleComposer::SubtitleLine*>, void>(void (SubtitleComposer::CurrentLineWidget::*)(SubtitleComposer::SubtitleLine*), SubtitleComposer::CurrentLineWidget*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  6: QtPrivate::QSlotObject<void (SubtitleComposer::CurrentLineWidget::*)(SubtitleComposer::SubtitleLine*), QtPrivate::List<SubtitleComposer::SubtitleLine*>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  7: void doActivate<false>(QObject*, int, void**) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  8: SubtitleComposer::LinesWidget::currentLineChanged(SubtitleComposer::SubtitleLine*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  9: SubtitleComposer::LinesWidget::onCurrentRowChanged() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  10: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (SubtitleComposer::LinesWidget::*)()>::call(void (SubtitleComposer::LinesWidget::*)(), SubtitleComposer::LinesWidget*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  11: void QtPrivate::FunctionPointer<void (SubtitleComposer::LinesWidget::*)()>::call<QtPrivate::List<>, void>(void (SubtitleComposer::LinesWidget::*)(), SubtitleComposer::LinesWidget*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  12: QtPrivate::QSlotObject<void (SubtitleComposer::LinesWidget::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  13: void doActivate<false>(QObject*, int, void**) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  14: QItemSelectionModel::currentRowChanged(QModelIndex const&, QModelIndex const&) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  15: QItemSelectionModel::clearCurrentIndex() in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  16: SubtitleComposer::LinesSelectionModel::clear() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  17: SubtitleComposer::LinesModel::onModelReset() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  18: SubtitleComposer::LinesModel::processSelectionUpdate() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  19: saveSelection(int*, QList<std::pair<int, int> >*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  20: SubtitleComposer::UndoStack::levelIncrease(int) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  21: SubtitleComposer::UndoStack::push(SubtitleComposer::UndoAction*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  22: SubtitleComposer::Subtitle::processAction(SubtitleComposer::UndoAction*) const in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  23: SubtitleComposer::SubtitleLine::processAction(SubtitleComposer::UndoAction*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  24: SubtitleComposer::SubtitleLine::primaryDocumentChanged() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  25: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (SubtitleComposer::SubtitleLine::*)()>::call(void (SubtitleComposer::SubtitleLine::*)(), SubtitleComposer::SubtitleLine*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
Block was alloc'd at
  1: operator new(unsigned long) in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
  2: KTextEdit::setHighlighter(Sonnet::Highlighter*) in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  3: KTextEdit::createHighlighter() in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  4: KTextEdit::setCheckSpellingEnabled(bool) in /home/max/kde/usr/lib/libKF5TextWidgets.so.5.99.0
  5: SubtitleComposer::SimpleRichTextEdit::toggleAutoSpellChecking() in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  6: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (SubtitleComposer::SimpleRichTextEdit::*)()>::call(void (SubtitleComposer::SimpleRichTextEdit::*)(), SubtitleComposer::SimpleRichTextEdit*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  7: void QtPrivate::FunctionPointer<void (SubtitleComposer::SimpleRichTextEdit::*)()>::call<QtPrivate::List<>, void>(void (SubtitleComposer::SimpleRichTextEdit::*)(), SubtitleComposer::SimpleRichTextEdit*, void**) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  8: QtPrivate::QSlotObject<void (SubtitleComposer::SimpleRichTextEdit::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) in /home/max/projects/SubtitleComposer/build-SubtitleComposer-kdesrc-Debug/src/subtitlecomposer
  9: void doActivate<false>(QObject*, int, void**) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  10: QAction::triggered(bool) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  11: QAction::activate(QAction::ActionEvent) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  12: QMenuPrivate::activateCausedStack(QVector<QPointer<QWidget> > const&, QAction*, QAction::ActionEvent, bool) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  13: QMenuPrivate::activateAction(QAction*, QAction::ActionEvent, bool) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  14: QWidget::event(QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  15: QApplicationPrivate::notify_helper(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  16: QApplication::notify(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  17: QCoreApplication::notifyInternal2(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  18: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  19: QWidgetWindow::handleMouseEvent(QMouseEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  20: QWidgetWindow::event(QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  21: QApplicationPrivate::notify_helper(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Widgets.so.5.15.6
  22: QCoreApplication::notifyInternal2(QObject*, QEvent*) in /home/max/kde/qt5/lib/libQt5Core.so.5.15.6
  23: QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) in /home/max/kde/qt5/lib/libQt5Gui.so.5.15.6
  24: QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) in /home/max/kde/qt5/lib/libQt5Gui.so.5.15.6
  25: xcbSourceDispatch(_GSource*, int (*)(void*), void*) in /home/max/kde/qt5/lib/libQt5XcbQpa.so.5.15.6

Merge request reports