forked from qt-creator/qt-creator
QmlDesigner: destroy BaseTextEditor before DesignDocument
Stale TextEditor::BaseTextEditor instances could still receive paint events after their DesignDocument had already been deleted. This led to a use-after-free in TextEditorWidgetPrivate::updateLineAnnotation() and sporadic heap corruption on shutdown. shutdown problem at https://the-qt-company-00.sentry.io/issues/6409328760 paint problem at https://the-qt-company-00.sentry.io/issues/6648131182 Change-Id: I5cc9762257d92cd1f6d9cf790ef77b3f1c2b0844 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -63,8 +63,9 @@ void TextEditorView::modelAttached(Model *model)
|
|||||||
|
|
||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
|
|
||||||
|
DesignDocument *designDocument = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||||
auto textEditor = Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor>(
|
auto textEditor = Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor>(
|
||||||
QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor()->duplicate());
|
designDocument->textEditor()->duplicate());
|
||||||
static constexpr char qmlTextEditorContextId[] = "QmlDesigner::TextEditor";
|
static constexpr char qmlTextEditorContextId[] = "QmlDesigner::TextEditor";
|
||||||
IContext::attach(textEditor->widget(),
|
IContext::attach(textEditor->widget(),
|
||||||
Context(qmlTextEditorContextId, Constants::qtQuickToolsMenuContextId),
|
Context(qmlTextEditorContextId, Constants::qtQuickToolsMenuContextId),
|
||||||
@@ -72,6 +73,12 @@ void TextEditorView::modelAttached(Model *model)
|
|||||||
m_widget->contextHelp(callback);
|
m_widget->contextHelp(callback);
|
||||||
});
|
});
|
||||||
m_widget->setTextEditor(std::move(textEditor));
|
m_widget->setTextEditor(std::move(textEditor));
|
||||||
|
|
||||||
|
disconnect(m_designDocumentConnection);
|
||||||
|
m_designDocumentConnection = connect(designDocument,
|
||||||
|
&DesignDocument::designDocumentClosed,
|
||||||
|
m_widget,
|
||||||
|
[this] { m_widget->setTextEditor(nullptr); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorView::modelAboutToBeDetached(Model *model)
|
void TextEditorView::modelAboutToBeDetached(Model *model)
|
||||||
@@ -80,6 +87,7 @@ void TextEditorView::modelAboutToBeDetached(Model *model)
|
|||||||
|
|
||||||
if (m_widget)
|
if (m_widget)
|
||||||
m_widget->setTextEditor(nullptr);
|
m_widget->setTextEditor(nullptr);
|
||||||
|
disconnect(m_designDocumentConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
void TextEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||||
|
@@ -78,6 +78,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<TextEditorWidget> m_widget;
|
QPointer<TextEditorWidget> m_widget;
|
||||||
|
QMetaObject::Connection m_designDocumentConnection;
|
||||||
bool m_errorState = false;
|
bool m_errorState = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user