Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions zerocopy-derive/tests/include.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,22 @@ pub mod util {
let ptr = ptr.cast::<_, ::zerocopy::pointer::cast::CastSized, _>();
assert!(<T as super::imp::TryFromBytes>::is_bit_valid(ptr));
}

pub fn test_is_bit_valid<T: super::imp::TryFromBytes, V: super::imp::IntoBytes>(
mut val: V,
is_bit_valid: bool,
) {
use super::imp::pointer::{cast::CastSized, BecauseExclusive};

let candidate = ::zerocopy::Ptr::from_mut(&mut val);
let candidate = candidate.forget_aligned();
// SAFETY: by `val: impl IntoBytes`, `val` consists entirely of
// initialized bytes. It's still unsound because this might let us
// overwrite `val` with initialized-but-invalid bytes, but we don't do
// that, so no UB is ever exercised.
let candidate = unsafe { candidate.assume_initialized() };
let candidate = candidate.cast::<T, CastSized, (_, BecauseExclusive)>();

super::imp::assert_eq!(T::is_bit_valid(candidate), is_bit_valid);
}
}
73 changes: 13 additions & 60 deletions zerocopy-derive/tests/struct_try_from_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,10 @@ include!("include.rs");

#[test]
fn zst() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let candidate = ::zerocopy::Ptr::from_ref(&());
let candidate = candidate.forget_aligned();
// SAFETY: `&()` trivially consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <() as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(is_bit_valid);
crate::util::test_is_bit_valid::<(), _>((), true);
}

#[derive(imp::TryFromBytes)]
#[derive(imp::TryFromBytes, imp::Immutable, imp::IntoBytes)]
#[repr(C)]
struct One {
a: u8,
Expand All @@ -36,16 +30,11 @@ util_assert_impl_all!(One: imp::TryFromBytes);

#[test]
fn one() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let candidate = ::zerocopy::Ptr::from_ref(&One { a: 42 });
let candidate = candidate.forget_aligned();
// SAFETY: `&One` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <One as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(is_bit_valid);
crate::util::test_is_bit_valid::<One, _>(One { a: 42 }, true);
crate::util::test_is_bit_valid::<One, _>(One { a: 43 }, true);
}

#[derive(imp::TryFromBytes)]
#[derive(imp::TryFromBytes, imp::Immutable, imp::IntoBytes)]
#[repr(C)]
struct Two {
a: bool,
Expand All @@ -56,34 +45,9 @@ util_assert_impl_all!(Two: imp::TryFromBytes);

#[test]
fn two() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let candidate = ::zerocopy::Ptr::from_ref(&Two { a: false, b: () });
let candidate = candidate.forget_aligned();
// SAFETY: `&Two` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <Two as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(is_bit_valid);
}

#[test]
fn two_bad() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let mut buf = [2u8; 1];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf);
let candidate = candidate.forget_aligned();
// SAFETY: `&Two` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };

let candidate = {
use imp::pointer::{cast::CastSized, BecauseExclusive};
candidate.cast::<_, CastSized, (_, BecauseExclusive)>()
};

// SAFETY: `candidate`'s referent is as-initialized as `Two`.
let candidate = unsafe { candidate.assume_initialized() };

let is_bit_valid = <Two as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(!is_bit_valid);
crate::util::test_is_bit_valid::<Two, _>(Two { a: false, b: () }, true);
crate::util::test_is_bit_valid::<Two, _>(Two { a: true, b: () }, true);
crate::util::test_is_bit_valid::<Two, _>([2u8], false);
}

#[derive(imp::KnownLayout, imp::TryFromBytes)]
Expand All @@ -99,11 +63,10 @@ fn un_sized() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let mut buf = [16u8, 12, 42];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf[..]);
let candidate = candidate.forget_aligned();
// SAFETY: `&Unsized` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };

let candidate = {
let mut candidate = {
use imp::pointer::{cast::CastUnsized, BecauseExclusive};
candidate.cast::<_, CastUnsized, (_, BecauseExclusive)>()
};
Expand Down Expand Up @@ -145,7 +108,7 @@ where

util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::TryFromBytes);

#[derive(imp::FromBytes)]
#[derive(imp::FromBytes, imp::IntoBytes)]
#[repr(C)]
struct MaybeFromBytes<T>(T);

Expand All @@ -155,19 +118,9 @@ fn test_maybe_from_bytes() {
// trivial `is_bit_valid` impl that always returns true. This test confirms
// that we *don't* spuriously do that when generic parameters are present.

let mut buf = [2u8];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf);
let candidate = candidate.bikeshed_recall_initialized_from_bytes();

let candidate = {
use imp::pointer::{cast::CastSized, BecauseExclusive};
candidate.cast::<MaybeFromBytes<bool>, CastSized, (_, BecauseExclusive)>()
};

// SAFETY: `[u8]` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <MaybeFromBytes<bool> as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(!is_bit_valid);
crate::util::test_is_bit_valid::<MaybeFromBytes<bool>, _>(MaybeFromBytes(false), true);
crate::util::test_is_bit_valid::<MaybeFromBytes<bool>, _>(MaybeFromBytes(true), true);
crate::util::test_is_bit_valid::<MaybeFromBytes<bool>, _>([2u8], false);
}

#[derive(Debug, PartialEq, Eq, imp::TryFromBytes, imp::Immutable, imp::KnownLayout)]
Expand Down
83 changes: 10 additions & 73 deletions zerocopy-derive/tests/union_try_from_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,11 @@ util_assert_impl_all!(One: imp::TryFromBytes);

#[test]
fn one() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let candidate = ::zerocopy::Ptr::from_ref(&One { a: 42 });
let candidate = candidate.forget_aligned();
// SAFETY: `&One` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <One as imp::TryFromBytes>::is_bit_valid(candidate);
assert!(is_bit_valid);
crate::util::test_is_bit_valid::<One, _>([42u8], true);
crate::util::test_is_bit_valid::<One, _>([43u8], true);
}

#[derive(imp::Immutable, imp::TryFromBytes)]
#[derive(imp::Immutable, imp::TryFromBytes, imp::IntoBytes)]
#[repr(C)]
union Two {
a: bool,
Expand All @@ -44,41 +39,9 @@ util_assert_impl_all!(Two: imp::TryFromBytes);

#[test]
fn two() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let candidate_a = ::zerocopy::Ptr::from_ref(&Two { a: false });
let candidate_a = candidate_a.forget_aligned();
// SAFETY: `&Two` consists entirely of initialized bytes.
let candidate_a = unsafe { candidate_a.assume_initialized() };
let is_bit_valid = <Two as imp::TryFromBytes>::is_bit_valid(candidate_a);
assert!(is_bit_valid);

let candidate_b = ::zerocopy::Ptr::from_ref(&Two { b: true });
let candidate_b = candidate_b.forget_aligned();
// SAFETY: `&Two` consists entirely of initialized bytes.
let candidate_b = unsafe { candidate_b.assume_initialized() };
let is_bit_valid = <Two as imp::TryFromBytes>::is_bit_valid(candidate_b);
assert!(is_bit_valid);
}

#[test]
fn two_bad() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let mut buf = [2u8];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf);
let candidate = candidate.forget_aligned();
// SAFETY: `&[u8]` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };

let candidate = {
use imp::pointer::{cast::CastSized, BecauseExclusive};
candidate.cast::<Two, CastSized, (_, BecauseExclusive)>()
};

// SAFETY: `candidate`'s referent is as-initialized as `Two`.
let candidate = unsafe { candidate.assume_initialized() };

let is_bit_valid = <Two as imp::TryFromBytes>::is_bit_valid(candidate);
assert!(!is_bit_valid);
crate::util::test_is_bit_valid::<Two, _>(Two { a: false }, true);
crate::util::test_is_bit_valid::<Two, _>(Two { b: true }, true);
crate::util::test_is_bit_valid::<Two, _>([2u8], false);
}

#[derive(imp::Immutable, imp::TryFromBytes)]
Expand All @@ -90,23 +53,9 @@ union BoolAndZst {

#[test]
fn bool_and_zst() {
// FIXME(#5): Use `try_transmute` in this test once it's available.
let mut buf = [2u8];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf);
let candidate = candidate.forget_aligned();
// SAFETY: `&[u8]` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };

let candidate = {
use imp::pointer::{cast::CastSized, BecauseExclusive};
candidate.cast::<BoolAndZst, CastSized, (_, BecauseExclusive)>()
};

// SAFETY: `candidate`'s referent is fully initialized.
let candidate = unsafe { candidate.assume_initialized() };

let is_bit_valid = <BoolAndZst as imp::TryFromBytes>::is_bit_valid(candidate);
assert!(is_bit_valid);
crate::util::test_is_bit_valid::<BoolAndZst, _>([0u8], true);
crate::util::test_is_bit_valid::<BoolAndZst, _>([1u8], true);
crate::util::test_is_bit_valid::<BoolAndZst, _>([2u8], true);
}

#[derive(imp::FromBytes)]
Expand All @@ -121,19 +70,7 @@ fn test_maybe_from_bytes() {
// trivial `is_bit_valid` impl that always returns true. This test confirms
// that we *don't* spuriously do that when generic parameters are present.

let mut buf = [2u8];
let candidate = ::zerocopy::Ptr::from_mut(&mut buf);
let candidate = candidate.bikeshed_recall_initialized_from_bytes();

let candidate = {
use imp::pointer::{cast::CastSized, BecauseExclusive};
candidate.cast::<MaybeFromBytes<bool>, CastSized, (_, BecauseExclusive)>()
};

// SAFETY: `[u8]` consists entirely of initialized bytes.
let candidate = unsafe { candidate.assume_initialized() };
let is_bit_valid = <MaybeFromBytes<bool> as imp::TryFromBytes>::is_bit_valid(candidate);
imp::assert!(!is_bit_valid);
crate::util::test_is_bit_valid::<MaybeFromBytes<bool>, _>([2u8], false);
}

#[derive(imp::Immutable, imp::TryFromBytes)]
Expand Down
Loading