Skip to content

Commit

Permalink
Correct CheckBytes impl for NonZero integers
Browse files Browse the repository at this point in the history
  • Loading branch information
djkoloski committed Sep 13, 2024
1 parent b04d8cc commit 29fc6bc
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 30 deletions.
30 changes: 0 additions & 30 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,35 +343,5 @@ macro_rules! impl_nonzero {
impl_partial_eq_and_eq!(for $name: $prim);
impl_partial_ord_and_ord!(for $name: $prim);
impl_fmt!(UpperHex for $name);

#[cfg(feature = "bytecheck")]
// SAFETY: `check_bytes` only returns `Ok` if `value` points to a valid
// non-zero value, which is the only requirement for `NonZero` integers.
unsafe impl<C> bytecheck::CheckBytes<C> for $name
where
C: bytecheck::rancor::Fallible + ?Sized,
C::Error: bytecheck::rancor::Trace,
$prim: bytecheck::CheckBytes<C>,
{
#[inline]
unsafe fn check_bytes(
value: *const Self,
context: &mut C,
) -> Result<(), C::Error> {
use bytecheck::rancor::ResultExt as _;

// SAFETY: `value` points to a `Self`, which has the same size
// as a `$prim` and is at least as aligned as one. Note that the
// bit pattern for 0 is always the same regardless of
// endianness.
unsafe {
<$prim>::check_bytes(value.cast(), context)
.with_trace(|| $crate::context::ValueCheckContext {
inner_name: core::stringify!($prim),
outer_name: core::stringify!($name),
})
}
}
}
};
}
30 changes: 30 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,36 @@ macro_rules! define_nonzero {
) => {
define_newtype!($name: $endian $size_align $prim);
impl_nonzero!($name: $endian $prim as $prim_int);

#[cfg(feature = "bytecheck")]
// SAFETY: `check_bytes` only returns `Ok` if `value` points to a valid
// non-zero value, which is the only requirement for `NonZero` integers.
unsafe impl<C> bytecheck::CheckBytes<C> for $name
where
C: bytecheck::rancor::Fallible + ?Sized,
C::Error: bytecheck::rancor::Trace,
$prim: bytecheck::CheckBytes<C>,
{
#[inline]
unsafe fn check_bytes(
value: *const Self,
context: &mut C,
) -> Result<(), C::Error> {
use bytecheck::rancor::ResultExt as _;

// SAFETY: `value` points to a `Self`, which has the same size
// as a `$prim` and is at least as aligned as one. Note that the
// bit pattern for 0 is always the same regardless of
// endianness.
unsafe {
<$prim>::check_bytes(value.cast(), context)
.with_trace(|| $crate::context::ValueCheckContext {
inner_name: core::stringify!($prim),
outer_name: core::stringify!($name),
})
}
}
}
};
}

Expand Down
35 changes: 35 additions & 0 deletions src/unaligned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,41 @@ macro_rules! define_unaligned_nonzero {
($name:ident: $endian:ident $size:literal $prim:ty as $prim_int:ty) => {
define_unaligned_newtype!($name: $endian $size $prim);
impl_nonzero!($name: $endian $prim as $prim_int);

#[cfg(feature = "bytecheck")]
// SAFETY: `check_bytes` only returns `Ok` if `value` points to a valid
// non-zero value, which is the only requirement for `NonZero` integers.
unsafe impl<C> bytecheck::CheckBytes<C> for $name
where
C: bytecheck::rancor::Fallible + ?Sized,
C::Error: bytecheck::rancor::Trace,
$prim: bytecheck::CheckBytes<C>,
{
#[inline]
unsafe fn check_bytes(
value: *const Self,
context: &mut C,
) -> Result<(), C::Error> {
use bytecheck::rancor::ResultExt as _;

// SAFETY: `value` points to a `Self`, which has the same size
// as a `$prim_int` and which the caller has guaranteed is valid
// for reads. All bit patterns are valid for `$prim_int`.
let value = unsafe {
value.cast::<$prim_int>().read_unaligned()
};
let ptr = (&value as *const $prim_int).cast::<$prim>();
// SAFETY: `ptr` points to a `$prim_int` and so is guaranteed to
// be aligned and point to enough bytes to represent a `$prim`.
unsafe {
<$prim>::check_bytes(ptr, context)
.with_trace(|| $crate::context::ValueCheckContext {
inner_name: core::stringify!($prim),
outer_name: core::stringify!($name),
})
}
}
}
};
}

Expand Down

0 comments on commit 29fc6bc

Please sign in to comment.