Skip to content

Commit

Permalink
Make make_bitflags! sound even when dirty tricks are employed
Browse files Browse the repository at this point in the history
Previously, the macro relied on an expression of the form Enum::Variant
always being a variant of the enum. However, it may also be an
associated integer constant, in which case we don't have any
guarantee that the value only contains bits valid for this enum.

Thus, adverserial input to the macro could create a `BitFlags<Enum>`
with bits that don't correspond to any of the enum variants. Iterating
over such a value would then cause UB. The debug formatter is also
affected, as internally it iterates over the value being formatted.
  • Loading branch information
meithecatte committed Apr 17, 2023
1 parent 467fe56 commit 24b13aa
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,10 @@ macro_rules! make_bitflags {
{
let mut n = 0;
$(
n |= $enum::$variant as <$enum as $crate::_internal::RawBitFlags>::Numeric;
{
let flag: $enum = $enum::$variant;
n |= flag as <$enum as $crate::_internal::RawBitFlags>::Numeric;
}
)*
// SAFETY: The value has been created from numeric values of the underlying
// enum, so only valid bits are set.
Expand Down
18 changes: 18 additions & 0 deletions test_suite/ui/sneaky_make_bitflags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use enumflags2::{bitflags, make_bitflags};

#[bitflags]
#[repr(u8)]
#[derive(Copy, Clone, Debug)]
enum Test {
A = 1,
B = 2,
}

impl Test {
const C: u8 = 69;
}

fn main() {
let x = make_bitflags!(Test::{C});
dbg!(x);
}
10 changes: 10 additions & 0 deletions test_suite/ui/sneaky_make_bitflags.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error[E0308]: mismatched types
--> ui/sneaky_make_bitflags.rs:16:13
|
16 | let x = make_bitflags!(Test::{C});
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected `Test`, found `u8`
| expected due to this
|
= note: this error originates in the macro `make_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)

0 comments on commit 24b13aa

Please sign in to comment.