Improve validness checks for UserId/ChatId/ChannelId.

This commit is contained in:
levlam 2021-09-14 17:09:40 +03:00
parent 1cb76f4c5a
commit 02ae56ae8a
7 changed files with 35 additions and 38 deletions

View File

@ -20,6 +20,9 @@ class ChannelId {
int64 id = 0;
public:
// the last (1 << 31) - 1 identifiers will be used for secret chat dialog identifiers
static constexpr int64 MAX_CHANNEL_ID = 1000000000000ll - (1ll << 31);
ChannelId() = default;
explicit ChannelId(int64 channel_id) : id(channel_id) {
@ -28,7 +31,7 @@ class ChannelId {
ChannelId(T channel_id) = delete;
bool is_valid() const {
return id > 0; // TODO better is_valid
return 0 < id && id < MAX_CHANNEL_ID;
}
int64 get() const {

View File

@ -20,6 +20,8 @@ class ChatId {
int64 id = 0;
public:
static constexpr int64 MAX_CHAT_ID = 999999999999ll;
ChatId() = default;
explicit ChatId(int64 chat_id) : id(chat_id) {
@ -28,7 +30,7 @@ class ChatId {
ChatId(T chat_id) = delete;
bool is_valid() const {
return id > 0;
return 0 < id && id <= MAX_CHAT_ID;
}
int64 get() const {

View File

@ -1467,7 +1467,8 @@ class ContactsManager final : public Actor {
static tl_object_ptr<td_api::SecretChatState> get_secret_chat_state_object(SecretChatState state);
static td_api::object_ptr<td_api::updateSecretChat> get_update_unknown_secret_chat_object(SecretChatId user_id);
static td_api::object_ptr<td_api::updateSecretChat> get_update_unknown_secret_chat_object(
SecretChatId secret_chat_id);
tl_object_ptr<td_api::secretChat> get_secret_chat_object(SecretChatId secret_chat_id, const SecretChat *secret_chat);

View File

@ -10,38 +10,31 @@
#include "td/utils/logging.h"
#include <limits>
namespace td {
bool DialogId::is_valid() const {
switch (get_type()) {
case DialogType::User:
return get_user_id().is_valid();
case DialogType::Chat:
return get_chat_id().is_valid();
case DialogType::Channel:
return get_channel_id().is_valid();
case DialogType::SecretChat:
return get_secret_chat_id().is_valid();
case DialogType::None:
return false;
default:
UNREACHABLE();
return false;
}
return get_type() != DialogType::None;
}
DialogType DialogId::get_type() const {
// check that valid ranges are continuous
static_assert(ZERO_CHANNEL_ID + 1 == -ChatId::MAX_CHAT_ID, "");
static_assert(
ZERO_SECRET_CHAT_ID + std::numeric_limits<int32>::max() + 1 == ZERO_CHANNEL_ID - ChannelId::MAX_CHANNEL_ID, "");
if (id < 0) {
if (MIN_CHAT_ID <= id) {
if (-ChatId::MAX_CHAT_ID <= id) {
return DialogType::Chat;
}
if (MIN_CHANNEL_ID <= id && id < MAX_CHANNEL_ID) {
if (ZERO_CHANNEL_ID - ChannelId::MAX_CHANNEL_ID <= id && id != ZERO_CHANNEL_ID) {
return DialogType::Channel;
}
if (MIN_SECRET_ID <= id && id < MAX_SECRET_ID) {
if (ZERO_SECRET_CHAT_ID + std::numeric_limits<int32>::min() <= id && id != ZERO_SECRET_CHAT_ID) {
return DialogType::SecretChat;
}
} else if (0 < id && id <= MAX_USER_ID) {
} else if (0 < id && id <= UserId::MAX_USER_ID) {
return DialogType::User;
}
return DialogType::None;
@ -59,12 +52,12 @@ ChatId DialogId::get_chat_id() const {
ChannelId DialogId::get_channel_id() const {
CHECK(get_type() == DialogType::Channel);
return ChannelId(MAX_CHANNEL_ID - id);
return ChannelId(ZERO_CHANNEL_ID - id);
}
SecretChatId DialogId::get_secret_chat_id() const {
CHECK(get_type() == DialogType::SecretChat);
return SecretChatId(static_cast<int32>(id - ZERO_SECRET_ID));
return SecretChatId(static_cast<int32>(id - ZERO_SECRET_CHAT_ID));
}
DialogId::DialogId(UserId user_id) {
@ -85,15 +78,15 @@ DialogId::DialogId(ChatId chat_id) {
DialogId::DialogId(ChannelId channel_id) {
if (channel_id.is_valid()) {
id = MAX_CHANNEL_ID - channel_id.get();
id = ZERO_CHANNEL_ID - channel_id.get();
} else {
id = 0;
}
}
DialogId::DialogId(SecretChatId chat_id) {
if (chat_id.is_valid()) {
id = ZERO_SECRET_ID + static_cast<int64>(chat_id.get());
DialogId::DialogId(SecretChatId secret_chat_id) {
if (secret_chat_id.is_valid()) {
id = ZERO_SECRET_CHAT_ID + static_cast<int64>(secret_chat_id.get());
} else {
id = 0;
}
@ -150,7 +143,7 @@ int64 DialogId::get_peer_id(const tl_object_ptr<telegram_api::Peer> &peer) {
return 0;
}
return MAX_CHANNEL_ID - channel_id.get();
return ZERO_CHANNEL_ID - channel_id.get();
}
default:
UNREACHABLE();

View File

@ -24,13 +24,8 @@ namespace td {
enum class DialogType : int32 { None, User, Chat, Channel, SecretChat };
class DialogId {
static constexpr int64 MIN_SECRET_ID = -2002147483648ll;
static constexpr int64 ZERO_SECRET_ID = -2000000000000ll;
static constexpr int64 MAX_SECRET_ID = -1997852516353ll;
static constexpr int64 MIN_CHANNEL_ID = -1997852516352ll;
static constexpr int64 MAX_CHANNEL_ID = -1000000000000ll;
static constexpr int64 MIN_CHAT_ID = -999999999999ll;
static constexpr int64 MAX_USER_ID = 999999999999ll;
static constexpr int64 ZERO_SECRET_CHAT_ID = -2000000000000ll;
static constexpr int64 ZERO_CHANNEL_ID = -1000000000000ll;
int64 id = 0;
@ -49,7 +44,7 @@ class DialogId {
explicit DialogId(UserId user_id);
explicit DialogId(ChatId chat_id);
explicit DialogId(ChannelId channel_id);
explicit DialogId(SecretChatId chat_id);
explicit DialogId(SecretChatId secret_chat_id);
int64 get() const {
return id;

View File

@ -34177,6 +34177,7 @@ void MessagesManager::force_create_dialog(DialogId dialog_id, const char *source
MessagesManager::Dialog *MessagesManager::add_dialog(DialogId dialog_id, const char *source) {
LOG(DEBUG) << "Creating " << dialog_id << " from " << source;
CHECK(!have_dialog(dialog_id));
LOG_CHECK(dialog_id.is_valid()) << source;
if (G()->parameters().use_message_db) {
// TODO preload dialog asynchronously, remove loading from this function

View File

@ -20,6 +20,8 @@ class UserId {
int64 id = 0;
public:
static constexpr int64 MAX_USER_ID = (1ll << 40) - 1;
UserId() = default;
explicit UserId(int64 user_id) : id(user_id) {
@ -46,7 +48,7 @@ class UserId {
}
bool is_valid() const {
return id > 0;
return 0 < id && id <= MAX_USER_ID;
}
int64 get() const {