diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 419cabdb5..3b3db6979 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -11164,7 +11164,11 @@ void MessagesManager::unload_dialog(DialogId dialog_id) { LOG(ERROR) << "Unknown dialog " << dialog_id; return; } - CHECK(d->has_unload_timeout); + + if (!d->has_unload_timeout) { + // possible right after the dialog was opened + return; + } if (!is_message_unload_enabled()) { // just in case @@ -14918,7 +14922,13 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector &&d, bool is_loaded_from_database) { auto dialog_id = d->dialog_id; + LOG_CHECK(is_inited_) << dialog_id << ' ' << is_loaded_from_database; switch (dialog_id.get_type()) { case DialogType::User: if (dialog_id == get_my_dialog_id() && d->last_read_inbox_message_id == MessageId::max() && @@ -34903,8 +34923,9 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen } auto folder_ptr = get_dialog_folder(d->folder_id); - LOG_CHECK(folder_ptr != nullptr) << dialog_id << ' ' << d->folder_id << ' ' << is_loaded_from_database << ' ' - << source; + LOG_CHECK(folder_ptr != nullptr) << is_inited_ << ' ' << G()->close_flag() << ' ' << dialog_id << ' ' << d->folder_id + << ' ' << is_loaded_from_database << ' ' << td_->auth_manager_->is_authorized() + << ' ' << td_->auth_manager_->was_authorized() << ' ' << source; auto &folder = *folder_ptr; if (old_date == new_date) { if (new_order == DEFAULT_ORDER) { diff --git a/tdutils/td/utils/port/FileFd.cpp b/tdutils/td/utils/port/FileFd.cpp index d5c0db9dc..8ee8c4a40 100644 --- a/tdutils/td/utils/port/FileFd.cpp +++ b/tdutils/td/utils/port/FileFd.cpp @@ -36,6 +36,8 @@ #include #include #include +#else +#include #endif #if TD_PORT_WINDOWS && defined(WIN32_LEAN_AND_MEAN) @@ -254,7 +256,9 @@ Result FileFd::write(Slice slice) { BOOL success = WriteFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_written, nullptr); #endif if (success) { - return narrow_cast(bytes_written); + auto result = narrow_cast(bytes_written); + CHECK(result <= slice.size()); + return result; } return OS_ERROR(PSLICE() << "Write to " << get_native_fd() << " has failed"); } @@ -266,14 +270,29 @@ Result FileFd::writev(Span slices) { auto bytes_written = detail::skip_eintr([&] { return ::writev(native_fd, slices.begin(), slices_size); }); bool success = bytes_written >= 0; if (success) { - return narrow_cast(bytes_written); + auto result = narrow_cast(bytes_written); + auto left = result; + for (const auto &slice : slices) { + if (left <= slice.iov_len) { + return result; + } + left -= slice.iov_len; + } + UNREACHABLE(); } return OS_ERROR(PSLICE() << "Writev to " << get_native_fd() << " has failed"); #else size_t res = 0; - for (auto slice : slices) { + for (const auto &slice : slices) { + if (slice.size() > std::numeric_limits::max() - res) { + break; + } TRY_RESULT(size, write(slice)); res += size; + if (size != slice.size()) { + CHECK(size < slice.size()); + break; + } } return res; #endif @@ -305,7 +324,9 @@ Result FileFd::read(MutableSlice slice) { if (is_eof) { get_poll_info().clear_flags(PollFlags::Read()); } - return static_cast(bytes_read); + auto result = narrow_cast(bytes_read); + CHECK(result <= slice.size()); + return result; } return OS_ERROR(PSLICE() << "Read from " << get_native_fd() << " has failed"); } @@ -329,7 +350,9 @@ Result FileFd::pwrite(Slice slice, int64 offset) { BOOL success = WriteFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_written, &overlapped); #endif if (success) { - return narrow_cast(bytes_written); + auto result = narrow_cast(bytes_written); + CHECK(result <= slice.size()); + return result; } return OS_ERROR(PSLICE() << "Pwrite to " << get_native_fd() << " at offset " << offset << " has failed"); } @@ -352,7 +375,9 @@ Result FileFd::pread(MutableSlice slice, int64 offset) const { BOOL success = ReadFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_read, &overlapped); #endif if (success) { - return narrow_cast(bytes_read); + auto result = narrow_cast(bytes_read); + CHECK(result <= slice.size()); + return result; } return OS_ERROR(PSLICE() << "Pread from " << get_native_fd() << " at offset " << offset << " has failed"); } diff --git a/tdutils/td/utils/port/FromApp.h b/tdutils/td/utils/port/FromApp.h index bab7324a8..71cdfb9bb 100644 --- a/tdutils/td/utils/port/FromApp.h +++ b/tdutils/td/utils/port/FromApp.h @@ -76,11 +76,15 @@ inline BOOL DeleteFileFromAppW(_In_ LPCWSTR lpFileName) { } inline BOOL MoveFileExFromAppW(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) { - auto func = get_from_app_function<4>("MoveFileFromAppW", &MoveFileEx); - if (func != &MoveFileEx && (dwFlags & MOVEFILE_REPLACE_EXISTING) != 0) { + auto func = get_from_app_function<4>("MoveFileFromAppW", &MoveFile); + if (func == &MoveFile || (dwFlags & ~MOVEFILE_REPLACE_EXISTING) != 0) { + // if can't find MoveFileFromAppW or have unsupported flags, call MoveFileEx directly + return MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags); + } + if ((dwFlags & MOVEFILE_REPLACE_EXISTING) != 0) { td::DeleteFileFromAppW(lpNewFileName); } - return func(lpExistingFileName, lpNewFileName, dwFlags); + return func(lpExistingFileName, lpNewFileName); } inline HANDLE FindFirstFileExFromAppW(_In_ LPCWSTR lpFileName, _In_ FINDEX_INFO_LEVELS fInfoLevelId, diff --git a/tdutils/td/utils/port/IoSlice.h b/tdutils/td/utils/port/IoSlice.h index f1d356dd1..47fa230d8 100644 --- a/tdutils/td/utils/port/IoSlice.h +++ b/tdutils/td/utils/port/IoSlice.h @@ -25,7 +25,7 @@ inline IoSlice as_io_slice(Slice slice) { return res; } -inline Slice as_slice(const IoSlice io_slice) { +inline Slice as_slice(const IoSlice &io_slice) { return Slice(static_cast(io_slice.iov_base), io_slice.iov_len); } diff --git a/tdutils/td/utils/port/SocketFd.cpp b/tdutils/td/utils/port/SocketFd.cpp index 05e6aee4b..83d418a0c 100644 --- a/tdutils/td/utils/port/SocketFd.cpp +++ b/tdutils/td/utils/port/SocketFd.cpp @@ -18,6 +18,8 @@ #include "td/utils/port/detail/Iocp.h" #include "td/utils/SpinLock.h" #include "td/utils/VectorQueue.h" + +#include #endif #if TD_PORT_POSIX @@ -98,7 +100,9 @@ class SocketFdImpl : private Iocp::Callback { Result writev(Span slices) { size_t total_size = 0; for (auto io_slice : slices) { - total_size += as_slice(io_slice).size(); + auto size = as_slice(io_slice).size(); + CHECK(size <= std::numeric_limits::max() - total_size); + total_size += size; } auto left_size = total_size; @@ -399,7 +403,19 @@ class SocketFdImpl { return ::writev(native_fd, slices.begin(), slices_size); #endif }); - return write_finish(write_res); + if (write_res >= 0) { + auto result = narrow_cast(write_res); + auto left = result; + for (const auto &slice : slices) { + if (left <= slice.iov_len) { + return result; + } + left -= slice.iov_len; + } + LOG(FATAL) << "Receive " << result << " as writev response, but tried to write only " << result - left + << " bytes"; + } + return write_finish(); } Result write(Slice slice) { @@ -412,15 +428,17 @@ class SocketFdImpl { ::write(native_fd, slice.begin(), slice.size()); #endif }); - return write_finish(write_res); + if (write_res >= 0) { + auto result = narrow_cast(write_res); + LOG_CHECK(result <= slice.size()) << "Receive " << result << " as write response, but tried to write only " + << slice.size() << " bytes"; + return result; + } + return write_finish(); } - Result write_finish(ssize_t write_res) { + Result write_finish() { auto write_errno = errno; - if (write_res >= 0) { - return narrow_cast(write_res); - } - if (write_errno == EAGAIN #if EAGAIN != EWOULDBLOCK || write_errno == EWOULDBLOCK @@ -468,7 +486,9 @@ class SocketFdImpl { get_poll_info().clear_flags(PollFlags::Read()); get_poll_info().add_flags(PollFlags::Close()); } - return narrow_cast(read_res); + auto result = narrow_cast(read_res); + CHECK(result <= slice.size()); + return result; } if (read_errno == EAGAIN #if EAGAIN != EWOULDBLOCK