format-probes: two adjacent start codes no longer panic the AVS3 probe #586
3 changed files with 44 additions and 1 deletions
|
|
@ -6,6 +6,12 @@ wire format may change and such changes are recorded here.
|
|||
|
||||
## Unreleased
|
||||
|
||||
### A probe no longer panics on two adjacent start codes
|
||||
|
||||
- `wai.video.avs3` and `wai.audio.avs3`: a payload with a start code prefix directly after another (`00 00 01 00 00 01`)
|
||||
made the unit split slice backwards and panic, so a hostile payload could stop whatever probed it. It is now the empty
|
||||
unit format-probes §8.2 reads, and the payload is refused. A test now gives every probe 30,000 payloads of hostile bytes.
|
||||
|
||||
### A third party's hop has a signed record: what was sent, what came back, and what the provider bills
|
||||
|
||||
- **The third-party hop record** ([extensions/route-record.md](extensions/route-record.md) §6.2, §7.2 step 9),
|
||||
|
|
|
|||
|
|
@ -164,6 +164,41 @@ mod tests {
|
|||
assert_eq!(probe(CAP_IMAGE_PNG, &[]), Err(Refusal::NoProbe));
|
||||
}
|
||||
|
||||
/// A payload is whatever arrives: no probe may panic on it, whatever its bytes.
|
||||
#[test]
|
||||
fn no_bytes_make_a_probe_panic() {
|
||||
let mut x = 0x9e37_79b9_7f4a_7c15u64;
|
||||
let mut next = move || {
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
x
|
||||
};
|
||||
// What the probes' framing is made of, so that noise reaches past their first checks.
|
||||
const EDGE: [u8; 14] = [0, 0, 0, 1, 2, 3, 0x40, 0x42, 0x44, 0xb0, 0xb3, 0xff, 0x10, 0x7c];
|
||||
const STARTS: [&[u8]; 8] = [
|
||||
b"", b"\x00\x00\x01", b"\x00\x00\x01\x00\x00\x01", b"\x00\x00\x01\xb0", b"\x00\x00\x01\x40\x01",
|
||||
b"\x00\x00\x01\x7c", b"\xff\x10\xff\x50", b"\xc0\x01\x10",
|
||||
];
|
||||
for round in 0..30_000u32 {
|
||||
let mut b = STARTS[round as usize % STARTS.len()].to_vec();
|
||||
for _ in 0..next() as usize % 128 {
|
||||
let r = next();
|
||||
b.push(if r & 1 == 0 { EDGE[(r >> 8) as usize % EDGE.len()] } else { (r >> 16) as u8 });
|
||||
}
|
||||
for &(c, _) in PROBES {
|
||||
let _ = probe(c, &b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adjacent_start_codes_are_refused_and_do_not_panic() {
|
||||
for c in [CAP_VIDEO_AVS3, CAP_AUDIO_AVS3, CAP_VIDEO_HEVC, CAP_VIDEO_VVC, CAP_VIDEO_LCEVC] {
|
||||
assert!(probe(c, b"\x00\x00\x01\x00\x00\x01\xb0\x00\x00\x01").is_err(), "{c}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codes_are_distinct_and_read_back() {
|
||||
for r in Refusal::ALL {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ pub fn units(b: &[u8]) -> Result<Vec<(u8, &[u8])>, Refusal> {
|
|||
let mut out = Vec::new();
|
||||
for (k, &s) in starts.iter().enumerate() {
|
||||
let end = if k + 1 < starts.len() { starts[k + 1] - 3 } else { b.len() };
|
||||
out.push((b[s], &b[s + 1..end]));
|
||||
// A prefix directly after a prefix: that unit's start code is the next prefix's first
|
||||
// byte, and it holds nothing.
|
||||
out.push((b[s], b.get(s + 1..end).unwrap_or(&[])));
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue