From bcb73999da7fc3da4b609789f1fe13c41f8efc33 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 13 Oct 2024 18:22:26 +0200 Subject: [PATCH] add NULL checks - brightness_grid --- .../src/brightness_grid.rs | 106 +++++++++++++----- crates/servicepoint_binding_c/src/command.rs | 4 +- 2 files changed, 80 insertions(+), 30 deletions(-) diff --git a/crates/servicepoint_binding_c/src/brightness_grid.rs b/crates/servicepoint_binding_c/src/brightness_grid.rs index 33662ff..db44687 100644 --- a/crates/servicepoint_binding_c/src/brightness_grid.rs +++ b/crates/servicepoint_binding_c/src/brightness_grid.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with `SPBrightnessGrid`s +//! C functions for interacting with [SPBrightnessGrid]s //! //! prefix `sp_brightness_grid_` @@ -29,9 +29,9 @@ impl Clone for SPBrightnessGrid { } } -/// Creates a new `SPBrightnessGrid` with the specified dimensions. +/// Creates a new [SPBrightnessGrid] with the specified dimensions. /// -/// returns: `SPBrightnessGrid` initialized to 0. Will never return NULL. +/// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. /// /// # Safety /// @@ -44,16 +44,21 @@ pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, ) -> *mut SPBrightnessGrid { - Box::into_raw(Box::new(SPBrightnessGrid( + let result = Box::into_raw(Box::new(SPBrightnessGrid( servicepoint::BrightnessGrid::new(width, height), - ))) + ))); + assert!(!result.is_null()); + result } -/// Loads a `SPBrightnessGrid` with the specified dimensions from the provided data. +/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. +/// +/// returns: new [SPBrightnessGrid] instance. Will never return NULL. /// /// # Panics /// -/// When the provided `data_length` is not sufficient for the `height` and `width` +/// - when `data` is NULL +/// - when the provided `data_length` does not match `height` and `width` /// /// # Safety /// @@ -70,24 +75,33 @@ pub unsafe extern "C" fn sp_brightness_grid_load( data: *const u8, data_length: usize, ) -> *mut SPBrightnessGrid { + assert!(!data.is_null()); let data = std::slice::from_raw_parts(data, data_length); let grid = PrimitiveGrid::load(width, height, data); let grid = servicepoint::BrightnessGrid::try_from(grid) .expect("invalid brightness value"); - Box::into_raw(Box::new(SPBrightnessGrid(grid))) + let result = Box::into_raw(Box::new(SPBrightnessGrid(grid))); + assert!(!result.is_null()); + result } -/// Clones a `SPBrightnessGrid`. +/// Clones a [SPBrightnessGrid]. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// +/// returns: new [SPBrightnessGrid] instance. Will never return NULL. +/// +/// # Panics +/// +/// - when `brightness_grid` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] /// - `brightness_grid` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_brightness_grid_free`. @@ -95,26 +109,34 @@ pub unsafe extern "C" fn sp_brightness_grid_load( pub unsafe extern "C" fn sp_brightness_grid_clone( brightness_grid: *const SPBrightnessGrid, ) -> *mut SPBrightnessGrid { - Box::into_raw(Box::new((*brightness_grid).clone())) + assert!(!brightness_grid.is_null()); + let result = Box::into_raw(Box::new((*brightness_grid).clone())); + assert!(!result.is_null()); + result } -/// Deallocates a `SPBrightnessGrid`. +/// Deallocates a [SPBrightnessGrid]. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// +/// # Panics +/// +/// - when `brightness_grid` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] /// - `brightness_grid` is not used concurrently or after this call /// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: *mut SPBrightnessGrid, ) { + assert!(!brightness_grid.is_null()); _ = Box::from_raw(brightness_grid); } @@ -125,15 +147,18 @@ pub unsafe extern "C" fn sp_brightness_grid_free( /// - `brightness_grid`: instance to read from /// - `x` and `y`: position of the cell to read /// +/// returns: value at position +/// /// # Panics /// -/// When accessing `x` or `y` out of bounds. +/// - when `brightness_grid` is NULL +/// - When accessing `x` or `y` out of bounds. /// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] /// - `brightness_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( @@ -141,10 +166,11 @@ pub unsafe extern "C" fn sp_brightness_grid_get( x: usize, y: usize, ) -> u8 { + assert!(!brightness_grid.is_null()); (*brightness_grid).0.get(x, y).into() } -/// Sets the value of the specified position in the `SPBrightnessGrid`. +/// Sets the value of the specified position in the [SPBrightnessGrid]. /// /// # Arguments /// @@ -156,6 +182,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// /// # Panics /// +/// - when `brightness_grid` is NULL /// - When accessing `x` or `y` out of bounds. /// - When providing an invalid brightness value /// @@ -172,12 +199,13 @@ pub unsafe extern "C" fn sp_brightness_grid_set( y: usize, value: u8, ) { + assert!(!brightness_grid.is_null()); let brightness = Brightness::try_from(value).expect("invalid brightness value"); (*brightness_grid).0.set(x, y, brightness); } -/// Sets the value of all cells in the `SPBrightnessGrid`. +/// Sets the value of all cells in the [SPBrightnessGrid]. /// /// # Arguments /// @@ -186,79 +214,101 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// /// # Panics /// +/// - when `brightness_grid` is NULL /// - When providing an invalid brightness value /// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( brightness_grid: *mut SPBrightnessGrid, value: u8, ) { + assert!(!brightness_grid.is_null()); let brightness = Brightness::try_from(value).expect("invalid brightness value"); (*brightness_grid).0.fill(brightness); } -/// Gets the width of the `SPBrightnessGrid` instance. +/// Gets the width of the [SPBrightnessGrid] instance. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// +/// returns: width +/// +/// # Panics +/// +/// - when `brightness_grid` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( brightness_grid: *const SPBrightnessGrid, ) -> usize { + assert!(!brightness_grid.is_null()); (*brightness_grid).0.width() } -/// Gets the height of the `SPBrightnessGrid` instance. +/// Gets the height of the [SPBrightnessGrid] instance. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// +/// returns: height +/// +/// # Panics +/// +/// - when `brightness_grid` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` +/// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( brightness_grid: *const SPBrightnessGrid, ) -> usize { + assert!(!brightness_grid.is_null()); (*brightness_grid).0.height() } -/// Gets an unsafe reference to the data of the `SPBrightnessGrid` instance. +/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// -/// ## Safety +/// returns: slice of bytes underlying the `brightness_grid`. +/// +/// # Panics +/// +/// - when `brightness_grid` is NULL +/// +/// # Safety /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBrightnessGrid` -/// - the returned memory range is never accessed after the passed `SPBrightnessGrid` has been freed -/// - the returned memory range is never accessed concurrently, either via the `SPBrightnessGrid` or directly +/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed +/// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( brightness_grid: *mut SPBrightnessGrid, ) -> SPByteSlice { + assert!(!brightness_grid.is_null()); assert_eq!(core::mem::size_of::(), 1); - let data = (*brightness_grid).0.data_ref_mut(); let data: &mut [u8] = transmute(data); SPByteSlice { diff --git a/crates/servicepoint_binding_c/src/command.rs b/crates/servicepoint_binding_c/src/command.rs index 7bc956a..4e5b45b 100644 --- a/crates/servicepoint_binding_c/src/command.rs +++ b/crates/servicepoint_binding_c/src/command.rs @@ -156,7 +156,7 @@ pub unsafe extern "C" fn sp_command_brightness( /// Set the brightness of individual tiles in a rectangular area of the display. /// -/// The passed `SPBrightnessGrid` gets consumed. +/// The passed [SPBrightnessGrid] gets consumed. /// /// Returns: a new `Command::CharBrightness` instance. Will never return NULL. /// @@ -164,7 +164,7 @@ pub unsafe extern "C" fn sp_command_brightness( /// /// The caller has to make sure that: /// -/// - `grid` points to a valid instance of `SPBrightnessGrid` +/// - `grid` points to a valid instance of [SPBrightnessGrid] /// - `grid` is not used concurrently or after this call /// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`.