Skip to content

Commit b67dbea

Browse files
committed
Fix zerocopy validation logic
1 parent 02e4ab5 commit b67dbea

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

src/lib.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,33 @@ where
667667
unsafe { BitFlags::from_bits_unchecked(bits & T::ALL_BITS) }
668668
}
669669

670+
/// Validate if an underlying bitwise value can safely be converted to `BitFlags`.
671+
/// Returns false if any invalid bits are set.
672+
///
673+
/// ```
674+
/// # use enumflags2::{bitflags, BitFlags};
675+
/// #[bitflags]
676+
/// #[repr(u8)]
677+
/// #[derive(Clone, Copy, PartialEq, Eq)]
678+
/// enum MyFlag {
679+
/// One = 0b0001,
680+
/// Two = 0b0010,
681+
/// Three = 0b1000,
682+
/// }
683+
///
684+
/// assert_eq!(BitFlags::<MyFlag>::validate_bits(0b1011), true);
685+
/// assert_eq!(BitFlags::<MyFlag>::validate_bits(0b0000), true);
686+
/// assert_eq!(BitFlags::<MyFlag>::validate_bits(0b0100), false);
687+
/// assert_eq!(BitFlags::<MyFlag>::validate_bits(0b1111), false);
688+
/// ```
689+
#[must_use]
690+
#[inline(always)]
691+
pub fn validate_bits(bits: T::Numeric) -> bool {
692+
// SAFETY: We're truncating out all the invalid bits so it will
693+
// only be different if there are invalid bits set.
694+
(bits & T::ALL_BITS) == bits
695+
}
696+
670697
/// Create a new BitFlags unsafely, without checking if the bits form
671698
/// a valid bit pattern for the type.
672699
///
@@ -1102,8 +1129,11 @@ mod impl_zerocopy {
11021129
let my_candidate =
11031130
unsafe { candidate.assume_validity::<zerocopy::pointer::invariant::Valid>() };
11041131
{
1105-
(my_candidate.read_unaligned::<zerocopy::pointer::BecauseImmutable>() ^ T::ALL_BITS)
1106-
== T::EMPTY
1132+
// TODO: Currently this assumes that the candidate is aligned. We actually need to check this beforehand
1133+
// Dereference the pointer to the candidate
1134+
let candidate =
1135+
my_candidate.read_unaligned::<zerocopy::pointer::BecauseImmutable>();
1136+
return BitFlags::<T>::validate_bits(candidate);
11071137
}
11081138
}
11091139
}

0 commit comments

Comments
 (0)