Forget emptied channels so a stale key can't leak to a recreated name

This commit is contained in:
Jean Chevronnet 2026-07-19 17:45:04 +00:00
parent eea6e30f20
commit 0c85c5b569
No known key found for this signature in database

View file

@ -341,11 +341,16 @@ impl Network {
} }
self.users.remove(uid); self.users.remove(uid);
self.accounts.remove(uid); self.accounts.remove(uid);
for c in self.channels.values_mut() { // Drop the membership, and forget any channel it emptied — an emptied
// channel is destroyed by the ircd, so a lingering entry would both grow
// unbounded over the process lifetime and hand stale modes (e.g. a `+k`
// key) to whoever recreates the name later.
self.channels.retain(|_, c| {
c.members.remove(uid); c.members.remove(uid);
c.ops.remove(uid); c.ops.remove(uid);
c.voices.remove(uid); c.voices.remove(uid);
} !c.members.is_empty()
});
} }
pub fn nick_of(&self, uid: &str) -> Option<&str> { pub fn nick_of(&self, uid: &str) -> Option<&str> {
@ -389,10 +394,19 @@ impl Network {
// A user left a channel (part/kick): drop membership and record last-seen. // A user left a channel (part/kick): drop membership and record last-seen.
pub fn channel_part(&mut self, channel: &str, uid: &str) { pub fn channel_part(&mut self, channel: &str, uid: &str) {
if let Some(c) = self.channels.get_mut(&lc(channel)) { let key = lc(channel);
let emptied = if let Some(c) = self.channels.get_mut(&key) {
c.members.remove(uid); c.members.remove(uid);
c.ops.remove(uid); c.ops.remove(uid);
c.voices.remove(uid); c.voices.remove(uid);
c.members.is_empty()
} else {
false
};
// An emptied channel is gone on the ircd; drop it so a later channel of
// the same name can't inherit its stale modes (see user_quit).
if emptied {
self.channels.remove(&key);
} }
if let Some(nick) = self.nick_of(uid).map(str::to_string) { if let Some(nick) = self.nick_of(uid).map(str::to_string) {
self.record_seen(lc(&nick), Seen { nick, ts: now(), what: format!("leaving {channel}") }); self.record_seen(lc(&nick), Seen { nick, ts: now(), what: format!("leaving {channel}") });