Skip to content

Commit

Permalink
macos: workaround UB and undefined instruction issue
Browse files Browse the repository at this point in the history
The compiler emitted `ud2` right around this code, effectively
breaking wezterm on startup.

In talking this through with @dtolnay, the definition of the
structs in the core_foundation crate makes it undefined behavior
to pass a null pointer to its fields, despite that being a valid
and documented way to use the struct.

This commit works around this by defining our own local versions
of the types and functions with the safe signature.

I'll follow up with the owners of the core_foundation crate
to submit an equivalent patch upstream.
  • Loading branch information
wez committed Nov 12, 2019
1 parent 7323e30 commit 398f333
Showing 1 changed file with 43 additions and 4 deletions.
47 changes: 43 additions & 4 deletions window/src/os/macos/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,45 @@ impl Connection {
}
}

/* Begin: workaround UB in CFRunLoopTimerContext struct.
* This can be removed once an equivalent change is upstreamed to the
* core_foundation crate */

use core_foundation::string::__CFString;
use std::ffi::c_void;

#[repr(transparent)]
pub struct __CFRunLoopTimer(c_void);

#[repr(C)]
#[allow(non_snake_case)]
pub struct CFRunLoopTimerContext {
pub version: i64,
pub info: *mut c_void,
pub retain: Option<extern "C" fn(*const c_void) -> *const c_void>,
pub release: Option<extern "C" fn(*const c_void)>,
pub copyDescription: Option<extern "C" fn(*const c_void) -> *const __CFString>,
}

extern "C" {
fn CFRunLoopTimerCreate(
allocator: *const c_void,
fireDate: f64,
interval: f64,
flags: u32,
order: i64,
callout: extern "C" fn(*mut __CFRunLoopTimer, *mut c_void),
context: *mut CFRunLoopTimerContext,
) -> *mut __CFRunLoopTimer;
fn CFRunLoopAddTimer(
rl: *mut __CFRunLoop,
timer: *mut __CFRunLoopTimer,
mode: *const __CFString,
);
}

/* End: UB workaround */

impl ConnectionOps for Connection {
fn terminate_message_loop(&self) {
unsafe {
Expand Down Expand Up @@ -103,7 +142,7 @@ impl ConnectionOps for Connection {
let callback = Box::into_raw(Box::new(callback));

extern "C" fn timer_callback<F: FnMut()>(
_timer_ref: CFRunLoopTimerRef,
_timer_ref: *mut __CFRunLoopTimer,
callback_ptr: *mut std::ffi::c_void,
) {
unsafe {
Expand All @@ -126,10 +165,10 @@ impl ConnectionOps for Connection {
0,
timer_callback::<F>,
&mut CFRunLoopTimerContext {
copyDescription: std::mem::MaybeUninit::zeroed().assume_init(),
copyDescription: None,
info: callback as _,
release: release_callback::<F>,
retain: std::mem::MaybeUninit::zeroed().assume_init(),
release: Some(release_callback::<F>),
retain: None,
version: 0,
},
)
Expand Down

0 comments on commit 398f333

Please sign in to comment.