shadowsocks/shadowsocks-rust · error
BloomFilter2
Error message
BloomFilter2
What it means
Identical to BloomFilter1 but for the second of the two rotating bloom filters in ppbloom's Self constructor. Bloom::new_for_fp_rate for the second filter failed (most commonly zero item capacity after item_count /= 2) and expect('BloomFilter2') panics.
Source
Thrown at crates/shadowsocks/src/security/replay/ppbloom.rs:51
bloom_count: [usize; 2],
item_count: usize,
current: usize,
}
impl PingPongBloom {
pub fn new(ty: ServerType) -> Self {
let (mut item_count, fp_p) = if ty.is_local() {
(BF_NUM_ENTRIES_FOR_CLIENT, BF_ERROR_RATE_FOR_CLIENT)
} else {
(BF_NUM_ENTRIES_FOR_SERVER, BF_ERROR_RATE_FOR_SERVER)
};
item_count /= 2;
Self {
blooms: [
Bloom::new_for_fp_rate(item_count, fp_p).expect("BloomFilter1"),
Bloom::new_for_fp_rate(item_count, fp_p).expect("BloomFilter2"),
],
bloom_count: [0, 0],
item_count,
current: 0,
}
}
// Check if data in `buf` exist.
//
// Set into the current bloom filter if not exist.
//
// Return `true` if data exist in bloom filter.
pub fn check_and_set(&mut self, buf: &[u8]) -> bool {
for bloom in &self.blooms {
if bloom.check(buf) {
return true;
}
}View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Ensure item_count is at least 2 before construction
- Guard capacity at the configuration layer (minimum allowed replay filter size)
- Replace expect with error propagation in a wrapper if dynamic capacities are unavoidable
- Update to a shadowsocks-rust version that validates capacity in the constructor
Example fix
// before
Ppbloom::with_capacity(0, FP_P)
// after
if capacity < 2 { capacity = 2; }
Ppbloom::with_capacity(capacity, FP_P) Defensive patterns
Strategy: validation
Validate before calling
let item_count = item_count.max(2); // both bloom filters now receive at least 1 item after the internal /= 2
Try / catch
// clamp before construction; do not attempt to catch this panic
let capacity = if capacity < 2 { 2 } else { capacity }; Prevention
- Apply the same capacity floor used for BloomFilter1 to all Ppbloom constructions
- Centralize Ppbloom construction behind a checked factory function
- Reject capacity=0/1 in CLI/config validation with a clear message
- Add regression tests for minimum-capacity construction
When it happens
Trigger: Public constructor Self::with_capacity with item_count 0 or 1, causing the second Bloom::new_for_fp_rate(item_count, fp_p) call to fail after the halving step.
Common situations: Zero/near-zero capacity settings flowing from server config; unit tests constructing Ppbloom with tiny capacities; capacity values reduced by earlier refactors without updating call sites.
Related errors
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/bea68ecb7d5315be.
Report an issue: GitHub.