Skip to content

Commit 24b13aa

Browse files
committed
Make make_bitflags! sound even when dirty tricks are employed
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.
1 parent 467fe56 commit 24b13aa

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,10 @@ macro_rules! make_bitflags {
402402
{
403403
let mut n = 0;
404404
$(
405-
n |= $enum::$variant as <$enum as $crate::_internal::RawBitFlags>::Numeric;
405+
{
406+
let flag: $enum = $enum::$variant;
407+
n |= flag as <$enum as $crate::_internal::RawBitFlags>::Numeric;
408+
}
406409
)*
407410
// SAFETY: The value has been created from numeric values of the underlying
408411
// enum, so only valid bits are set.

test_suite/ui/sneaky_make_bitflags.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use enumflags2::{bitflags, make_bitflags};
2+
3+
#[bitflags]
4+
#[repr(u8)]
5+
#[derive(Copy, Clone, Debug)]
6+
enum Test {
7+
A = 1,
8+
B = 2,
9+
}
10+
11+
impl Test {
12+
const C: u8 = 69;
13+
}
14+
15+
fn main() {
16+
let x = make_bitflags!(Test::{C});
17+
dbg!(x);
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0308]: mismatched types
2+
--> ui/sneaky_make_bitflags.rs:16:13
3+
|
4+
16 | let x = make_bitflags!(Test::{C});
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| expected `Test`, found `u8`
8+
| expected due to this
9+
|
10+
= note: this error originates in the macro `make_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)