-
Notifications
You must be signed in to change notification settings - Fork 283
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Thread locals are currently translated as static mut which is unsafe, but more importantly are accessed by &mut which adds UB compared to C.
As a minimal example this:
static __thread int x = 0;
void bar(int *y) {
int *z = &x;
*z = *y;
}
void foo() { bar(&x); }Currently translates on the website (https://c2rust.com) as:
#[thread_local]
static mut x: libc::c_int = 0 as libc::c_int;
#[no_mangle]
pub unsafe extern "C" fn bar(mut y: *mut libc::c_int) {
let mut z: *mut libc::c_int = &mut x;
*z = *y;
}
#[no_mangle]
pub unsafe extern "C" fn foo() {
bar(&mut x);
}Which creates 2 &mut x references and uses the first after the construction of the second, leading to UB absent in the original C code.
But it could use translate as:
use core::cell::Cell;
#[thread_local]
static x: Cell<libc::c_int> = Cell::new(0 as libc::c_int);
#[no_mangle]
pub unsafe extern "C" fn bar(mut y: *mut libc::c_int) {
let mut z: *mut libc::c_int = x.as_ptr();
*z = *y;
}
#[no_mangle]
pub unsafe extern "C" fn foo() {
bar(x.as_ptr());
}This translation would prevent the UB from creating multiple &mut to the same static, and moreover makes the definition of x itself completely safe. It would even work with pointer typed static __thread variables because unlike normal statics, #[thread_local] static does not need to be Sync.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working