Fix possible crash in common groups list.

Currently Data::Session::processChat() may change adminRights(),
that may change Data::CanSendAnyOf(peer, ...), that may lead to
Window::SessionController::updateThirdColumnToCurrentChat() call,
that destroys current third column to replace it with another one.

If common groups list was opened in the third column this will crash.

Fixes #27640.
This commit is contained in:
John Preston 2024-05-01 15:02:35 +04:00
parent ad6321d3ae
commit 12a24dd473

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "info/common_groups/info_common_groups_inner_widget.h" #include "info/common_groups/info_common_groups_inner_widget.h"
#include "base/weak_ptr.h"
#include "info/common_groups/info_common_groups_widget.h" #include "info/common_groups/info_common_groups_widget.h"
#include "info/info_controller.h" #include "info/info_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -27,7 +28,9 @@ namespace {
constexpr auto kCommonGroupsPerPage = 40; constexpr auto kCommonGroupsPerPage = 40;
constexpr auto kCommonGroupsSearchAfter = 20; constexpr auto kCommonGroupsSearchAfter = 20;
class ListController final : public PeerListController { class ListController final
: public PeerListController
, public base::has_weak_ptr {
public: public:
ListController( ListController(
not_null<Controller*> controller, not_null<Controller*> controller,
@ -108,16 +111,30 @@ void ListController::loadMoreRows() {
return data.vchats().v; return data.vchats().v;
}); });
if (!chats.empty()) { if (!chats.empty()) {
auto add = std::vector<not_null<PeerData*>>();
auto allLoaded = _allLoaded;
auto preloadGroupId = _preloadGroupId;
const auto owner = &_user->owner();
const auto weak = base::make_weak(this);
for (const auto &chat : chats) { for (const auto &chat : chats) {
if (const auto peer = _user->owner().processChat(chat)) { if (const auto peer = owner->processChat(chat)) {
if (!peer->migrateTo()) { if (!peer->migrateTo()) {
delegate()->peerListAppendRow( add.push_back(peer);
createRow(peer));
} }
_preloadGroupId = peer->id; preloadGroupId = peer->id;
_allLoaded = false; allLoaded = false;
} }
} }
if (!weak) {
return;
}
for (const auto &peer : add) {
if (!delegate()->peerListFindRow(peer->id.value)) {
delegate()->peerListAppendRow(createRow(peer));
}
}
_preloadGroupId = preloadGroupId;
_allLoaded = allLoaded;
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
} }
auto fullCount = delegate()->peerListFullRowsCount(); auto fullCount = delegate()->peerListFullRowsCount();