Fix: TOCTOU in remove_pair() bei nebenläufigem Schreiber

Die "vorher"-Länge wurde über einen separaten, vorgelagerten load()
ermittelt statt innerhalb desselben atomaren modify()-Aufrufs -
zwischen beiden Aufrufen konnte ein nebenläufiger Schreiber die
Paarliste ändern, was zu einem falschen PairNotFound trotz
erfolgreichem Entfernen führen konnte. Der Vorher/Nachher-Vergleich
läuft jetzt vollständig innerhalb des modify()-Closures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjyzpGWECyKSBWz5DtkTGz
This commit is contained in:
2026-09-15 23:06:20 +02:00
co-authored by Claude Sonnet 5
parent 2b3514ab66
commit d4d80be1bf
+9 -2
View File
@@ -31,11 +31,18 @@ pub fn update_pair(pair: DrivePair) -> Result<AppConfig> {
/// Entfernt ein Laufwerkspaar per ID. /// Entfernt ein Laufwerkspaar per ID.
pub fn remove_pair(id: &str) -> Result<AppConfig> { pub fn remove_pair(id: &str) -> Result<AppConfig> {
let before_len = load()?.pairs.len(); // Die "vorher"-Länge wird INNERHALB desselben `modify`-Aufrufs (auf der bereits frisch
// geladenen `cfg`) ermittelt statt über einen separaten, vorgelagerten `load()`-Aufruf:
// zwischen zwei getrennten Aufrufen könnte ein nebenläufiger Schreiber die Paarliste
// ändern, was hier sonst zu einem falschen `PairNotFound` trotz erfolgreichem Entfernen
// (oder umgekehrt) führen könnte.
let removed = std::cell::Cell::new(false);
let updated = config_ctdra::modify::<AppConfig, _>(|cfg| { let updated = config_ctdra::modify::<AppConfig, _>(|cfg| {
let before_len = cfg.pairs.len();
cfg.pairs.retain(|p| p.id != id); cfg.pairs.retain(|p| p.id != id);
removed.set(cfg.pairs.len() != before_len);
})?; })?;
if updated.pairs.len() == before_len { if !removed.get() {
return Err(Error::PairNotFound(id.to_string())); return Err(Error::PairNotFound(id.to_string()));
} }
Ok(updated) Ok(updated)