From 3c8fd02d0745d535b1193f7f7e8d19bbdd89a488 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 12 Mar 2019 12:38:37 +0300 Subject: [PATCH] Add sanity checks for get_channel_participants results. GitOrigin-RevId: 3bc0ac414e7b6ca18631528ff069564ac9862409 --- td/telegram/ContactsManager.cpp | 41 ++++++++++++++++++++++--------- td/telegram/DialogParticipant.cpp | 26 ++++++++++++++++++++ td/telegram/DialogParticipant.h | 18 ++++++++++++++ 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 16ca953d..32e0272b 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -7433,20 +7433,32 @@ void ContactsManager::on_get_channel_participants_success( auto it = received_channel_participants_.find(random_id); CHECK(it != received_channel_participants_.end()); - it->second.first = total_count; - auto &result = it->second.second; CHECK(result.empty()); for (auto &participant_ptr : participants) { result.push_back(get_dialog_participant(channel_id, std::move(participant_ptr))); + if ((filter.is_bots() && !is_user_bot(result.back().user_id)) || + (filter.is_administrators() && !result.back().status.is_administrator()) || + ((filter.is_recent() || filter.is_search()) && !result.back().status.is_member()) || + (filter.is_restricted() && !result.back().status.is_restricted()) || + (filter.is_banned() && !result.back().status.is_banned())) { + LOG(ERROR) << "Receive " << result.back() << ", while searching for " << filter; + result.pop_back(); + total_count--; + } } + if (total_count < narrow_cast(result.size())) { + LOG(ERROR) << "Receive total_count = " << total_count << ", but have at least " << result.size() << " members in " + << channel_id; + total_count = static_cast(result.size()); + } + it->second.first = total_count; if (filter.is_recent() && total_count != 0 && total_count < 10000) { auto channel_full = get_channel_full(channel_id); if (channel_full != nullptr && channel_full->participant_count != total_count) { channel_full->participant_count = total_count; channel_full->is_changed = true; - update_channel_full(channel_full, channel_id); } auto c = get_channel(channel_id); if (c != nullptr && c->participant_count != total_count) { @@ -7455,16 +7467,23 @@ void ContactsManager::on_get_channel_participants_success( update_channel(c, channel_id); } } - if (offset == 0 && static_cast(participants.size()) < limit) { - if (filter.is_administrators() || filter.is_bots()) { - auto user_ids = transform(result, [](const DialogParticipant &participant) { return participant.user_id; }); - if (filter.is_administrators()) { - on_update_dialog_administrators(DialogId(channel_id), std::move(user_ids), true); - } else { - td_->messages_manager_->on_dialog_bots_updated(DialogId(channel_id), std::move(user_ids)); - } + int32 administrator_count = filter.is_administrators() ? total_count : -1; + if (offset == 0 && static_cast(participants.size()) < limit && + (filter.is_administrators() || filter.is_bots())) { + auto user_ids = transform(result, [](const DialogParticipant &participant) { return participant.user_id; }); + if (filter.is_administrators()) { + on_update_dialog_administrators(DialogId(channel_id), std::move(user_ids), true); + } + if (filter.is_bots()) { + td_->messages_manager_->on_dialog_bots_updated(DialogId(channel_id), std::move(user_ids)); } } + auto channel_full = get_channel_full(channel_id); + if (channel_full != nullptr && channel_full->administrator_count != administrator_count) { + channel_full->administrator_count = administrator_count; + channel_full->is_changed = true; + } + update_channel_full(channel_full, channel_id); } void ContactsManager::on_get_channel_participants_fail(ChannelId channel_id, ChannelParticipantsFilter filter, diff --git a/td/telegram/DialogParticipant.cpp b/td/telegram/DialogParticipant.cpp index bdfb3ed4..80aba99e 100644 --- a/td/telegram/DialogParticipant.cpp +++ b/td/telegram/DialogParticipant.cpp @@ -371,6 +371,12 @@ DialogParticipantStatus get_dialog_participant_status( can_send_games, can_use_inline_bots, can_add_web_page_previews); } +StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant) { + return string_builder << '[' << dialog_participant.user_id << " invited by " << dialog_participant.inviter_user_id + << " at " << dialog_participant.joined_date << " with status " << dialog_participant.status + << ']'; +} + tl_object_ptr ChannelParticipantsFilter::get_input_channel_participants_filter() const { switch (type) { @@ -425,6 +431,26 @@ ChannelParticipantsFilter::ChannelParticipantsFilter(const tl_object_ptr &filter) { if (filter == nullptr) { return DialogParticipantsFilter::Members; diff --git a/td/telegram/DialogParticipant.h b/td/telegram/DialogParticipant.h index c2e188fc..7a2de271 100644 --- a/td/telegram/DialogParticipant.h +++ b/td/telegram/DialogParticipant.h @@ -246,10 +246,14 @@ struct DialogParticipant { } }; +StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant); + class ChannelParticipantsFilter { enum class Type : int32 { Recent, Administrators, Search, Restricted, Banned, Bots } type; string query; + friend StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter); + public: explicit ChannelParticipantsFilter(const tl_object_ptr &filter); @@ -266,8 +270,22 @@ class ChannelParticipantsFilter { bool is_recent() const { return type == Type::Recent; } + + bool is_search() const { + return type == Type::Search; + } + + bool is_restricted() const { + return type == Type::Search; + } + + bool is_banned() const { + return type == Type::Search; + } }; +StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter); + enum class DialogParticipantsFilter : int32 { Administrators, Members, Restricted, Banned, Bots }; DialogParticipantsFilter get_dialog_participants_filter(const tl_object_ptr &filter);