From 8119b36c21763466892d5bb78aa2bcb648b874f8 Mon Sep 17 00:00:00 2001 From: Earl Co Date: Fri, 23 Oct 2026 16:53:42 +0200 Subject: [PATCH] security(mpeg2v): index picture extensions linearly (#2904) --- crates/mpeg2v/src/lib.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/mpeg2v/src/lib.rs b/crates/mpeg2v/src/lib.rs index 6d8cb0497..55c1ab9ad 100644 --- a/crates/mpeg2v/src/lib.rs +++ b/crates/mpeg2v/src/lib.rs @@ -338,11 +338,16 @@ pub fn access_units(es: &[u8]) -> Vec> { } PICTURE_START => { // picture_structure from the picture coding extension that follows - let structure = codes[k + 1..] + let structure = codes .iter() - .take_while(|c| c.1 == EXTENSION || c.1 == headers::USER_DATA) - .find_map(|&(p, c)| { - let end = codes.iter().find(|x| x.0 > p).map_or(es.len(), |x| x.0); + .enumerate() + .skip(k + 1) + .take_while(|(_, c)| c.1 == EXTENSION || c.1 == headers::USER_DATA) + .find_map(|(next, &(p, c))| { + // `next` is this unit's position in `codes`, so its successor gives the + // payload end directly. Searching `codes` from the beginning here made a + // stream of short picture/extension pairs quadratic to index. + let end = codes.get(next + 1).map_or(es.len(), |x| x.0); (c == EXTENSION).then(|| Extension::parse(&es[(p + 4).min(end)..end]).ok()).flatten() }) .and_then(|e| match e {