Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upUsing Rust enums to represent C enums can result in undefined behavior #667
Comments
fitzgen
added
the
help wanted
label
Apr 26, 2017
This comment has been minimized.
This comment has been minimized.
|
Thanks for the bug report! |
This comment has been minimized.
This comment has been minimized.
|
We have some related features:
Agree that we should generally do the Right Thing by default |
mjbshaw
referenced this issue
Apr 27, 2017
Closed
Match on repr(C) enum returned from C library with unknown value leads to UB #36927
This comment has been minimized.
This comment has been minimized.
jeandudey
commented
May 31, 2017
Just as a reminder don't do this unless |
This comment has been minimized.
This comment has been minimized.
lilianmoraru
commented
Feb 14, 2018
•
|
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). |
jonemil
referenced this issue
Apr 3, 2018
Closed
Moves low level ffi into sys and updates bindgen #765
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
mjbshaw commentedApr 26, 2017
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
bindgeninto: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 = 3field), 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_AUTHthen 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:
bindgenuser to specify a flag that will makebindgengenerate 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 thebarenum could be represented safely as a Rust enum, since it would only be constructed in the Rust code. If all the C functions thatbindgenfinds only take an enum by value (or a pointer to const enum), then this should be a safe optimization to make.bindgenuser to specify a different flag that will makebindgengenerate 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.