Add the missing direct coverage for parse_stss
Every other sample-table parser (stco, stsc, stts, ctts) had a "count lie" test proving the declared count is bounded by what the box actually holds, and stco/stsc had their own arithmetic pinned. parse_stss had neither - no test in this file ever called it with real entries, only with a too-short buffer. Added the same two: two distinct entries read from their own offsets (catching the o = 8 + i*4 arithmetic and the per-entry bounds check), and a declared count of 3 backed by only 2 real entries (catching the same "trust the box, not the count" contract the other four parsers already had).
This commit is contained in:
@@ -1098,6 +1098,54 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `parse_stss` had no direct positive-path test anywhere in this file —
|
||||||
|
/// only its short-buffer safety was pinned. Two real, distinct entries in
|
||||||
|
/// a buffer sized to exactly fit them (`b.len() == 16`, so the second
|
||||||
|
/// entry's `o + 4 == b.len()` exactly) separates every arithmetic mutant
|
||||||
|
/// at once: an `o = 8 + i*4` → `8 - i*4` slip reads the `count` field
|
||||||
|
/// instead of the second entry; an `i*4` → `i/4` slip re-reads the FIRST
|
||||||
|
/// entry for the second (integer division collapses `i=1` back to the
|
||||||
|
/// same offset as `i=0`); and an `o + 4 > b.len()` → `o + 4 < b.len()`
|
||||||
|
/// slip breaks out on the very first entry, because there IS more room
|
||||||
|
/// after it (`12 < 16`) — leaving the set empty instead of holding both.
|
||||||
|
#[test]
|
||||||
|
fn parse_stss_reads_two_distinct_entries_from_their_own_offsets() {
|
||||||
|
let mut b = vec![0u8, 0, 0, 0]; // version+flags
|
||||||
|
b.extend_from_slice(&2u32.to_be_bytes()); // entry_count = 2
|
||||||
|
b.extend_from_slice(&100u32.to_be_bytes());
|
||||||
|
b.extend_from_slice(&200u32.to_be_bytes());
|
||||||
|
assert_eq!(b.len(), 16, "sized to fit exactly 2 entries, no slack");
|
||||||
|
let set = parse_stss(&b);
|
||||||
|
assert_eq!(
|
||||||
|
set,
|
||||||
|
[100u32, 200u32].into_iter().collect(),
|
||||||
|
"both distinct sync sample numbers must be present"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A declared `count` larger than the box can hold (a lie, or a truncated
|
||||||
|
/// box) must be bounded by the per-entry guard, not by trusting the
|
||||||
|
/// count — the SAME contract `parse_stco`/`parse_stsc`/`parse_stts` pin
|
||||||
|
/// with their own "count lie" tests. Bounded HERE means the loop must
|
||||||
|
/// stop, not read past the end: an `o + 4 > b.len()` → `o - 4 > b.len()`
|
||||||
|
/// mutant almost never fires (`o - 4` stays small for every realistic
|
||||||
|
/// `o`), so it lets the loop walk straight past a truncated box into an
|
||||||
|
/// out-of-bounds `be32` read.
|
||||||
|
#[test]
|
||||||
|
fn parse_stss_count_lie_is_bounded_by_the_box_not_trusted() {
|
||||||
|
let mut b = vec![0u8, 0, 0, 0];
|
||||||
|
b.extend_from_slice(&3u32.to_be_bytes()); // declares 3, lying
|
||||||
|
b.extend_from_slice(&100u32.to_be_bytes()); // only 2 real entries
|
||||||
|
b.extend_from_slice(&200u32.to_be_bytes());
|
||||||
|
assert_eq!(b.len(), 16, "room for exactly 2 real entries, not 3");
|
||||||
|
let set = parse_stss(&b);
|
||||||
|
assert_eq!(
|
||||||
|
set,
|
||||||
|
[100u32, 200u32].into_iter().collect(),
|
||||||
|
"only the entries the box actually holds, no panic on the lie"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stsc_offsets_one_sample_per_chunk() {
|
fn stsc_offsets_one_sample_per_chunk() {
|
||||||
// Our writer's layout: 1 sample/chunk, co64 lists every offset.
|
// Our writer's layout: 1 sample/chunk, co64 lists every offset.
|
||||||
|
|||||||
Reference in New Issue
Block a user