-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add forbidden function casts RFC #3526
base: master
Are you sure you want to change the base?
Add forbidden function casts RFC #3526
Conversation
Co-authored-by: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com>
Co-authored-by: Jules Bertholet <jules.bertholet@gmail.com>
what happens when code pointers are bigger than data pointers? do you have to fall back on an example is the 8086 Medium Memory Model, which has 16-bit data pointers and 32-bit code pointers. |
usize is guaranteed to be the same size as a data pointer, so seemingly if cast to a data pointer would truncate, cast to usize would too. Does Rust support any such platform? https://doc.rust-lang.org/reference/type-layout.html#pointers-and-references-layout |
I couldn't find any specific instances, but I know AVR also can have different code/data pointer sizes, and MSP430 too, just all the configurations I could find don't do that. With rustc's GCC backend, there are a whole pile of weird and wonderful cpu architectures that rust could feasibly support in the future. I know others have discussed different code/data pointer sizes before, in reference to |
Either way, if cast to Casting function pointer to an integer doesn’t seem to be a common operation either: you can’t do pointer arithmetics on it, so I think the only reason you would want this is some FFI / inline asm stuff? I think if you’re on an architecture where function pointers are larger than data pointers and you want their numeric values, you very much know what you’re doing and could write a transmute, and if you’re writing cross-platform code you would more often than not write |
Side note: having something like |
I am ambivalent on this proposal as-is without something like |
Could you elaborate on this, please? As I've written before, if cast to a data pointer truncates, cast to usize also does, so this doesn't seem to cause any new issues. |
if a function pointer doesn't fit in // assume 32-bit code pointers and 16-bit data pointers:
pub fn works(fptr: fn()) -> u32 {
fptr as u32
}
pub fn broken(fptr: fn()) -> u32 {
fptr as *const () as u32
} |
Personally I would like to see us do something here. But I feel uneasy about recommending that function pointers be converted to data pointers, both for the reasons of size discrepancies that @programmerjake raised and because more generally, code and data could exist in different address spaces entirely. |
I think we should add e.g.: impl<A, R, const ABI: &'static str> extern ABI fn(..A) -> R { // all function pointer types (needs more impls for unsafe fn, etc.
pub fn addr(self) -> core::ffi::uintfptr {
unsafe { mem::transmute(self) }
}
} |
I like to use |
wasm is a well-known architecture where function pointers are in a different address space from data pointers (they're table indices) despite being the same size. |
Is it relevant? Cast through a data pointer should still work I think? |
CHERI is coming so I'm in favour of stopping conflating data pointers with function pointers with integers that can count a number of things in memory. Making people use transmute seems reasonable, because it will complain if two things are not the same size, but do I like Also I spent nearly a decade programming the XAP2 processor (it's in almost every CSR Bluetooth chip) and it has entirely separate code and data address spaces. So, I'm sensitised to these kinds of issues because they bit me hard in C all the time. |
Note that this requires fnptr to integer to fnptr transmutes to be valid, which is not obvious, cf. rust-lang/unsafe-code-guidelines#286, rust-lang/unsafe-code-guidelines#340
Unfortunately, I don’t think we can stop conflating |
The concern about targets with data and function pointers being different is interesting. Note that I don't think difference in address spaces is significant — whatever the "blessed" way will be, we can just make sure we account for address spaces properly (going through For platforms with
Expanding on the second question, it seems like the assumption that
Assumptions for
And also unstable APIs ( I'm not sure we have a way out of all of this, given that unsafe code is relatively likely to depend on stuff like this (my opinion). |
@rustbot labels -A-edition-2024 +A-maybe-next-edition We discussed the timeline of edition items in the lang meeting today, and this didn't make the list, so it seems unlikely this will happen for Rust 2024. We'll keep this in mind for future editions. Thanks to everyone working on this and providing helpful feedback here. |
This RFC proposes to forbid function -> integer
as
casts, since they have surprising aspects and are error prone.Rendered