Skip to content

Commit a4953e4

Browse files
authored
Refactor weight management in WeightStore to use checked arithmetic for safety. Replace debug assertions with runtime assertions to ensure invariants are maintained during weight updates. This change enhances error handling and prevents potential underflows in total weight calculations during insertions and removals. (#43)
1 parent c1b78c0 commit a4953e4

1 file changed

Lines changed: 13 additions & 8 deletions

File tree

src/store/weight.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,16 +501,17 @@ where
501501
pub fn try_insert(&mut self, key: K, value: Arc<V>) -> Result<Option<Arc<V>>, StoreFull> {
502502
let new_weight = self.compute_weight(value.as_ref());
503503
if let Some(entry) = self.map.get_mut(&key) {
504-
debug_assert!(
504+
assert!(
505505
self.total_weight >= entry.weight,
506506
"WeightStore invariant violated: total_weight ({}) is less than entry.weight ({})",
507507
self.total_weight,
508508
entry.weight
509509
);
510-
let next_total = self
510+
let base_total = self
511511
.total_weight
512-
.saturating_sub(entry.weight)
513-
.saturating_add(new_weight);
512+
.checked_sub(entry.weight)
513+
.expect("WeightStore invariant violated: checked_sub failed after invariant check");
514+
let next_total = base_total.checked_add(new_weight).ok_or(StoreFull)?;
514515
if next_total > self.capacity_weight {
515516
return Err(StoreFull);
516517
}
@@ -525,7 +526,8 @@ where
525526
if self.map.len() >= self.capacity_entries {
526527
return Err(StoreFull);
527528
}
528-
if self.total_weight + new_weight > self.capacity_weight {
529+
let next_total = self.total_weight.checked_add(new_weight).ok_or(StoreFull)?;
530+
if next_total > self.capacity_weight {
529531
return Err(StoreFull);
530532
}
531533

@@ -536,7 +538,7 @@ where
536538
weight: new_weight,
537539
},
538540
);
539-
self.total_weight += new_weight;
541+
self.total_weight = next_total;
540542
self.metrics.inc_insert();
541543
Ok(None)
542544
}
@@ -560,11 +562,14 @@ where
560562
/// ```
561563
pub fn remove(&mut self, key: &K) -> Option<Arc<V>> {
562564
let entry = self.map.remove(key)?;
563-
debug_assert!(
565+
assert!(
564566
self.total_weight >= entry.weight,
565567
"total_weight underflow in remove"
566568
);
567-
self.total_weight = self.total_weight.saturating_sub(entry.weight);
569+
self.total_weight = self
570+
.total_weight
571+
.checked_sub(entry.weight)
572+
.expect("WeightStore invariant violated: checked_sub failed after invariant check");
568573
self.metrics.inc_remove();
569574
Some(entry.value)
570575
}

0 commit comments

Comments
 (0)