diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 116444d93..d9d176232 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3680,7 +3680,7 @@ networkStatistics since_date:int32 entries:vector = Netw //@preload_large_videos True, if the beginning of video files needs to be preloaded for instant playback //@preload_next_audio True, if the next audio track needs to be preloaded while the user is listening to an audio file //@use_less_data_for_calls True, if "use less data for calls" option needs to be enabled -autoDownloadSettings is_auto_download_enabled:Bool max_photo_file_size:int32 max_video_file_size:int32 max_other_file_size:int32 video_upload_bitrate:int32 preload_large_videos:Bool preload_next_audio:Bool use_less_data_for_calls:Bool = AutoDownloadSettings; +autoDownloadSettings is_auto_download_enabled:Bool max_photo_file_size:int32 max_video_file_size:int53 max_other_file_size:int53 video_upload_bitrate:int32 preload_large_videos:Bool preload_next_audio:Bool use_less_data_for_calls:Bool = AutoDownloadSettings; //@description Contains auto-download settings presets for the current user //@low Preset with lowest settings; supposed to be used by default when roaming diff --git a/td/telegram/AutoDownloadSettings.cpp b/td/telegram/AutoDownloadSettings.cpp index 444980a7e..c462701ca 100644 --- a/td/telegram/AutoDownloadSettings.cpp +++ b/td/telegram/AutoDownloadSettings.cpp @@ -25,9 +25,13 @@ static td_api::object_ptr convert_auto_download_se auto video_preload_large = (flags & telegram_api::autoDownloadSettings::VIDEO_PRELOAD_LARGE_MASK) != 0; auto audio_preload_next = (flags & telegram_api::autoDownloadSettings::AUDIO_PRELOAD_NEXT_MASK) != 0; auto phonecalls_less_data = (flags & telegram_api::autoDownloadSettings::PHONECALLS_LESS_DATA_MASK) != 0; + constexpr int32 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */; + constexpr int64 MAX_DOCUMENT_SIZE = (1ll << 52); return td_api::make_object( - !disabled, settings->photo_size_max_, settings->video_size_max_, settings->file_size_max_, - settings->video_upload_maxbitrate_, video_preload_large, audio_preload_next, phonecalls_less_data); + !disabled, clamp(settings->photo_size_max_, static_cast(0), MAX_PHOTO_SIZE), + clamp(settings->video_size_max_, static_cast(0), MAX_DOCUMENT_SIZE), + clamp(settings->file_size_max_, static_cast(0), MAX_DOCUMENT_SIZE), settings->video_upload_maxbitrate_, + video_preload_large, audio_preload_next, phonecalls_less_data); } class GetAutoDownloadSettingsQuery final : public Td::ResultHandler { diff --git a/td/telegram/AutoDownloadSettings.h b/td/telegram/AutoDownloadSettings.h index 5cc92c6b5..9efce1ffe 100644 --- a/td/telegram/AutoDownloadSettings.h +++ b/td/telegram/AutoDownloadSettings.h @@ -20,8 +20,8 @@ class Td; class AutoDownloadSettings { public: int32 max_photo_file_size = 0; - int32 max_video_file_size = 0; - int32 max_other_file_size = 0; + int64 max_video_file_size = 0; + int64 max_other_file_size = 0; int32 video_upload_bitrate = 0; bool is_enabled = false; bool preload_large_videos = false; diff --git a/td/telegram/DocumentsManager.cpp b/td/telegram/DocumentsManager.cpp index 8f635c485..4df6e9898 100644 --- a/td/telegram/DocumentsManager.cpp +++ b/td/telegram/DocumentsManager.cpp @@ -238,7 +238,7 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo int64 id; int64 access_hash; int32 dc_id; - int32 size; + int64 size; int32 date = 0; string mime_type; string file_reference; diff --git a/td/telegram/EncryptedFile.h b/td/telegram/EncryptedFile.h index 880933d89..83b433679 100644 --- a/td/telegram/EncryptedFile.h +++ b/td/telegram/EncryptedFile.h @@ -16,16 +16,16 @@ namespace td { struct EncryptedFile { - static constexpr int32 MAGIC = 0x473d738a; int64 id_ = 0; int64 access_hash_ = 0; - int32 size_ = 0; + int64 size_ = 0; int32 dc_id_ = 0; int32 key_fingerprint_ = 0; EncryptedFile() = default; - EncryptedFile(int64 id, int64 access_hash, int32 size, int32 dc_id, int32 key_fingerprint) + EncryptedFile(int64 id, int64 access_hash, int64 size, int32 dc_id, int32 key_fingerprint) : id_(id), access_hash_(access_hash), size_(size), dc_id_(dc_id), key_fingerprint_(key_fingerprint) { + CHECK(size_ >= 0); } static unique_ptr get_encrypted_file(tl_object_ptr file_ptr) { @@ -33,17 +33,26 @@ struct EncryptedFile { return nullptr; } auto file = move_tl_object_as(file_ptr); - return make_unique(file->id_, file->access_hash_, static_cast(file->size_), file->dc_id_, - file->key_fingerprint_); + if (file->size_ < 0) { + return nullptr; + } + return make_unique(file->id_, file->access_hash_, file->size_, file->dc_id_, file->key_fingerprint_); } template void store(StorerT &storer) const { using td::store; - store(MAGIC, storer); + bool has_64bit_size = (size_ >= (1ll << 31)); + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_64bit_size); + END_STORE_FLAGS(); store(id_, storer); store(access_hash_, storer); - store(size_, storer); + if (has_64bit_size) { + store(size_, storer); + } else { + store(narrow_cast(size_), storer); + } store(dc_id_, storer); store(key_fingerprint_, storer); } @@ -51,18 +60,25 @@ struct EncryptedFile { template void parse(ParserT &parser) { using td::parse; - int32 got_magic; - - parse(got_magic, parser); + bool has_64bit_size; + BEGIN_PARSE_FLAGS(); + constexpr int32 OLD_MAGIC = 0x473d738a; + if (flags_parse == OLD_MAGIC) { + flags_parse = 0; + } + PARSE_FLAG(has_64bit_size); + END_PARSE_FLAGS(); parse(id_, parser); parse(access_hash_, parser); - parse(size_, parser); + if (has_64bit_size) { + parse(size_, parser); + } else { + int32 int_size; + parse(int_size, parser); + size_ = int_size; + } parse(dc_id_, parser); parse(key_fingerprint_, parser); - - if (got_magic != MAGIC) { - parser.set_error("EncryptedFile magic mismatch"); - } } }; diff --git a/td/telegram/PhotoSize.cpp b/td/telegram/PhotoSize.cpp index 14b0acc9e..68549e68a 100644 --- a/td/telegram/PhotoSize.cpp +++ b/td/telegram/PhotoSize.cpp @@ -243,6 +243,10 @@ Variant get_photo_size(FileManager *file_manager, PhotoSizeSo if (source.get_type("get_photo_size") == PhotoSizeSource::Type::Thumbnail) { source.thumbnail().thumbnail_type = res.type; } + if (res.size < 0 || res.size > 1000000000) { + LOG(ERROR) << "Receive photo of size " << res.size; + res.size = 0; + } res.file_id = register_photo_size(file_manager, source, id, access_hash, std::move(file_reference), owner_dialog_id, res.size, dc_id, format); @@ -276,6 +280,10 @@ AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource sour if (source.get_type("get_animation_size") == PhotoSizeSource::Type::Thumbnail) { source.thumbnail().thumbnail_type = res.type; } + if (res.size < 0 || res.size > 1000000000) { + LOG(ERROR) << "Receive animation of size " << res.size; + res.size = 0; + } res.file_id = register_photo_size(file_manager, source, id, access_hash, std::move(file_reference), owner_dialog_id, res.size, dc_id, PhotoFormat::Mpeg4); @@ -302,9 +310,9 @@ PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_t } auto http_url = r_http_url.move_as_ok(); auto url = http_url.get_url(); - file_id = file_manager->register_remote(FullRemoteFileLocation(file_type, url, web_document->access_hash_), - FileLocationSource::FromServer, owner_dialog_id, 0, web_document->size_, - get_url_query_file_name(http_url.query_)); + file_id = file_manager->register_remote( + FullRemoteFileLocation(file_type, url, web_document->access_hash_), FileLocationSource::FromServer, + owner_dialog_id, 0, static_cast(web_document->size_), get_url_query_file_name(http_url.query_)); size = web_document->size_; mime_type = std::move(web_document->mime_type_); attributes = std::move(web_document->attributes_); @@ -363,6 +371,11 @@ PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_t s.dimensions = dimensions; s.size = size; s.file_id = file_id; + + if (s.size < 0 || s.size > 1000000000) { + LOG(ERROR) << "Receive web photo of size " << s.size; + s.size = 0; + } return s; } diff --git a/td/telegram/files/FileDownloader.cpp b/td/telegram/files/FileDownloader.cpp index bc701dbba..1c04b43f9 100644 --- a/td/telegram/files/FileDownloader.cpp +++ b/td/telegram/files/FileDownloader.cpp @@ -247,26 +247,25 @@ Result> FileDownloader::start_part(Part part, int32 #endif DcId dc_id = remote_.is_web() ? G()->get_webfile_dc_id() : remote_.get_dc_id(); auto id = UniqueId::next(UniqueId::Type::Default, static_cast(QueryType::Default)); - net_query = remote_.is_web() - ? G()->net_query_creator().create( - id, - telegram_api::upload_getWebFile(remote_.as_input_web_file_location(), - static_cast(part.offset), static_cast(size)), - {}, dc_id, net_query_type, NetQuery::AuthFlag::On) - : G()->net_query_creator().create( - id, - telegram_api::upload_getFile(flags, false /*ignored*/, false /*ignored*/, - remote_.as_input_file_location(), - static_cast(part.offset), static_cast(size)), - {}, dc_id, net_query_type, NetQuery::AuthFlag::On); + net_query = + remote_.is_web() + ? G()->net_query_creator().create( + id, + telegram_api::upload_getWebFile(remote_.as_input_web_file_location(), static_cast(part.offset), + static_cast(size)), + {}, dc_id, net_query_type, NetQuery::AuthFlag::On) + : G()->net_query_creator().create( + id, + telegram_api::upload_getFile(flags, false /*ignored*/, false /*ignored*/, + remote_.as_input_file_location(), part.offset, static_cast(size)), + {}, dc_id, net_query_type, NetQuery::AuthFlag::On); } else { if (remote_.is_web()) { return Status::Error("Can't download web file from CDN"); } auto it = cdn_part_reupload_token_.find(part.id); if (it == cdn_part_reupload_token_.end()) { - auto query = telegram_api::upload_getCdnFile(BufferSlice(cdn_file_token_), static_cast(part.offset), - static_cast(size)); + auto query = telegram_api::upload_getCdnFile(BufferSlice(cdn_file_token_), part.offset, narrow_cast(size)); cdn_part_file_token_generation_[part.id] = cdn_file_token_generation_; LOG(DEBUG) << part.id << " " << to_string(query); net_query = @@ -313,7 +312,7 @@ Result FileDownloader::process_part(Part part, NetQueryPtr net_query) { TRY_RESULT(file_base, fetch_result(net_query->ok())); CHECK(file_base->get_id() == telegram_api::upload_file::ID); auto file = move_tl_object_as(file_base); - LOG(DEBUG) << part.id << " upload_getFile result " << to_string(file); + LOG(DEBUG) << part.id << " upload.getFile result " << to_string(file); bytes = std::move(file->bytes_); } break; @@ -322,7 +321,7 @@ Result FileDownloader::process_part(Part part, NetQueryPtr net_query) { TRY_RESULT(file_base, fetch_result(net_query->ok())); CHECK(file_base->get_id() == telegram_api::upload_cdnFile::ID); auto file = move_tl_object_as(file_base); - LOG(DEBUG) << part.id << " upload_getCdnFile result " << to_string(file); + LOG(DEBUG) << part.id << " upload.getCdnFile result " << to_string(file); bytes = std::move(file->bytes_); need_cdn_decrypt = true; break; @@ -412,7 +411,7 @@ FileLoader::Callback *FileDownloader::get_callback() { Status FileDownloader::process_check_query(NetQueryPtr net_query) { has_hash_query_ = false; TRY_STATUS(check_net_query(net_query)); - TRY_RESULT(file_hashes, fetch_result(std::move(net_query))); + TRY_RESULT(file_hashes, fetch_result(std::move(net_query))); add_hash_info(file_hashes); return Status::OK(); } @@ -467,8 +466,7 @@ Result FileDownloader::check_loop(int64 checked_prefix_si } if (!has_hash_query_) { has_hash_query_ = true; - auto query = - telegram_api::upload_getFileHashes(remote_.as_input_file_location(), narrow_cast(checked_prefix_size)); + auto query = telegram_api::upload_getFileHashes(remote_.as_input_file_location(), checked_prefix_size); auto net_query_type = is_small_ ? NetQuery::Type::DownloadSmall : NetQuery::Type::Download; auto net_query = G()->net_query_creator().create(query, {}, remote_.get_dc_id(), net_query_type); info.queries.push_back(std::move(net_query)); diff --git a/td/telegram/files/FileHashUploader.cpp b/td/telegram/files/FileHashUploader.cpp index f2f7ff606..75427bbbb 100644 --- a/td/telegram/files/FileHashUploader.cpp +++ b/td/telegram/files/FileHashUploader.cpp @@ -66,12 +66,11 @@ Status FileHashUploader::loop_impl() { TRY_STATUS(loop_sha()); } if (state_ == State::NetRequest) { - // messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document; + // messages.getDocumentByHash#338e2464 sha256:bytes size:long mime_type:string = Document; auto hash = BufferSlice(32); sha256_state_.extract(hash.as_slice(), true); auto mime_type = MimeType::from_extension(PathView(local_.path_).extension(), "image/gif"); - auto query = - telegram_api::messages_getDocumentByHash(std::move(hash), static_cast(size_), std::move(mime_type)); + auto query = telegram_api::messages_getDocumentByHash(std::move(hash), size_, std::move(mime_type)); LOG(INFO) << "Send getDocumentByHash request: " << to_string(query); auto ptr = G()->net_query_creator().create(query); G()->net_query_dispatcher().dispatch_with_callback(std::move(ptr), actor_shared(this)); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 426086f6e..52dd4120d 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -1226,6 +1226,15 @@ Result FileManager::register_file(FileData &&data, FileLocationSource fi return Status::Error(400, "No location"); } + if (data.size_ < 0) { + LOG(ERROR) << "Receive file of size " << data.size_; + data.size_ = 0; + } + if (data.expected_size_ < 0) { + LOG(ERROR) << "Receive file of expected size " << data.expected_size_; + data.expected_size_ = 0; + } + FileId file_id = next_file_id(); LOG(INFO) << "Register file data " << data << " as " << file_id << " from " << source;