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:
+9
-2
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user