From fd170b66d949ad18d3a13db7e6c20dbf1ab981b2 Mon Sep 17 00:00:00 2001 From: dailz Date: Sat, 6 Jun 2026 11:56:47 +0800 Subject: [PATCH] fix(unsafe): add SAFETY comment and runtime guards for from_raw_parts in drain_encoder Issue: #5 - Read AVPacket fields into local variable to avoid repeated pointer deref - Guard against size <= 0 (prevents c_int negative wrap to huge usize) - Guard against null data pointer (from_raw_parts(null, 0) is UB in Rust) - Add SAFETY comment matching existing codebase convention (30+ instances) --- src/avhw.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/avhw.rs b/src/avhw.rs index 245a783..0e62690 100644 --- a/src/avhw.rs +++ b/src/avhw.rs @@ -866,13 +866,18 @@ impl SwEncState { self.frames_written = true; } Some(FrameOutput::Channel(ref tx)) => { - let data: &[u8] = unsafe { - std::slice::from_raw_parts( - (*pkt.as_mut_ptr()).data, - (*pkt.as_mut_ptr()).size as usize, - ) - }; - let _ = tx.send(data.to_vec()); + let raw = unsafe { *pkt.as_mut_ptr() }; + if raw.size > 0 && !raw.data.is_null() { + // SAFETY: `pkt` is a valid AVPacket just filled by a successful + // `avcodec_receive_packet` call. We checked `size > 0` and + // `data` is non-null, so `data` points to `size` initialized + // bytes owned by the packet. `u8` has alignment 1, and the + // slice is copied into a Vec before the packet is unreffed. + let data: &[u8] = unsafe { + std::slice::from_raw_parts(raw.data, raw.size as usize) + }; + let _ = tx.send(data.to_vec()); + } } None => {} }