-
Notifications
You must be signed in to change notification settings - Fork 279
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