From ffd2817d18a2d89536ae39e2b05c75b46d1c74c7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 18 Jul 2018 22:22:07 +0300 Subject: [PATCH] Destroy InputField::Inner before InputField. Inner has a pointer to parent and uses it assuming it is InputField. If Inner lives longer than InputField (till ~QWidget) then in some cases it accesses InputField as a (not completely) destroyed object. --- .../SourceFiles/ui/widgets/input_fields.cpp | 18 +++++++++++------- Telegram/SourceFiles/ui/widgets/input_fields.h | 4 +++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index afcbdd7fd3..7e30458c52 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -1137,7 +1137,7 @@ InputField::InputField( , _mode(mode) , _minHeight(st.heightMin) , _maxHeight(st.heightMax) -, _inner(this) +, _inner(std::make_unique(this)) , _lastTextWithTags(value) , _placeholderFactory(std::move(placeholderFactory)) { _inner->setAcceptRichText(false); @@ -1182,10 +1182,12 @@ InputField::InputField( connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer())); connect(_inner->document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(onDocumentContentsChange(int,int,int))); - connect(_inner, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool))); - connect(_inner, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool))); - connect(_inner, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged())); - if (App::wnd()) connect(_inner, SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu())); + connect(_inner.get(), SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool))); + connect(_inner.get(), SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool))); + connect(_inner.get(), SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged())); + if (App::wnd()) { + connect(_inner.get(), SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu())); + } const auto bar = _inner->verticalScrollBar(); _scrollTop = bar->value(); @@ -2463,11 +2465,11 @@ void InputField::clearFocus() { } not_null InputField::rawTextEdit() { - return _inner; + return _inner.get(); } not_null InputField::rawTextEdit() const { - return _inner; + return _inner.get(); } void InputField::keyPressEventInner(QKeyEvent *e) { @@ -3376,6 +3378,8 @@ void InputField::setErrorShown(bool error) { } } +InputField::~InputField() = default; + MaskedInputField::MaskedInputField( QWidget *parent, const style::InputField &st, diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.h b/Telegram/SourceFiles/ui/widgets/input_fields.h index e91fbae78a..7b4b098b51 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.h +++ b/Telegram/SourceFiles/ui/widgets/input_fields.h @@ -297,6 +297,8 @@ public: int scrollTopMax() const; void scrollTo(int top); + ~InputField(); + private slots: void onTouchTimer(); @@ -413,7 +415,7 @@ private: bool _forcePlaceholderHidden = false; bool _reverseMarkdownReplacement = false; - object_ptr _inner; + const std::unique_ptr _inner; TextWithTags _lastTextWithTags; std::vector _lastMarkdownTags;