From e29fceaee47e0a2edba83605c7fa2789cfb8de1e Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Fri, 31 Aug 2018 09:10:47 +0300 Subject: [PATCH] Fix a use-after-free error during logout --- src/ChatPage.cpp | 37 +++++++++++++++++++------------------ src/ChatPage.h | 1 + src/MainWindow.cpp | 15 +++++++++++---- src/MainWindow.h | 2 +- src/UserInfoWidget.cpp | 4 ++-- src/UserInfoWidget.h | 3 --- 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index b7cb999f..4bb7b497 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -169,24 +169,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) }); connect(this, &ChatPage::loggedOut, this, &ChatPage::logout); - connect(user_info_widget_, &UserInfoWidget::logout, this, [this]() { - http::client()->logout( - [this](const mtx::responses::Logout &, mtx::http::RequestErr err) { - if (err) { - // TODO: handle special errors - emit contentLoaded(); - nhlog::net()->warn( - "failed to logout: {} - {}", - mtx::errors::to_string(err->matrix_error.errcode), - err->matrix_error.error); - return; - } - - emit loggedOut(); - }); - - emit showOverlayProgressBar(); - }); connect(top_bar_, &TopRoomBar::showRoomList, splitter, &Splitter::showFullRoomList); connect(top_bar_, &TopRoomBar::inviteUsers, this, [this](QStringList users) { @@ -1332,3 +1314,22 @@ ChatPage::isSideBarExpanded() { return sideBar_->size().width() > ui::sidebar::NormalSize; } + +void +ChatPage::initiateLogout() +{ + http::client()->logout([this](const mtx::responses::Logout &, mtx::http::RequestErr err) { + if (err) { + // TODO: handle special errors + emit contentLoaded(); + nhlog::net()->warn("failed to logout: {} - {}", + mtx::errors::to_string(err->matrix_error.errcode), + err->matrix_error.error); + return; + } + + emit loggedOut(); + }); + + emit showOverlayProgressBar(); +} diff --git a/src/ChatPage.h b/src/ChatPage.h index 5bb7ecae..9398b443 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -72,6 +72,7 @@ public: void hideSideBars(); //! Show the room/group list (if it was visible). void showSideBars(); + void initiateLogout(); public slots: void leaveRoom(const QString &room_id); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index a93f0c9f..95c56554 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -441,15 +441,22 @@ MainWindow::showSolidOverlayModal(QWidget *content, QFlags fl } void -MainWindow::openLogoutDialog(std::function callback) +MainWindow::openLogoutDialog() { auto dialog = new dialogs::Logout(this); - connect(dialog, &dialogs::Logout::closing, this, [this, callback](bool logging_out) { + connect(dialog, &dialogs::Logout::closing, this, [this](bool logging_out) { if (modal_) modal_->hide(); - if (logging_out) - callback(); + // By initiating the logout process a new overlay widget + // will replace & destroy the previous widget (logout dialog). + // + // This will force the destruction of the logout widget to + // happen after the click event has been fully processed. + QTimer::singleShot(0, this, [logging_out, this]() { + if (logging_out) + chat_page_->initiateLogout(); + }); }); showTransparentOverlayModal(dialog, Qt::AlignCenter); diff --git a/src/MainWindow.h b/src/MainWindow.h index 0fa49f17..1953ba0e 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -70,7 +70,7 @@ public: void openCreateRoomDialog( std::function callback); void openJoinRoomDialog(std::function callback); - void openLogoutDialog(std::function callback); + void openLogoutDialog(); void openRoomSettings(const QString &room_id = ""); void openMemberListDialog(const QString &room_id = ""); void openUserProfile(const QString &user_id, const QString &room_id); diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp index c0409823..c3f541ba 100644 --- a/src/UserInfoWidget.cpp +++ b/src/UserInfoWidget.cpp @@ -89,8 +89,8 @@ UserInfoWidget::UserInfoWidget(QWidget *parent) topLayout_->addLayout(buttonLayout_); // Show the confirmation dialog. - connect(logoutButton_, &QPushButton::clicked, this, [this]() { - MainWindow::instance()->openLogoutDialog([this]() { emit logout(); }); + connect(logoutButton_, &QPushButton::clicked, this, []() { + MainWindow::instance()->openLogoutDialog(); }); } diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h index ea2d5400..65de7be9 100644 --- a/src/UserInfoWidget.h +++ b/src/UserInfoWidget.h @@ -42,9 +42,6 @@ public: QColor borderColor() const { return borderColor_; } void setBorderColor(QColor &color) { borderColor_ = color; } -signals: - void logout(); - protected: void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override;