Fix all PES pipeline audit findings (20 issues)
Critical: - C1: PES serialize validates track < 256 and data < 4GB - C2: PES deserialize caps frame size at 256MB (OOM protection) - C3: TsMuxer stuffing uses static buffer, no per-packet alloc - C4: PES length uses unbounded (0x0000) for audio >65535 bytes - C6: TsDemuxer validates AF length <= 183 Warning: - W1: parse_timestamp validates marker bits, returns Option - W2: PES header data_start clamped to data.len() - W3: TsMuxer PTS conversion uses saturating_mul, rejects negative - W4: AC3/DTS replace debug_assert with runtime bounds check - W6: MKV block_vint handles 3-4 byte VINTs - W7: meta.rs to_title() uses unwrap_or fallbacks instead of panic - W8: MKV reader skips frames for non-existent tracks - W9: DVD PTS uses higher-precision conversion (1e9/90000) - FMKV read_header caps JSON at 10MB - PAT section_len underflow guard Suggestion: - S2: TsMuxer uses static STUFF_FF buffer - S3: HEVC parser single-pass NAL scan (was duplicated) - S4: TsDemuxer caps remainder at one packet - S5: PTS 90kHz→ns uses round-to-nearest
This commit is contained in:
+25
-2
@@ -22,6 +22,18 @@ pub struct PesFrame {
|
||||
impl PesFrame {
|
||||
/// Serialize to bytes: track(1) | pts(8) | keyframe(1) | len(4) | data
|
||||
pub fn serialize(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||
if self.track > 255 {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
"track index exceeds 255",
|
||||
));
|
||||
}
|
||||
if self.data.len() > u32::MAX as usize {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
"frame data exceeds 4 GB",
|
||||
));
|
||||
}
|
||||
w.write_all(&[self.track as u8])?;
|
||||
w.write_all(&self.pts.to_le_bytes())?;
|
||||
w.write_all(&[if self.keyframe { 1 } else { 0 }])?;
|
||||
@@ -31,6 +43,8 @@ impl PesFrame {
|
||||
|
||||
/// Deserialize from bytes. Returns None at EOF.
|
||||
pub fn deserialize(r: &mut dyn std::io::Read) -> std::io::Result<Option<Self>> {
|
||||
const MAX_FRAME_SIZE: usize = 256 * 1024 * 1024; // 256 MB
|
||||
|
||||
let mut header = [0u8; 14]; // 1 + 8 + 1 + 4
|
||||
match r.read_exact(&mut header) {
|
||||
Ok(_) => {}
|
||||
@@ -38,9 +52,18 @@ impl PesFrame {
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
let track = header[0] as usize;
|
||||
let pts = i64::from_le_bytes(header[1..9].try_into().unwrap());
|
||||
let pts = i64::from_le_bytes([
|
||||
header[1], header[2], header[3], header[4],
|
||||
header[5], header[6], header[7], header[8],
|
||||
]);
|
||||
let keyframe = header[9] != 0;
|
||||
let len = u32::from_le_bytes(header[10..14].try_into().unwrap()) as usize;
|
||||
let len = u32::from_le_bytes([header[10], header[11], header[12], header[13]]) as usize;
|
||||
if len > MAX_FRAME_SIZE {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("frame size {} exceeds maximum {}", len, MAX_FRAME_SIZE),
|
||||
));
|
||||
}
|
||||
let mut data = vec![0u8; len];
|
||||
r.read_exact(&mut data)?;
|
||||
Ok(Some(Self { track, pts, keyframe, data }))
|
||||
|
||||
Reference in New Issue
Block a user