Skip to content

Commit b8c3508

Browse files
committed
ZJIT: Avoid transmute dodging rustc/LLVM int-to-ptr miscompilation
The transmute triggered a miscompilation on Rust 1.85.0, where the callback was "optimized" to unconditional go to a `SIGTRAP`ping instruction. While later Rust versions don't have the same miscompilation, it seems that this is also partly our fault for being funky with the pointer provenance in this code. It's possible rust will make some changes that break the transmute. Use the Exposed Provenance API here and steer clear of transmute. See: rust-lang/rust#121282 See: rust-lang/rust#147265 See: rust-lang/rust#128409 (comment)
1 parent a6c6e56 commit b8c3508

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

zjit/src/cruby.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,13 +1228,13 @@ pub mod test_utils {
12281228
// "Fun" double pointer dance to get a thin function pointer to pass through C
12291229
unsafe extern "C" fn callback_wrapper(data: VALUE) -> VALUE {
12301230
// SAFETY: shorter lifetime than the data local in the caller frame
1231-
let callback: &mut &mut dyn FnMut() = unsafe { std::mem::transmute(data) };
1232-
callback();
1231+
let callback: *mut &mut dyn FnMut() = std::ptr::with_exposed_provenance_mut(data.0);
1232+
unsafe { (*callback)() };
12331233
Qnil
12341234
}
12351235

12361236
let mut state: c_int = 0;
1237-
unsafe { super::rb_protect(Some(callback_wrapper), VALUE((&mut data) as *mut _ as usize), &mut state) };
1237+
unsafe { super::rb_protect(Some(callback_wrapper), VALUE((&raw mut data).expose_provenance()), &mut state) };
12381238
if state != 0 {
12391239
unsafe { rb_zjit_print_exception(); }
12401240
assert_eq!(0, state, "Exceptional unwind in callback. Ruby exception?");

0 commit comments

Comments
 (0)