Skip to content

Commit

Permalink
Fix sending nil messages to super on GNUStep, and clean up documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Nov 24, 2021
1 parent ffccd4e commit 76f3956
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
11 changes: 11 additions & 0 deletions objc2/src/message/gnustep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ where
A: MessageArguments,
R: Encode,
{
// If `receiver` is NULL, objc_msg_lookup will return a standard C-method
// taking two arguments, the receiver and the selector. Transmuting and
// calling such a function with multiple parameters is UB, so instead we
// just return NULL directly.
if receiver.is_null() {
// SAFETY: Caller guarantees that messages to NULL-receivers only
// return pointers, and a mem::zeroed pointer is just a NULL-pointer.
return unsafe { mem::zeroed() };
}

Expand All @@ -33,6 +39,11 @@ where
A: MessageArguments,
R: Encode,
{
if receiver.is_null() {
// SAFETY: Same as in `send_unverified`.
return unsafe { mem::zeroed() };
}

let sup = ffi::objc_super {
receiver: receiver as *mut _,
super_class: superclass as *const Class as *const _,
Expand Down
18 changes: 15 additions & 3 deletions objc2/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,26 @@ mod tests {
#[test]
fn test_send_message_nil() {
let nil: *mut Object = ::core::ptr::null_mut();
let result: usize = unsafe { msg_send![nil, hash] };
assert!(result == 0);

let result: *mut Object = unsafe { msg_send![nil, description] };
assert!(result.is_null());

// This result should not be relied on
let result: usize = unsafe { msg_send![nil, hash] };
assert_eq!(result, 0);

// This result should not be relied on
#[cfg(target_pointer_width = "16")]
let result: f32 = 0.0;
#[cfg(target_pointer_width = "32")]
let result: f32 = unsafe { msg_send![nil, floatValue] };
#[cfg(target_pointer_width = "64")]
let result: f64 = unsafe { msg_send![nil, doubleValue] };
assert!(result == 0.0);
assert_eq!(result, 0.0);

// This result should not be relied on
let result: *mut Object = unsafe { msg_send![nil, multiple: 1u32, arguments: 2i8] };
assert!(result.is_null());
}

#[test]
Expand Down

0 comments on commit 76f3956

Please sign in to comment.