use container_probe::{DEFAULT_BUDGET, Probe, probe_with_budget};
fn adversarial_inputs() -> Vec<(&'static str, Vec<u8>)> {
vec![
(
"ebml-declared-body-past-region",
vec![
0x1A, 0x45, 0xDF, 0xA3, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
],
),
(
"id3-268mb-declared-tag",
vec![b'I', b'D', b'3', 0x04, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F],
),
("ts-single-sync", vec![0x47]),
(
"adts-mixed-frame-lengths",
vec![
0xFF, 0xF1, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xFF, 0xF1, 0x00, 0x03, 0xFF, 0xE0, 0x00,
],
),
(
"isobmff-cut-largesize",
vec![0x00, 0x00, 0x00, 0x01, b'f', b't', b'y', b'p', 0x00, 0x00],
),
]
}
fn at(seed: &[u8], len: usize) -> Vec<u8> {
let mut b = seed.to_vec();
b.resize(len, 0x00);
b
}
#[test]
fn every_adversarial_input_actually_reaches_insufficient() {
for (name, seed) in adversarial_inputs() {
let reached = [seed.len().max(1), 64, 1024, 4096, DEFAULT_BUDGET]
.into_iter()
.any(|len| {
matches!(
probe_with_budget(&at(&seed, len), len),
Probe::Insufficient { .. }
)
});
assert!(
reached,
"{name} never probes Insufficient at any tested length, so it cannot \
witness a defect in the Insufficient contract — it is inert, and an \
inert input makes every other assertion in this file vacuous for it"
);
}
}
#[test]
fn need_at_least_always_exceeds_the_bytes_examined() {
let lengths = [
1,
188,
4096,
DEFAULT_BUDGET - 1,
DEFAULT_BUDGET,
DEFAULT_BUDGET + 1,
DEFAULT_BUDGET * 2,
];
let mut failures: Vec<String> = Vec::new();
for (name, seed) in adversarial_inputs() {
for len in lengths {
let buf = at(&seed, len);
for budget in [DEFAULT_BUDGET, buf.len()] {
let examined = core::cmp::min(buf.len(), budget);
if let Probe::Insufficient { need_at_least, .. } = probe_with_budget(&buf, budget)
&& need_at_least <= examined
{
failures.push(format!(
" {name}: len={len} budget={budget} examined={examined} -> \
need_at_least={need_at_least}, which does not exceed the bytes \
examined; a caller re-probes to the same answer forever"
));
}
}
}
}
assert!(
failures.is_empty(),
"Insufficient must always ask for ground not yet examined:\n{}",
failures.join("\n")
);
}
#[test]
fn the_documented_caller_loop_converges() {
const MAX_TURNS: usize = 48;
const FILE_LEN: usize = DEFAULT_BUDGET * 4;
for (name, seed) in adversarial_inputs() {
let file = at(&seed, FILE_LEN);
let mut have = 1usize;
let mut turns = 0usize;
let verdict = loop {
turns += 1;
assert!(
turns <= MAX_TURNS,
"{name}: the documented loop had not converged after {MAX_TURNS} turns \
(at {have} of {FILE_LEN} bytes). A need derived from the buffer length \
rather than the structure terminates but crawls; that is the defect."
);
let buf = &file[..have];
match probe_with_budget(buf, buf.len()) {
Probe::Insufficient { need_at_least, .. } => {
assert!(
need_at_least > have,
"{name}: at {have} bytes the probe asked for {need_at_least} — \
no advance, so the caller loops forever on this input"
);
let next = need_at_least.min(file.len());
if next <= have {
assert_eq!(
have,
file.len(),
"{name}: stopped advancing at {have} without having read the \
whole {FILE_LEN}-byte file"
);
break Probe::Unknown;
}
have = next;
}
other => break other,
}
};
assert!(
!matches!(verdict, Probe::Insufficient { .. }),
"{name}: loop exited still Insufficient"
);
}
}