-
Notifications
You must be signed in to change notification settings - Fork 449
On the size_t / uintptr_t guard #329
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
Comments
Kernel defines |
On 64-bit Windows they're different. This is obviously not relevant to us :-)
…On Wed, Jun 2, 2021 at 8:42 PM Gary Guo ***@***.***> wrote:
Kernel defines uintptr_t to be unsigned long, and size_t to be unsigned int in 32-bit arch and unsigned long in 64-bit arch. Technically according to C spec, int and long are not compatible, but in kernel they are guaranteed to be of the same size and align. Are there 32-bit archs where int and long are not ABI-compatible?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
--
All that is necessary for evil to succeed is for good people to do nothing.
|
I was briefly afraid that ARM's I don't know for sure but I expect there aren't any 32-bit arches where (btw - no need for Windows, on plain old x86_64 Linux, |
BTW there are platforms where size_t and uintptr_t are different, e.g. CHERI. CHERI uses 64-bit size_t with 128-bit uintptr_t. There is no Linux support for such platforms though, and Rust currently do not support differently-sized size_t and uintptr_t either, see rust-lang/rust#65473. |
Filed rust-lang/rust-bindgen#2062. Thanks for the link to that Rust issue - I wholeheartedly agree with
If we ever run into an architecture (like CHERI) where |
Well, the issue is that And this isn't an issue for us TBH. Many kernel code pretty much assumed that |
Closed by #330. |
In #196 it was found that the
__builtin_types_compatible_p(size_t, uintptr_t)
check fails onCONFIG_ARM
, and that PR skipped the check.It turns out that the types are in fact compatible at the ABI level - they're both 32-bit integers. It turns out that they're just not compatible as C types. You can get a better error message if you try to assign a
size_t
pointer to auintptr_t *
or something:C doesn't believe that
unsigned int
andlong unsigned int
are compatible types in terms of the abstract C idea ofint
andlong
- but on 32-bit ARM, they're not actually different (what else could they be?).So I think it should be safe to change this test to something else, like
sizeof(size_t) == sizeof(uintptr_t) && __alignof__(size_t) == __alignof__(uintptr_t)
, which does pass on ARM, and make it not-platform-specific.I added this check (without thinking too hard about how
_builtin_types_compatible_p
works) back in fishinabarrel/linux-kernel-module-rust@1e8ca1dc because, at least in the way we're using it, the way that rust-lang/rust-bindgen#1671 was fixed effectively adds a new bug. The bug it adds is that it translates the Csize_t
type tou32
or whatever instead of tousize
, which means you can't straightforwardly use it in contexts where Rust expects ausize
, e.g., slice indexing.We are working around that (new) bug by passing
--size_t-is-usize
to bindgen (inrust/Makefile
). But that simply assumes that the two types are compatible. I think in every practical place they are (and in particular, I'm pretty sure they are everywhere mainline Linux and/or Rust currently runs), but the bug originally reported in 1671 is that this isn't guaranteed by the C standard, and there might be places (like 16-bit x86 with segmentation, I think) where it's not.In case we ever end up on such a platform, somehow, we don't want to be binding C functions that use
size_t
with a Rustusize
because that's either ABI-incompatible or prone to integer overflow bugs. We either want to decide to not support that platform or to very carefully fix our uses ofusize
. (Or, possibly, try to get the kernel's ABI on that platform to change to make those types the same.)That is, the fact that issue 1671 is closed doesn't mean we no longer need the guard. We very much need the guard on all platforms because we use
--size_t-is-usize
.I'll send in a patch to fix the test and also improve the comment / assertion message.
I'm going to see if I can get a change into bindgen where bindgen itself does the compatibility check when it generates bindings and also defaults to
--size_t-is-usize
, and if the compatibility check fails (and something usessize_t
), you need to specify an option saying that you're okay with bindingsize_t
tou32
/u64
/whatever. If that lands, then we can remove the guard.The text was updated successfully, but these errors were encountered: