From 8b327a3f2767b2c6ace24979c8cf3c8a61656e22 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 6 Oct 2026 12:46:32 +0200 Subject: [PATCH] Bound upload cache growth and reject stale transfer completions --- src/chat/chat_profile.c | 4 +++- tools/chatgui/src/avatars/avatarmanager.cpp | 9 ++++++++- tools/chatgui/tests/test_avatars.cpp | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/chat/chat_profile.c b/src/chat/chat_profile.c index 86f8c6c8..2ba19578 100644 --- a/src/chat/chat_profile.c +++ b/src/chat/chat_profile.c @@ -131,7 +131,9 @@ static int profile_update_channel(struct UTUN_INSTANCE* inst, const char* ch, in uint64_t local_uts = 0; struct profile_json profile = { .text = "{", .used = 1, .avatar = avatar }; - if (profile_pair(&profile, "name", inst->name) < 0) return -1; + if (profile_pair(&profile, "name", inst->name) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_CHAT, "profile: display name exceeds profile limit channel=%s", ch); return -1; + } { char q[256]; snprintf(q, sizeof(q), "SELECT update_ts,userinfo FROM \"%s\" WHERE node_id=?", tbl); sqlite3_stmt* ps = NULL; if (sqlite3_prepare_v2(cc->db, q, -1, &ps, NULL) == SQLITE_OK) { diff --git a/tools/chatgui/src/avatars/avatarmanager.cpp b/tools/chatgui/src/avatars/avatarmanager.cpp index 714ffc5a..6c51297a 100644 --- a/tools/chatgui/src/avatars/avatarmanager.cpp +++ b/tools/chatgui/src/avatars/avatarmanager.cpp @@ -185,8 +185,11 @@ void AvatarManager::uploadDefault(const QString& source, quint64 server) { if (!m_ready || m_preparing || !server || !gui_bridge_is_uasync_ready()) return; m_preparing = true; emit statusChanged(text("Preparing avatar…")); const QString directory = m_directory; const quint64 generation = ++m_generation; cancelUploads(); - m_pool.start(QRunnable::create([this, source, directory, server, generation] { + QStringList pinned; if (!m_defaultHash.isEmpty()) pinned << m_defaultHash; + for (const auto& job : m_jobs) if (job.upload) pinned << job.ref.hash; + m_pool.start(QRunnable::create([this, source, directory, server, generation, pinned] { const auto result = AvatarCache::prepare(source, directory); + if (!result.image.isNull()) { auto keep = pinned; keep << result.hash; AvatarCache::prune(directory, keep); } QMetaObject::invokeMethod(this, [this, result, server, generation] { m_preparing = false; if (generation != m_generation) return; @@ -314,6 +317,10 @@ void AvatarManager::onTransfer(const uint8_t* data, int length) { if (length != 51 || data[50] != 2) return; const quint64 id = mf_get64(data); if (!m_jobs.contains(id)) return; auto& job = m_jobs[id]; const int status = data[48] | (int(data[49]) << 8); + if (job.stage != 99 || job.ref.group != mf_get64(data + 8) || job.ref.server != mf_get64(data + 16) || + job.ref.owner != mf_get64(data + 24)) { + DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "avatar: stale or mismatched transfer completion id=%llu", (unsigned long long)id); return; + } if (status) { finish(id, status); return; } if (job.upload) { publish(job); return; } const Job snapshot = job; const QString directory = m_directory; job.stage = 101; diff --git a/tools/chatgui/tests/test_avatars.cpp b/tools/chatgui/tests/test_avatars.cpp index 6798f0e4..72b95fb5 100644 --- a/tools/chatgui/tests/test_avatars.cpp +++ b/tools/chatgui/tests/test_avatars.cpp @@ -13,6 +13,7 @@ extern "C" { #include "chat/chat_member.h" #include "chat/member_sync.h" #include "routing_layer/topo_group.h" +#include "routing_layer/topo_node_sqlite.h" #include "member_files/member_files.h" #include "json_flat.h" #include "mem.h"