fix: harden io-core and concurrency boundaries against panics (#4503)

fix(io-core,concurrency): harden boundary validation and arithmetic against panics (backlog#1024)
This commit is contained in:
Zhengchao An
2026-07-09 00:15:36 +08:00
committed by GitHub
parent 6cb47049e8
commit 20447422cf
7 changed files with 176 additions and 28 deletions
+28 -1
View File
@@ -223,7 +223,18 @@ impl BackpressureMonitor {
/// Release a slot after operation completes.
pub fn release(&self) {
let prev = self.current.fetch_sub(1, Ordering::Relaxed);
// Guard against underflow: an unpaired release at 0 must not wrap to
// usize::MAX, which would permanently reject all future acquisitions.
let prev = match self
.current
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| current.checked_sub(1))
{
Ok(prev) => prev,
Err(_) => {
tracing::warn!("BackpressureMonitor::release called with no outstanding acquisition; ignoring");
0
}
};
let low_threshold = self.config.low_threshold();
// Update state if needed
@@ -362,6 +373,22 @@ mod tests {
assert_eq!(monitor.state(), BackpressureState::Normal);
}
#[test]
fn test_release_underflow_stays_at_zero() {
// An unpaired release at current==0 must not wrap to usize::MAX,
// which would make try_acquire reject everything forever.
let monitor = BackpressureMonitor::with_defaults();
monitor.release();
assert_eq!(monitor.current(), 0);
// The monitor must still be usable.
assert!(monitor.try_acquire());
assert_eq!(monitor.current(), 1);
monitor.release();
assert_eq!(monitor.current(), 0);
}
#[test]
fn test_rejection_rate() {
let config = BackpressureConfig {