diff --git a/Cargo.toml b/Cargo.toml index 14037b6bf..2a6f5bb7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ fn_to_numeric_cast_any = "warn" ptr_cast_constness = "warn" # == Correctness == # +#indexing_slicing = "warn" TODO: enable this lint project wide. #as_conversions = "warn" cast_lossless = "warn" cast_possible_truncation = "warn" diff --git a/crates/ironrdp-web/src/canvas.rs b/crates/ironrdp-web/src/canvas.rs index fcb7464ea..26d7eb760 100644 --- a/crates/ironrdp-web/src/canvas.rs +++ b/crates/ironrdp-web/src/canvas.rs @@ -44,10 +44,8 @@ impl Canvas { let region_height = region.height(); let mut src = buffer.chunks_exact(4).map(|pixel| { - let r = pixel[0]; - let g = pixel[1]; - let b = pixel[2]; - u32::from_be_bytes([0, r, g, b]) + let [r, g, b] = pixel.first_chunk::<3>().expect("cannot be out of bounds"); + u32::from_be_bytes([0, *r, *g, *b]) }); let mut dst = self.surface.buffer_mut().expect("surface buffer"); diff --git a/crates/ironrdp-web/src/image.rs b/crates/ironrdp-web/src/image.rs index 13ac3fedb..c13f4a0ed 100644 --- a/crates/ironrdp-web/src/image.rs +++ b/crates/ironrdp-web/src/image.rs @@ -1,9 +1,13 @@ #![allow(clippy::arithmetic_side_effects)] +use anyhow::Context as _; use ironrdp::pdu::geometry::{InclusiveRectangle, Rectangle as _}; use ironrdp::session::image::DecodedImage; -pub(crate) fn extract_partial_image(image: &DecodedImage, region: InclusiveRectangle) -> (InclusiveRectangle, Vec) { +pub(crate) fn extract_partial_image( + image: &DecodedImage, + region: InclusiveRectangle, +) -> anyhow::Result<(InclusiveRectangle, Vec)> { // PERF: needs actual benchmark to find a better heuristic if region.height() > 64 || region.width() > 512 { extract_whole_rows(image, region) @@ -13,7 +17,10 @@ pub(crate) fn extract_partial_image(image: &DecodedImage, region: InclusiveRecta } // Faster for low-height and smaller images -fn extract_smallest_rectangle(image: &DecodedImage, region: InclusiveRectangle) -> (InclusiveRectangle, Vec) { +fn extract_smallest_rectangle( + image: &DecodedImage, + region: InclusiveRectangle, +) -> anyhow::Result<(InclusiveRectangle, Vec)> { let pixel_size = usize::from(image.pixel_format().bytes_per_pixel()); let image_width = usize::from(image.width()); @@ -33,20 +40,31 @@ fn extract_smallest_rectangle(image: &DecodedImage, region: InclusiveRectangle) for row in 0..region_height { let src_begin = image_stride * (region_top + row) + region_left * pixel_size; let src_end = src_begin + region_stride; - let src_slice = &src[src_begin..src_end]; + let src_slice = src.get(src_begin..src_end).with_context(|| { + format!( + "invalid region {region:?} for image with dimensions {}x{}", + image.width(), + image.height() + ) + })?; let target_begin = region_stride * row; let target_end = target_begin + region_stride; - let target_slice = &mut dst[target_begin..target_end]; + let target_slice = dst + .get_mut(target_begin..target_end) + .expect("slice index cannot be out of bounds"); target_slice.copy_from_slice(src_slice); } - (region, dst) + Ok((region, dst)) } // Faster for high-height and bigger images -fn extract_whole_rows(image: &DecodedImage, region: InclusiveRectangle) -> (InclusiveRectangle, Vec) { +fn extract_whole_rows( + image: &DecodedImage, + region: InclusiveRectangle, +) -> anyhow::Result<(InclusiveRectangle, Vec)> { let pixel_size = usize::from(image.pixel_format().bytes_per_pixel()); let image_width = usize::from(image.width()); @@ -60,7 +78,16 @@ fn extract_whole_rows(image: &DecodedImage, region: InclusiveRectangle) -> (Incl let src_begin = region_top * image_stride; let src_end = (region_bottom + 1) * image_stride; - let dst = src[src_begin..src_end].to_vec(); + let dst = src + .get(src_begin..src_end) + .with_context(|| { + format!( + "invalid region {region:?} for image with dimensions {}x{}", + image.width(), + image.height() + ) + })? + .to_vec(); let wider_region = InclusiveRectangle { left: 0, @@ -69,5 +96,5 @@ fn extract_whole_rows(image: &DecodedImage, region: InclusiveRectangle) -> (Incl bottom: region.bottom, }; - (wider_region, dst) + Ok((wider_region, dst)) } diff --git a/crates/ironrdp-web/src/session.rs b/crates/ironrdp-web/src/session.rs index a3e189a7e..357b3d405 100644 --- a/crates/ironrdp-web/src/session.rs +++ b/crates/ironrdp-web/src/session.rs @@ -587,7 +587,7 @@ impl iron_remote_desktop::Session for Session { } ActiveStageOutput::GraphicsUpdate(region) => { // PERF: some copies and conversion could be optimized - let (region, buffer) = extract_partial_image(&image, region); + let (region, buffer) = extract_partial_image(&image, region)?; gui.draw(&buffer, region).context("draw updated region")?; } ActiveStageOutput::PointerDefault => {