Skip to content

Commit f259379

Browse files
authored
sample_builder: fix panic on timestamp wrap (#735)
* sample_builder: fix panic on timestamp wrap * remove unsafe usage * fix unintentional typo
1 parent 4da5280 commit f259379

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

media/src/io/sample_builder/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<T: Depacketizer> SampleBuilder<T> {
111111
return false;
112112
}
113113

114-
found_tail.unwrap() - found_head.unwrap() > self.max_late_timestamp
114+
found_tail.unwrap().wrapping_sub(found_head.unwrap()) > self.max_late_timestamp
115115
}
116116

117117
/// Returns the timestamp associated with a given sample location
@@ -341,7 +341,7 @@ impl<T: Depacketizer> SampleBuilder<T> {
341341
data.extend_from_slice(&p);
342342
i = i.wrapping_add(1);
343343
}
344-
let samples = after_timestamp - sample_timestamp;
344+
let samples = after_timestamp.wrapping_sub(sample_timestamp);
345345

346346
let sample = Sample {
347347
data: Bytes::copy_from_slice(&data),

media/src/io/sample_builder/sample_builder_test.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,79 @@ fn test_pop_with_timestamp() {
14731473
assert_eq!(s.pop_with_timestamp(), None);
14741474
}
14751475

1476+
#[test]
1477+
fn test_too_old_timestamp_wrapping() {
1478+
// Create a SampleBuilder with 1ms max late duration (sample rate 48000 = 48 samples per 1ms)
1479+
let mut s = SampleBuilder::new(10, FakeDepacketizer::new(), 48000)
1480+
.with_max_time_delay(Duration::from_millis(1));
1481+
1482+
// Push packet with very high timestamp that would wrap around
1483+
s.push(Packet {
1484+
header: Header {
1485+
sequence_number: 1,
1486+
timestamp: u32::MAX - 10, // Very high timestamp
1487+
marker: false,
1488+
..Default::default()
1489+
},
1490+
payload: bytes!(0x01),
1491+
});
1492+
1493+
// Push packet with wrapped timestamp, too_old will say true and we would get a sample with above packet
1494+
s.push(Packet {
1495+
header: Header {
1496+
sequence_number: 2,
1497+
timestamp: 38, // Very low timestamp but the ts diff will be > 48
1498+
marker: false,
1499+
..Default::default()
1500+
},
1501+
payload: bytes!(0x02),
1502+
});
1503+
1504+
// This test would panic with "attempt to subtract with overflow" if wrapping_sub wasn't used
1505+
// The difference between timestamps should wrap around properly
1506+
assert!(
1507+
s.prepared.count() > 0, // due to ts diff 49 > 48 it will say that an old sample is done
1508+
"Expected packets to be considered too old event with timestamp wrapping"
1509+
);
1510+
}
1511+
1512+
#[test]
1513+
fn test_too_old_ok_timestamp_wrapping() {
1514+
// Create a SampleBuilder with 1ms max late duration (sample rate 48000 = 48 samples per 1ms)
1515+
let mut s = SampleBuilder::new(10, FakeDepacketizer::new(), 48000)
1516+
.with_max_time_delay(Duration::from_millis(1));
1517+
1518+
// Push packet with very high timestamp that would wrap around
1519+
s.push(Packet {
1520+
header: Header {
1521+
sequence_number: 1,
1522+
timestamp: u32::MAX - 10, // Very high timestamp
1523+
marker: false,
1524+
..Default::default()
1525+
},
1526+
payload: bytes!(0x01),
1527+
});
1528+
1529+
// Push packet with low timestamp
1530+
s.push(Packet {
1531+
header: Header {
1532+
sequence_number: 2,
1533+
timestamp: 10, // Very low timestamp
1534+
marker: false,
1535+
..Default::default()
1536+
},
1537+
payload: bytes!(0x02),
1538+
});
1539+
1540+
// This test would panic with "attempt to subtract with overflow" if wrapping_sub wasn't used
1541+
// The difference between timestamps should wrap around properly
1542+
assert!(
1543+
!s.too_old(&s.filled), // 21 < 48
1544+
"Expected packets to not be considered too old even with timestamp wrapping"
1545+
);
1546+
assert!(s.prepared.empty());
1547+
}
1548+
14761549
#[test]
14771550
fn test_sample_builder_data() {
14781551
let mut s = SampleBuilder::new(10, FakeDepacketizer::new(), 1);

0 commit comments

Comments
 (0)