Enforce a locked parameterized channel mode against param changes, not just removal
All checks were successful
CI / check (push) Successful in 5m19s

This commit is contained in:
Jean Chevronnet 2026-07-20 21:23:50 +00:00
parent 7fa7831390
commit b2f075ee00
No known key found for this signature in database
2 changed files with 13 additions and 1 deletions

View file

@ -707,7 +707,11 @@ impl ChannelInfo {
'+' => adding = true, '+' => adding = true,
'-' => adding = false, '-' => adding = false,
m if m.is_ascii_alphabetic() => { m if m.is_ascii_alphabetic() => {
if (m == 'r' || self.lock_on.contains(m)) && !adding && !readd.contains(m) { // A param mode (e.g. +f) is re-asserted whenever it's touched — set
// as well as unset — so changing its param is reverted to the locked
// one, not just re-added after a plain `-f`.
let param_locked = self.lock_params.iter().any(|(c, _)| *c == m);
if (m == 'r' || self.lock_on.contains(m)) && (!adding || param_locked) && !readd.contains(m) {
readd.push(m); readd.push(m);
} else if self.lock_off.contains(m) && adding && !reremove.contains(m) { } else if self.lock_off.contains(m) && adding && !reremove.contains(m) {
reremove.push(m); reremove.push(m);

View file

@ -764,6 +764,14 @@
assert_eq!(info.enforce("-r"), Some("+r".to_string())); // +r always locked assert_eq!(info.enforce("-r"), Some("+r".to_string())); // +r always locked
assert_eq!(info.enforce("+m"), None); // unrelated mode ignored assert_eq!(info.enforce("+m"), None); // unrelated mode ignored
// A param mode (+f): both a plain unset AND a changed param revert to the
// locked param — not just the unset case.
db.set_mlock_params("#chan", "ntf", "s", vec![('f', "kick:4:5s".to_string())]).unwrap();
let info = db.channel("#chan").unwrap();
assert_eq!(info.enforce("-f"), Some("+f kick:4:5s".to_string())); // unset re-added with param
assert_eq!(info.enforce("+f"), Some("+f kick:4:5s".to_string())); // changed param reverted
db.set_mlock("#chan", "nt", "s").unwrap(); // restore for the reopen check
drop(db); drop(db);
let db = Db::open(&p, "local"); let db = Db::open(&p, "local");
assert_eq!(db.channel("#chan").unwrap().lock_modes(), "+rnt-s", "survives reopen"); assert_eq!(db.channel("#chan").unwrap().lock_modes(), "+rnt-s", "survives reopen");