From 27360e6ff24ea421e160b8b50459f7f9f1f62aca Mon Sep 17 00:00:00 2001 From: "seer-by-sentry[bot]" <157164994+seer-by-sentry[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:30:58 +0000 Subject: [PATCH] Refactor: Convert RGBA to RGB with bounds checking in MP4 export --- crates/export/src/mp4.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/export/src/mp4.rs b/crates/export/src/mp4.rs index 79edbffb46..3aa83f7e56 100644 --- a/crates/export/src/mp4.rs +++ b/crates/export/src/mp4.rs @@ -186,18 +186,35 @@ impl Mp4ExportSettings { } if let Some(frame) = first_frame { + // Calculate the unpadded width (RGBA = 4 bytes per pixel) + let unpadded_width = (frame.width * 4) as usize; + + // Convert RGBA to RGB with bounds checking to prevent memory access violations + let rgb_data: Vec = frame + .data + .chunks(frame.padded_bytes_per_row as usize) + .flat_map(|row| { + // Use min to safely handle edge cases where row might be shorter than expected + let actual_width = row.len().min(unpadded_width); + row[0..actual_width] + .chunks(4) + .take(frame.width as usize) + .flat_map(|chunk| { + // Ensure chunk has at least 3 bytes (RGB) before accessing + if chunk.len() >= 3 { + vec![chunk[0], chunk[1], chunk[2]] + } else { + vec![] + } + }) + .collect::>() + }) + .collect(); + let rgb_img = ImageBuffer::, Vec>::from_raw( frame.width, frame.height, - frame - .data - .chunks(frame.padded_bytes_per_row as usize) - .flat_map(|row| { - row[0..(frame.width * 4) as usize] - .chunks(4) - .flat_map(|chunk| [chunk[0], chunk[1], chunk[2]]) - }) - .collect::>(), + rgb_data, ) .expect("Failed to create image from frame data");