Pin find_boxes_capped's cap boundary and its size-field byte offsets
Nothing asserted the scan actually STOPS at cap rather than one match past it, or that the declared box size is decoded from its own four bytes rather than an adjacent one - every existing fixture used sizes small enough that all but the last size byte are zero, so an index slip reading the wrong byte would read the same zero and go unnoticed.
This commit is contained in:
@@ -2938,6 +2938,46 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `find_boxes_capped` stops at exactly `cap` matches, not one past it —
|
||||||
|
/// the whole point being that a caller asking for `cap` matches never
|
||||||
|
/// forces the scan to walk (and match-collect) further into a crafted
|
||||||
|
/// payload than it asked for.
|
||||||
|
#[test]
|
||||||
|
fn find_boxes_capped_stops_exactly_at_cap_not_one_past() {
|
||||||
|
let mut payload = Vec::new();
|
||||||
|
for _ in 0..3 {
|
||||||
|
payload.extend_from_slice(&mp4_box(b"test", &[]));
|
||||||
|
}
|
||||||
|
let out = find_boxes_capped(&payload, b"test", 2);
|
||||||
|
assert_eq!(
|
||||||
|
out.len(),
|
||||||
|
2,
|
||||||
|
"three matches exist in the payload; cap=2 must return exactly 2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The declared box size is decoded from four specific bytes
|
||||||
|
/// (`payload[pos..pos+4]`, big-endian). A size deliberately chosen so byte
|
||||||
|
/// 1 differs from byte 0 catches an index slip that rereads byte 0 (or any
|
||||||
|
/// other wrong offset) instead of the byte the field actually occupies —
|
||||||
|
/// with a small size every byte but the last is zero, so such a slip would
|
||||||
|
/// go unnoticed.
|
||||||
|
#[test]
|
||||||
|
fn find_boxes_capped_decodes_the_size_field_from_its_own_bytes() {
|
||||||
|
let want_size: u32 = 0x0001_0010; // byte0=0x00 byte1=0x01 byte2=0x00 byte3=0x10
|
||||||
|
let mut payload = vec![0u8; want_size as usize];
|
||||||
|
payload[0..4].copy_from_slice(&want_size.to_be_bytes());
|
||||||
|
payload[4..8].copy_from_slice(b"test");
|
||||||
|
let out = find_boxes_capped(&payload, b"test", 1);
|
||||||
|
assert_eq!(out.len(), 1, "the declared-size box must be found");
|
||||||
|
assert_eq!(
|
||||||
|
out[0].len() as u32,
|
||||||
|
want_size - 8,
|
||||||
|
"the matched payload slice's length must match the size field \
|
||||||
|
decoded from its own four bytes"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// An `stsc` entry names a `first_chunk` that may exceed the chunk count the
|
/// An `stsc` entry names a `first_chunk` that may exceed the chunk count the
|
||||||
/// `stco` actually declares (a truncated or crafted table). The run it would
|
/// `stco` actually declares (a truncated or crafted table). The run it would
|
||||||
/// fill has to be clamped to the chunks that exist — indexing `spc` past its
|
/// fill has to be clamped to the chunks that exist — indexing `spc` past its
|
||||||
|
|||||||
Reference in New Issue
Block a user