-
Notifications
You must be signed in to change notification settings - Fork 707
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
Generated tests use UB in their calculations #1651
Comments
This is known, but thanks for filing. I've always hoped that rust would have an offsetof macro, but... ;) Creating structs on the stack with zeroed memory is ok for C, but not so sure for C++, where what bindgen may generate is not POD, or may have destructors or other side effects. |
Can go by if the type is Copy or not. Also can use ManuallyDrop if the Rust target is new enough. I'm not sure what most of the point of those tests is anyway, most of them can't ever fail so it seems kinda silly. |
How not? Those tests are important, if bindgen generates something that has the wrong size or alignment or anything, those tests catch it. |
Replied in a separate issue because it's not really related to this "offset calculation is UB" issue. |
@Lokathor whatever you come up with will be UB anyways, because |
@gnzlbg that is true, but it has nothing to do with https://github.com/Gilnaa/memoffset/ implements the currently best way we have to do this. The most important part is to avoid NULL references; you could use |
Given that library solutions cannot (it seems) soundly support nested fields and arrays, I think indeed this should become a built-in macro. But I don't have a thick enough skin for the syntax bikeshed that will undoubtedly trigger. ;) Until then, we have that macro as a library. |
Notice that |
@gnzlbg why did i get pinged? |
Because you proposed a solution:
so I thought you might work on it, but that solution doesn't work, because of I think the |
Oh, well (1) I'm not going to work on this myself I'm just reporting the problem, (2) bindgen knows when it will emit |
What should it do in that case then?
The main problem is undefined behavior, but there are no solutions without undefined behavior. There is nothing for This should either be "blocked on" some rust-lang/rust tracking issue, or closed as "non-actionable", but right now there is no way to fix on |
Structs that aren't repr(packed) can be fixed. Further, structs that are repr(packed) can still at least be tested against a zeroed value on the stack instead of on a null pointer and at least eliminate one of the problems, even if it's not every problem being solved. It's okay to solve part of a problem at a time. |
I don't see the point yet. If this is a problem because it is UB, there are currently not solutions to this problem. But if "UB is ok as long as it works", then the current code, which works, is as good as anything else. Time would be better spent into trying to provide a way to do this without any UB, but that cannot happen here. |
Well, most structs aren't repr(packed), so actually it can happen here. |
Even for non |
...okay but you get my point that this can be fixed for the vast majority of C struct bindings I hope. |
I disagree with vast majority (all C bindings I work on use |
@gnzlbg there's still a big difference between "theoretical UB" (that works because it's spec-only UB but we currently -- as of the latest nightly rustc -- never exploit it) and UB that rustc/LLVM might actually exploit, but they happen to not do that in the cases you checked (like NULL references). I don't understand why you are fighting back so hard against what is clearly a strict improvement in language compliance. Why this black-and-white attitude? |
This issue reports that the generic code that bindgen uses is broken, but
such code can’t be fixed, and this issue can’t be closed. The code has
currently UB in the spec and in LLVM, and the proposed “fix” does so as
well. We all agree that this reliance on UB is brittle, and Id rather not
change something that’s known to work for bindgen users to something that
doesn’t really fixes the issue and isn’t known to work at the bindgen scale
(many more crates use bindgen than offsetof, reliance on the behavior of UB
on many different toolchain versions, etc.). This also only impacts UB in
#[test]s, and that code is not even compiled when using bindgen libraries
as dependencies.
Once &raw is available, fixing this issue would be a no brainer, but right
now there are IMO dozens of other open issues with a better value
proposition than what putting any work on this one would deliver.
|
So, let me rephrase: "if it can't be perfect (doesn't really fix the issue) then we don't care how awful it is".
offsetof is used in crossbeam, so if you really want to compare numbers... But also, this is clearly not leading anywhere, so I'll just stop here. |
That's not what I said. |
Update: there is a fully sound The "catch" is that you have to pass in an instance of the type to the macro. So either the type needs to have default or makeable with all 0s or something like that. |
Would the addition of addr_of make this easier to implement without UB? FYI, the recent addition of a new lint for deref'ing a null ptr surfaces this:
|
Perhaps? But for that we'd also need to create an instance of the type, which we might not know how to create, and which may have other side effects... Can we get an address into a I don't see how off-hand but that doesn't necessarily mean it doesn't exist... In any case I think we'd still be working around the lack of a standard |
any C type can be constructed of zeroed memory at least. |
Not if you implement |
It looks like rust-lang/rust#95372 caused these warnings are now errors in For the next person, it looks like quick work around (but definitely not the correct long term solution) is to use |
Disabling layout tests is only useful to remove the warning and undefined behavior, at the expense of more risks with regard to ABI changes. That's a compromise one needs to think about. The |
The layout tests can't detect that to begin with so there's no difference if you turn them off. |
If the layout tests can't detect ABI changes, then what are they supposed to validate? |
They don't validate much because they don't call into C. It's just checking rust code against other rust code. All they actually end up doing is a clumsy check that your C type aliases are correct. Which you can do once per crate, instead of once per type, and get just as much benefit. EDIT: even then, checking the type aliases once per crate is excessive probably. Really they should be checked once when defined (eg: in |
Does this mean that one way of actually solving this issue would be to remove the generation of these checks entirely? |
that's my suggestion, yes. |
This is not right. The layout tests are useful, because they test the actual generated rust code with the offsets that we get from libclang. |
So even though it's not the same as calling into C and back, it's pretty close, and they've caught ABI issues in Firefox in the past, for example. |
the tests could certainly detect some problems, but if all C type aliases are correct then that's about the extent of what they can check. For example, if a conditional compilation adds or changes a field in a C struct in a new C lib version, or on a different target, the rust code has no way to notice, and these tests won't help you. They are extremely un-portable tests. |
Use latest version of bindgen (0.62) and add Default to implementations. This fixes `clippy::derivable_impls` warning and rust-lang/rust-bindgen#1651. Signed-off-by: Petre Eftime <[email protected]>
Use latest version of bindgen (0.62) and add Default to implementations. This fixes `clippy::derivable_impls` warning and rust-lang/rust-bindgen#1651. Signed-off-by: Petre Eftime <[email protected]>
Since the update to rustc 1.53, bindgen using UB causes warnings. See rust-lang/rust-bindgen#1651 for detail. Warnings all in the style of: --------------------------------------------------------------------- warning: dereferencing a null pointer --> ../godot-rust/target/<toolchain>/debug/build/gdnative-sys-7023d0a45a684438/out/bindings.rs:98:19 | 98 | unsafe { &(*(::std::ptr::null::<godot_string>()))._dont_touch_that as *const _ as usize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: `#[warn(deref_nullptr)]` on by default ---------------------------------------------------------------------
776: Silence UB warnings caused by bindgen r=Bromeon a=Bromeon Since the update to rustc 1.53, bindgen using UB causes warnings. See rust-lang/rust-bindgen#1651 for detail. Warnings all in the style of: ``` warning: dereferencing a null pointer --> ../godot-rust/target/<toolchain>/debug/build/gdnative-sys-7023d0a45a684438/out/bindings.rs:98:19 | 98 | unsafe { &(*(::std::ptr::null::<godot_string>()))._dont_touch_that as *const _ as usize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: `#[warn(deref_nullptr)]` on by default ``` Co-authored-by: Jan Haller <[email protected]>
The clippy override `allow(deref_nullptr)` is no longer needed since the issue has been fixed from rust-bindgen [1]. [1] rust-lang/rust-bindgen#1651 Signed-off-by: Bo Chen <[email protected]>
The clippy override `allow(deref_nullptr)` is no longer needed since the issue has been fixed from rust-bindgen [1]. [1] rust-lang/rust-bindgen#1651 Signed-off-by: Bo Chen <[email protected]>
Test code for struct offsets run checks like this:
But it's UB to dereference a null pointer, and it's also UB to create a
&T
with numeric value 0.There is actually trivial to fix. Instead of using a null pointer, just create a value on the stack (using
core::mem::zeroed()
, which is safe since all C structs can be created as zeroed-memory), and then use a reference to that stack value, the fields of that stack value, and so on.The text was updated successfully, but these errors were encountered: