Skip to content

Commit a3a8348

Browse files
authored
fix: Allow null pointers as empty slices (#79)
1 parent 29b4a3e commit a3a8348

3 files changed

Lines changed: 35 additions & 16 deletions

File tree

include/accesskit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2204,7 +2204,8 @@ struct accesskit_custom_actions *accesskit_node_custom_actions(
22042204
const struct accesskit_node *node);
22052205

22062206
/**
2207-
* Caller is responsible for freeing each `custom_action` in the array.
2207+
* Caller is responsible for freeing each `custom_action` in the array
2208+
* as well as the `values` array itself.
22082209
*/
22092210
void accesskit_node_set_custom_actions(
22102211
struct accesskit_node *node, size_t length,

src/common.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,16 @@ macro_rules! array_setter {
6363
#[no_mangle]
6464
pub extern "C" fn $c_setter(node: *mut node, length: usize, values: *const $ffi_type) {
6565
let node = mut_from_ptr(node);
66-
let values = unsafe {
67-
slice::from_raw_parts(values, length)
68-
.iter()
69-
.cloned()
70-
.map(From::from)
71-
.collect::<Vec<$rust_type>>()
66+
let values = if length == 0 {
67+
Vec::new()
68+
} else {
69+
unsafe {
70+
slice::from_raw_parts(values, length)
71+
.iter()
72+
.cloned()
73+
.map(From::from)
74+
.collect::<Vec<$rust_type>>()
75+
}
7276
};
7377
node.$setter(values);
7478
}
@@ -157,8 +161,13 @@ macro_rules! slice_struct {
157161
}
158162
impl From<$struct_name> for Vec<$rust_type> {
159163
fn from(values: $struct_name) -> Self {
160-
unsafe {
161-
slice::from_raw_parts(values.values as *mut $rust_type, values.length).to_vec()
164+
if values.length == 0 {
165+
Vec::new()
166+
} else {
167+
unsafe {
168+
slice::from_raw_parts(values.values as *mut $rust_type, values.length)
169+
.to_vec()
170+
}
162171
}
163172
}
164173
}
@@ -795,19 +804,24 @@ impl node {
795804
BoxCastPtr::to_mut_ptr(node.custom_actions().into())
796805
}
797806

798-
/// Caller is responsible for freeing each `custom_action` in the array.
807+
/// Caller is responsible for freeing each `custom_action` in the array
808+
/// as well as the `values` array itself.
799809
#[no_mangle]
800810
pub extern "C" fn accesskit_node_set_custom_actions(
801811
node: *mut node,
802812
length: usize,
803813
values: *const *mut custom_action,
804814
) {
805815
let node = mut_from_ptr(node);
806-
let values = unsafe {
807-
slice::from_raw_parts(values, length)
808-
.iter()
809-
.map(|ptr| ref_from_ptr(*ptr).clone())
810-
.collect::<Vec<CustomAction>>()
816+
let values = if length == 0 {
817+
Vec::new()
818+
} else {
819+
unsafe {
820+
slice::from_raw_parts(values, length)
821+
.iter()
822+
.map(|ptr| ref_from_ptr(*ptr).clone())
823+
.collect::<Vec<CustomAction>>()
824+
}
811825
};
812826
node.set_custom_actions(values);
813827
}

src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,5 +194,9 @@ where
194194
}
195195

196196
unsafe fn string_from_c_slice(value: *const c_char, length: usize) -> String {
197-
String::from_utf8_lossy(slice::from_raw_parts(value as *const u8, length)).into_owned()
197+
if length == 0 {
198+
String::new()
199+
} else {
200+
String::from_utf8_lossy(slice::from_raw_parts(value as *const u8, length)).into_owned()
201+
}
198202
}

0 commit comments

Comments
 (0)