fix(contacts): stricter path guard in pruneOrphanAvatar

Compare the file's parent path to the managed dir instead of a string prefix,
so a sibling dir like contact-avatars-x can't false-match. Our avatar copies
always live directly in the dir, so this is both correct and safer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 10:09:00 -05:00
parent 731d4e04ff
commit f8034b843a

View File

@@ -169,8 +169,9 @@ static void pruneOrphanAvatar(const std::string& oldAvatar, const data::AddressB
const std::string path = oldAvatar.substr(4); const std::string path = oldAvatar.substr(4);
fs::path managed = fs::weakly_canonical(fs::path(util::Platform::getConfigDir()) / "contact-avatars", ec); fs::path managed = fs::weakly_canonical(fs::path(util::Platform::getConfigDir()) / "contact-avatars", ec);
fs::path target = fs::weakly_canonical(fs::path(path), ec); fs::path target = fs::weakly_canonical(fs::path(path), ec);
// Only prune files actually inside the managed dir (guards against a hand-edited external path). // Only prune files sitting DIRECTLY in the managed dir (copyAvatarImage never nests) — a parent-path
if (managed.empty() || target.string().rfind(managed.string(), 0) != 0) return; // compare avoids string-prefix false matches (e.g. a sibling "contact-avatars-x") and path escapes.
if (managed.empty() || target.parent_path() != managed) return;
fs::remove(target, ec); fs::remove(target, ec);
invalidateAvatarTexture(path); invalidateAvatarTexture(path);
} }