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
12 changes: 6 additions & 6 deletions zerocopy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1979,7 +1979,7 @@ pub unsafe trait TryFromBytes {
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match source.try_into_valid() {
match source.try_into_safe() {
Ok(valid) => Ok(valid.as_ref()),
Err(e) => {
Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
Expand Down Expand Up @@ -2306,7 +2306,7 @@ pub unsafe trait TryFromBytes {
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match source.try_into_valid() {
match source.try_into_safe() {
Ok(source) => Ok(source.as_mut()),
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
}
Expand Down Expand Up @@ -2623,7 +2623,7 @@ pub unsafe trait TryFromBytes {
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match source.try_into_valid() {
match source.try_into_safe() {
Ok(source) => Ok(source.as_ref()),
Err(e) => {
Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
Expand Down Expand Up @@ -2948,7 +2948,7 @@ pub unsafe trait TryFromBytes {
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match source.try_into_valid() {
match source.try_into_safe() {
Ok(source) => Ok(source.as_mut()),
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
}
Expand Down Expand Up @@ -3399,7 +3399,7 @@ fn try_ref_from_prefix_suffix<T: TryFromBytes + KnownLayout + Immutable + ?Sized
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match source.try_into_valid() {
match source.try_into_safe() {
Ok(valid) => Ok((valid.as_ref(), prefix_suffix.as_ref())),
Err(e) => Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into()),
}
Expand All @@ -3419,7 +3419,7 @@ fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized
// This call may panic. If that happens, it doesn't cause any soundness
// issues, as we have not generated any invalid state which we need to
// fix before returning.
match candidate.try_into_valid() {
match candidate.try_into_safe() {
Ok(valid) => Ok((valid.as_mut(), prefix_suffix.as_mut())),
Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
}
Expand Down
2 changes: 1 addition & 1 deletion zerocopy/src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ mod _transitions {
/// On error, unsafe code may rely on this method's returned
/// `ValidityError` containing `self`.
#[inline]
pub fn try_into_valid<R, S>(
pub fn try_into_safe<R, S>(
mut self,
) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Safe)>, ValidityError<Self, T>>
where
Expand Down
4 changes: 2 additions & 2 deletions zerocopy/src/util/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ where
let res = ptr.try_with(#[inline(always)] |ptr| {
let ptr = ptr.recall_validity::<Initialized, _>();
let ptr = ptr.cast::<_, crate::layout::CastFrom<Dst>, _>();
ptr.try_into_valid()
ptr.try_into_safe()
});
match res {
Ok(ptr) => {
Expand Down Expand Up @@ -696,7 +696,7 @@ where
ptr.try_with_unchecked(#[inline(always)] |ptr| {
let ptr = ptr.recall_validity::<Initialized, (_, (_, _))>();
let ptr = ptr.cast::<_, crate::layout::CastFrom<Dst>, _>();
ptr.try_into_valid()
ptr.try_into_safe()
})
};
match res {
Expand Down
59 changes: 32 additions & 27 deletions zerocopy/zerocopy-derive/src/derive/try_from_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
use proc_macro2::TokenStream;
use quote::quote;
use syn::{spanned::Spanned as _, Data, DataEnum, DataStruct, DataUnion, Error};
use syn::{spanned::Spanned as _, Data, DataEnum, DataStruct, DataUnion, Error, Type, Visibility};

use crate::{
derive::project::{
Expand All @@ -16,6 +16,31 @@ use crate::{
},
};

/// Generates validation of every field of a struct or enum variant.
fn derive_variant_is_safe(
ctx: &Ctx,
variant_id: &TokenStream,
fields: &[(&Visibility, TokenStream, &Type)],
) -> TokenStream {
let zerocopy_crate = &ctx.zerocopy_crate;
let trait_path = Trait::TryFromBytes.crate_path(ctx);
let field_names = fields.iter().map(|(_, name, _)| name);
let field_tys = fields.iter().map(|(_, _, ty)| ty);
quote! {
true #(&& {
let field_candidate = #zerocopy_crate::into_inner!(
candidate.reborrow().project::<
#zerocopy_crate::project_clients::TryFromBytesDerive,
_,
{ #variant_id },
{ #zerocopy_crate::ident_id!(#field_names) },
>()
);
<#field_tys as #trait_path>::is_safe(field_candidate)
})*
}
}

/// Generates an implementation of `is_safe` for an arbitrary enum.
///
/// For an enum with fields, [`derive_enum`] generates the representation model
Expand All @@ -35,7 +60,6 @@ pub(crate) fn derive_is_safe(
));
}

let trait_path = Trait::TryFromBytes.crate_path(ctx);
let zerocopy_crate = &ctx.zerocopy_crate;
let core = ctx.core_path();
let projections = if data.fields().is_empty() {
Expand All @@ -57,20 +81,10 @@ pub(crate) fn derive_is_safe(
let match_arms = data.variants().into_iter().map(|(variant, fields)| {
let variant = &variant.unwrap().ident;
let tag = tag_ident(variant);
let field_names = fields.iter().map(|(_, name, _)| name);
let field_tys = fields.iter().map(|(_, _, ty)| ty);
let variant_id = quote! { #zerocopy_crate::ident_id!(#variant) };
let fields_is_safe = derive_variant_is_safe(ctx, &variant_id, &fields);
quote! {
#tag => true #(&& {
let field_candidate = #zerocopy_crate::into_inner!(
candidate.reborrow().project::<
#zerocopy_crate::project_clients::TryFromBytesDerive,
_,
{ #zerocopy_crate::ident_id!(#variant) },
{ #zerocopy_crate::ident_id!(#field_names) },
>()
);
<#field_tys as #trait_path>::is_safe(field_candidate)
})*
#tag => #fields_is_safe
}
});

Expand Down Expand Up @@ -119,9 +133,8 @@ fn derive_try_from_bytes_struct(
) -> Result<TokenStream, Error> {
let extras = try_gen_trivial_is_safe(ctx, top_level).unwrap_or_else(|| {
let zerocopy_crate = &ctx.zerocopy_crate;
let fields = strct.fields();
let field_names = fields.iter().map(|(_vis, name, _ty)| name);
let field_tys = fields.iter().map(|(_vis, _name, ty)| ty);
let variant_id = quote! { #zerocopy_crate::STRUCT_VARIANT_ID };
let fields_is_safe = derive_variant_is_safe(ctx, &variant_id, &strct.fields());
let core = ctx.core_path();
quote!(
// SAFETY: We use `is_safe` to validate that each field is bit-valid,
Expand All @@ -135,15 +148,7 @@ fn derive_try_from_bytes_struct(
where
___ZcAlignment: #zerocopy_crate::invariant::Alignment,
{
true #(&& {
let field_candidate = #zerocopy_crate::into_inner!(candidate.reborrow().project::<
#zerocopy_crate::project_clients::TryFromBytesDerive,
_,
{ #zerocopy_crate::STRUCT_VARIANT_ID },
{ #zerocopy_crate::ident_id!(#field_names) }
>());
<#field_tys as #zerocopy_crate::TryFromBytes>::is_safe(field_candidate)
})*
#fields_is_safe
}
)
});
Expand Down