fix(A.3 #25): guard sample_index_for_seconds against NaN and infinity
Review feedback (MINOR): the original <= 0.0 clamp caught negatives and zero but not non-finite inputs. Rust's saturating float-to-int cast turns f64::INFINITY into u64::MAX, which would park the capture buffer origin beyond any reachable sample index and trim the whole buffer forever if a future end_secs source ever produces infinity (clock glitch, overflow upstream, corrupted timestamp in a pass). Adds is_finite() check. NaN, +infinity, -infinity, and zero all return 0, which downstream trim_buffer_to_commit_point treats as no-op. Test covers all three non-finite cases.
This commit is contained in:
@@ -14,8 +14,14 @@
|
||||
/// Absolute sample index at the end of the given session-relative
|
||||
/// seconds mark, rounded to the nearest sample. `end_secs` typically
|
||||
/// comes from `LocalAgreement::last_committed_end_secs()`.
|
||||
///
|
||||
/// Guards against non-finite inputs: NaN and ±infinity both return 0
|
||||
/// ("nothing committed yet"). Without this, Rust's saturating
|
||||
/// float-to-int cast turns `f64::INFINITY` into `u64::MAX`, which
|
||||
/// would park the capture buffer origin at an index beyond any
|
||||
/// reachable sample and trim the entire buffer forever.
|
||||
pub fn sample_index_for_seconds(end_secs: f64, sample_rate: u32) -> u64 {
|
||||
if end_secs <= 0.0 {
|
||||
if !end_secs.is_finite() || end_secs <= 0.0 {
|
||||
return 0;
|
||||
}
|
||||
(end_secs * sample_rate as f64).round() as u64
|
||||
@@ -65,6 +71,17 @@ mod tests {
|
||||
assert_eq!(sample_index_for_seconds(-1.0, 16_000), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_index_for_seconds_rejects_nan_and_infinity() {
|
||||
// Defensive against non-finite inputs: without the is_finite()
|
||||
// check, Rust's saturating float-to-int cast makes +infinity
|
||||
// become u64::MAX, which would park the buffer origin beyond
|
||||
// reach and trim the whole buffer forever.
|
||||
assert_eq!(sample_index_for_seconds(f64::NAN, 16_000), 0);
|
||||
assert_eq!(sample_index_for_seconds(f64::INFINITY, 16_000), 0);
|
||||
assert_eq!(sample_index_for_seconds(f64::NEG_INFINITY, 16_000), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_index_for_seconds_rounds_nearest() {
|
||||
// 0.5 s at 16 kHz = 8000 samples exactly.
|
||||
|
||||
Reference in New Issue
Block a user