use container_probe::Probe;
use std::fs;
fn fixture(rel: &str) -> Vec<u8> {
fs::read(format!("{}/../{}", env!("CARGO_MANIFEST_DIR"), rel))
.unwrap_or_else(|e| panic!("failed to read fixture {rel}: {e}"))
}
struct Prng(u64);
impl Prng {
fn next_u8(&mut self) -> u8 {
self.0 ^= self.0 << 13;
self.0 ^= self.0 >> 7;
self.0 ^= self.0 << 17;
(self.0 & 0xFF) as u8
}
fn fill(&mut self, out: &mut [u8]) {
for b in out {
*b = self.next_u8();
}
}
}
fn assert_well_formed(data: &[u8]) {
let p = container_probe::probe(data);
match &p {
Probe::Identified { .. } | Probe::Ambiguous { .. } => {
}
Probe::Insufficient { need_at_least, .. } => {
assert!(
*need_at_least > data.len(),
"Insufficient must demand more than the {} supplied bytes, got {p:?}",
data.len()
);
}
Probe::Unknown => {}
_ => panic!("unexpected new Probe variant: {p:?}"),
}
}
#[test]
fn no_panic_on_prefixes_of_every_real_fixture() {
let fixtures = [
"fixtures/ts/h264_aac.ts",
"fixtures/mp4/h264_high.mp4",
"fixtures/mkv/h264_aac.mkv",
"fixtures/webm/vorbis.webm",
"fixtures/mxf/op1a_mpeg2_pcm.mxf",
"fixtures/ps/h264_ac3.ps",
"fixtures/flv/av.flv",
"fixtures/container-probe/pcm_s16le.wav",
"fixtures/container-probe/opus.ogg",
"fixtures/container-probe/video.asf",
"fixtures/container-probe/aac.adts",
"fixtures/container-probe/audio.mp3",
"fixtures/container-probe/h264.annexb",
];
for rel in fixtures {
let full = fixture(rel);
for len in 1..=64usize.min(full.len()) {
let prefix = &full[..len];
assert_well_formed(prefix);
}
assert_well_formed(&full);
}
}
#[test]
fn no_panic_on_zero_and_fill() {
assert_well_formed(&[0u8; 4096]);
assert_well_formed(&[0xFFu8; 4096]);
}
#[test]
fn no_panic_on_deterministic_random() {
let mut rng = Prng(0x9E3779B97F4A7C15);
let mut buf = vec![0u8; 8192];
rng.fill(&mut buf);
assert_well_formed(&buf);
}
fn structured_length_mutations() -> Vec<Vec<u8>> {
let mut out = Vec::new();
for width in 1..=8u32 {
let mut buf = vec![0x1A, 0x45, 0xDF, 0xA3]; buf.push(1u8 << (8 - width));
buf.resize(4 + width as usize, 0);
buf.extend_from_slice(b"\x42\x82\x80\x00\x00\x00\x00\x00\x00\x00");
out.push(buf);
}
let mut large = vec![0u8; 16];
large[3] = 1; large[4..8].copy_from_slice(b"free");
large[8..].copy_from_slice(&u64::MAX.to_be_bytes());
out.push(large);
let mut eof = vec![0u8; 8];
eof[4..8].copy_from_slice(b"free");
out.push(eof);
let mut tiny = vec![0u8; 8];
tiny[3] = 7;
tiny[4..8].copy_from_slice(b"free");
out.push(tiny);
let mxf_key = [
0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
for octets in 1..=9u8 {
let mut m = mxf_key.to_vec();
m.push(0x80 | octets); m.extend(std::iter::repeat_n(0u8, octets as usize + 2));
out.push(m);
}
for fl in [7u16, 0x01FF, 0x1FFF, 0x0800] {
let mut a = vec![0xFF, 0xF1, 0x00, 0, 0, 0];
a[3] = ((fl >> 11) & 0x03) as u8;
a[4] = ((fl >> 3) & 0xFF) as u8;
a[5] = ((fl & 0x07) as u8) << 5;
a.extend(std::iter::repeat_n(0x00, 32));
out.push(a);
}
for (b2, b3) in [(0x54u8, 0x00u8), (0xF4, 0x00), (0x20, 0x02), (0x54, 0x02)] {
let mut m = vec![0xFF, 0xFB, b2, b3];
m.extend(std::iter::repeat_n(0x00, 32));
out.push(m);
}
out
}
#[test]
fn no_panic_on_structured_length_mutations() {
for input in structured_length_mutations() {
assert_well_formed(&input);
}
}