-
Notifications
You must be signed in to change notification settings - Fork 697
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
Using Rust enums to represent C enums can result in undefined behavior #667
Comments
Thanks for the bug report! |
We have some related features:
Agree that we should generally do the Right Thing by default |
Just as a reminder don't do this unless |
Related issue #758 "Fixed" through constified enums that you then need to use correctly for "bounds checking"(you can manually check if the "value" overflows the expected API and then probably abort or something). |
Yeah, this is fixed now. |
This is similar to #225, but different in that this is about C enums that are used as actual enums (not bit flags).
Consider, for example, the following C code:
This gets translated by
bindgen
into:The problem is that the C project could add enum fields (which is often considered to not be an API/ABI breaking change in the C world) to the end (e.g. a new
STATUS_BAD_AUTH = 3
field), at which point using the (old) Rust enum would result in undefined behavior due to Rust's strict enum range requirements. If a function in the C API ever returnedSTATUS_BAD_AUTH
then the Rust code would have undefined behavior. Static linking the C library will help mitigate this, but if the library is dynamically linked then the Rust code really can't be considered safe.Here are my current thoughts on how to solve this, though other solutions are likely possible:
bindgen
user to specify a flag that will makebindgen
generate Rust enums to represent C enums only for C enums that are used as input parameters. For example, if the C function isenum foo do_something(enum bar)
then thebar
enum could be represented safely as a Rust enum, since it would only be constructed in the Rust code. If all the C functions thatbindgen
finds only take an enum by value (or a pointer to const enum), then this should be a safe optimization to make.bindgen
user to specify a different flag that will makebindgen
generate Rust enums for all C enums. This would be an unsafe option, but would allow the user to take advantage of potential compiler optimizations, and in a controlled environment (e.g. statically linking to a known library version) can be done safely.This would be a nontrivial amount of work, but I think at least the first point is important for ensuring the safety of Rust programs that have to interact with C libraries.
See rust-lang/rust#36927 for the relevant issue filed against Rust itself.
The text was updated successfully, but these errors were encountered: