Skip to content
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

Are raw pointers to sized types usable in C FFI ? #99

Closed
gnzlbg opened this issue Mar 14, 2019 · 7 comments
Closed

Are raw pointers to sized types usable in C FFI ? #99

gnzlbg opened this issue Mar 14, 2019 · 7 comments
Labels
A-ffi Topic: Related to FFI A-layout Topic: Related to data structure layout (`#[repr]`)

Comments

@gnzlbg
Copy link
Contributor

gnzlbg commented Mar 14, 2019

AFAICT we don't mention this explicitly anywhere.

https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/pointers.md#representation mentions that they are one word in size, but maybe we should spell out that they are layout compatible with C pointers (including alignment) to make it clear that's ok to use raw pointers in C FFI.

@gnzlbg gnzlbg added A-layout Topic: Related to data structure layout (`#[repr]`) A-ffi Topic: Related to FFI labels Mar 14, 2019
gnzlbg added a commit to gnzlbg/unsafe-code-guidelines that referenced this issue Mar 14, 2019
@briansmith
Copy link

briansmith commented Mar 21, 2019

they are layout compatible with C pointers (including alignment) to make it clear that's ok to use raw pointers in C FFI.

C doesn't guarantee that sizeof(void*) == sizeof(size_t) but Rust guarantees that its pointers, references, usize, and libc::size_t are all the same size. For example, in a 64-bit CHERI-based ABI a C pointer would be 128 or 256 bits wide but Rust pointers, size_t and usize would all be 64 bits.

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Mar 21, 2019

but Rust guarantees that its pointers, references, usize, and libc::size_t are all the same size.

Pointers to sized types, references to sized types, isize and usize have the same size as C pointers which is the same size as intptr_t and uintptr_t.

I don't think we guarantee anything with respect to size_t, and I don't know how libc::size_t relates to any of the other types.

@briansmith
Copy link

I don't think we guarantee anything with respect to size_t, and I don't know how libc::size_t relates to any of the other types.

https://docs.rs/libc/0.2.50/libc/type.size_t.html says that libc defines libc::size_t to be usize:

type size_t = usize;

Because of this, the Rust compiler allows implicit conversion between usize and size_t and much code assumes this will work.

Thus, things are over-constrained. I suggest that this all be qualified to "platforms where uintptr_t and size_t have the same representation."

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Mar 21, 2019

Because of this, the Rust compiler allows implicit conversion between usize and size_t and much code assumes this will work.

The only thing we guarantee about libc::size_t is that it matches C's size_t. In the targets in which that's the same as usize, that assumption is correct and the code is intended to work like it does.

If we ever add a target where libc::size_t is some other type, then code that assumes it is an usize will not work, but that code is not portable - libc does not provide a portable wrapper over all platforms, it provides raw access to the platforms API, whatever they might be.

So I don't think we have to say anything about libc::size_t at all.

@briansmith
Copy link

I bet there's a lot of (FFI-using) code that both assumes that Rust pointers and references are the same size as a C pointer and also assumes that usize is equivalent to size_t. I have written a bit of such code myself. Note that there's an RFC issue about what we can assume about usize: rust-lang/rfcs#1748.

Stepping back from that, I think the broader issue is this: Rust doesn't currently support any ABI where a C pointer isn't just an address, like a CHERI-based system. It is unclear what would need to change in Rust to support such an ABI, basically because we (IMO wrongly) overloaded usize to mean both size_t and uintptr_t. I think that we need flexibility to fix any/all issues that result from that if/when Rust is ported to an ABI where pointers are not plain memory addresses, so I do think that qualifying this guarantee to systems where pointers are plain addresses and where uintptr_t and size_t are the same is prudent.

@petrochenkov
Copy link

petrochenkov commented Mar 21, 2019

It was widely assumed since before 1.0 when the types were renamed from uint to usize that all the usize, c::size_t, c::ssize_t, c::ptrdiff_t, c::uintptr_t, c::void* types are compatible with each other (modulo signedness).
No one wanted all the complexity associated with the C types, that C/C++ language lawyers love arguing about so much.
It that's not documented explicitly yet, then it should be.

@gnzlbg
Copy link
Contributor Author

gnzlbg commented Mar 21, 2019

I bet there's a lot of (FFI-using) code that both assumes that Rust pointers and references are the same size as a C pointer and also assumes that usize is equivalent to size_t.

There is a lot of code in the wild that assumes a lot of non-portable things to be true because that's a valid assumption for all platforms that that code cares about, and that's ok.

It is unclear what would need to change in Rust to support such an ABI, basically because we (IMO wrongly) overloaded usize to mean both size_t and uintptr_t.

We explicitly guarantee that usize == uintptr_t which is correct for CHERI platforms, so AFAICT we haven't overloaded anything.

Note that there's an RFC issue about what we can assume about usize: rust-lang/rfcs#1748.

I don't think this is the right issue to discuss adding / removing guarantees to isize/usize, but note that this repo is actually an RFC, and we have written here what unsafe code is allowed to assume about these types. If unsafe code assumes things that we don't guarantee, then arguably that code isn't 100% portable, but that doesn't mean its incorrect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ffi Topic: Related to FFI A-layout Topic: Related to data structure layout (`#[repr]`)
Projects
None yet
Development

No branches or pull requests

3 participants