Fix crash in ChannelsLimitBox.

Fixes https://bugs.telegram.org/c/35214

Deleting `placeholder` in content->heightValue() resulted in `delete`
sometimes being called deep inside the layer->show() which already had
a reference to that `placeholder` saved and was accessed after -> crash.
This commit is contained in:
John Preston 2024-01-04 09:33:13 +04:00
parent c7f11eb05a
commit d2246337a2
1 changed files with 28 additions and 13 deletions

View File

@ -68,6 +68,8 @@ public:
void prepare() override; void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
[[nodiscard]] rpl::producer<int> countValue() const;
private: private:
void appendRow(not_null<PeerData*> peer, TimeId date); void appendRow(not_null<PeerData*> peer, TimeId date);
[[nodiscard]] std::unique_ptr<PeerListRow> createRow( [[nodiscard]] std::unique_ptr<PeerListRow> createRow(
@ -75,6 +77,7 @@ private:
TimeId date) const; TimeId date) const;
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
rpl::variable<int> _count;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
}; };
@ -91,12 +94,15 @@ public:
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
void rowRightActionClicked(not_null<PeerListRow*> row) override; void rowRightActionClicked(not_null<PeerListRow*> row) override;
[[nodiscard]] rpl::producer<int> countValue() const;
private: private:
void appendRow(not_null<PeerData*> peer); void appendRow(not_null<PeerData*> peer);
[[nodiscard]] std::unique_ptr<PeerListRow> createRow( [[nodiscard]] std::unique_ptr<PeerListRow> createRow(
not_null<PeerData*> peer) const; not_null<PeerData*> peer) const;
const not_null<Window::SessionNavigation*> _navigation; const not_null<Window::SessionNavigation*> _navigation;
rpl::variable<int> _count;
Fn<void()> _closeBox; Fn<void()> _closeBox;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
@ -210,17 +216,17 @@ void InactiveController::prepare() {
_requestId = _session->api().request(MTPchannels_GetInactiveChannels( _requestId = _session->api().request(MTPchannels_GetInactiveChannels(
)).done([=](const MTPmessages_InactiveChats &result) { )).done([=](const MTPmessages_InactiveChats &result) {
_requestId = 0; _requestId = 0;
result.match([&](const MTPDmessages_inactiveChats &data) { const auto &data = result.data();
_session->data().processUsers(data.vusers()); _session->data().processUsers(data.vusers());
const auto &list = data.vchats().v; const auto &list = data.vchats().v;
const auto &dates = data.vdates().v; const auto &dates = data.vdates().v;
for (auto i = 0, count = int(list.size()); i != count; ++i) { for (auto i = 0, count = int(list.size()); i != count; ++i) {
const auto peer = _session->data().processChat(list[i]); const auto peer = _session->data().processChat(list[i]);
const auto date = (i < dates.size()) ? dates[i].v : TimeId(); const auto date = (i < dates.size()) ? dates[i].v : TimeId();
appendRow(peer, date); appendRow(peer, date);
} }
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
}); _count = delegate()->peerListFullRowsCount();
}).send(); }).send();
} }
@ -228,6 +234,10 @@ void InactiveController::rowClicked(not_null<PeerListRow*> row) {
delegate()->peerListSetRowChecked(row, !row->checked()); delegate()->peerListSetRowChecked(row, !row->checked());
} }
rpl::producer<int> InactiveController::countValue() const {
return _count.value();
}
void InactiveController::appendRow( void InactiveController::appendRow(
not_null<PeerData*> participant, not_null<PeerData*> participant,
TimeId date) { TimeId date) {
@ -296,6 +306,10 @@ Main::Session &PublicsController::session() const {
return _navigation->session(); return _navigation->session();
} }
rpl::producer<int> PublicsController::countValue() const {
return _count.value();
}
void PublicsController::prepare() { void PublicsController::prepare() {
_requestId = _navigation->session().api().request( _requestId = _navigation->session().api().request(
MTPchannels_GetAdminedPublicChannels(MTP_flags(0)) MTPchannels_GetAdminedPublicChannels(MTP_flags(0))
@ -315,6 +329,7 @@ void PublicsController::prepare() {
} }
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
} }
_count = delegate()->peerListFullRowsCount();
}).send(); }).send();
} }
@ -571,7 +586,7 @@ void ChannelsLimitBox(
{}); {});
using namespace rpl::mappers; using namespace rpl::mappers;
content->heightValue( controller->countValue(
) | rpl::filter(_1 > 0) | rpl::start_with_next([=] { ) | rpl::filter(_1 > 0) | rpl::start_with_next([=] {
delete placeholder; delete placeholder;
}, placeholder->lifetime()); }, placeholder->lifetime());
@ -662,7 +677,7 @@ void PublicLinksLimitBox(
{}); {});
using namespace rpl::mappers; using namespace rpl::mappers;
content->heightValue( controller->countValue(
) | rpl::filter(_1 > 0) | rpl::start_with_next([=] { ) | rpl::filter(_1 > 0) | rpl::start_with_next([=] {
delete placeholder; delete placeholder;
}, placeholder->lifetime()); }, placeholder->lifetime());