diff --git a/zerocopy/src/lib.rs b/zerocopy/src/lib.rs index 9334924d22..40b835610e 100644 --- a/zerocopy/src/lib.rs +++ b/zerocopy/src/lib.rs @@ -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::().as_ref()).into()) @@ -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()), } @@ -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::().as_ref()).into()) @@ -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()), } @@ -3399,7 +3399,7 @@ fn try_ref_from_prefix_suffix Ok((valid.as_ref(), prefix_suffix.as_ref())), Err(e) => Err(e.map_src(|src| src.as_bytes::().as_ref()).into()), } @@ -3419,7 +3419,7 @@ fn try_mut_from_prefix_suffix Ok((valid.as_mut(), prefix_suffix.as_mut())), Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()), } diff --git a/zerocopy/src/pointer/ptr.rs b/zerocopy/src/pointer/ptr.rs index fbc469ed87..0e6aa298f9 100644 --- a/zerocopy/src/pointer/ptr.rs +++ b/zerocopy/src/pointer/ptr.rs @@ -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( + pub fn try_into_safe( mut self, ) -> Result, ValidityError> where diff --git a/zerocopy/src/util/macro_util.rs b/zerocopy/src/util/macro_util.rs index 9dd4eb3aa0..f374a089f4 100644 --- a/zerocopy/src/util/macro_util.rs +++ b/zerocopy/src/util/macro_util.rs @@ -633,7 +633,7 @@ where let res = ptr.try_with(#[inline(always)] |ptr| { let ptr = ptr.recall_validity::(); let ptr = ptr.cast::<_, crate::layout::CastFrom, _>(); - ptr.try_into_valid() + ptr.try_into_safe() }); match res { Ok(ptr) => { @@ -696,7 +696,7 @@ where ptr.try_with_unchecked(#[inline(always)] |ptr| { let ptr = ptr.recall_validity::(); let ptr = ptr.cast::<_, crate::layout::CastFrom, _>(); - ptr.try_into_valid() + ptr.try_into_safe() }) }; match res { diff --git a/zerocopy/zerocopy-derive/src/derive/try_from_bytes.rs b/zerocopy/zerocopy-derive/src/derive/try_from_bytes.rs index 0b18f4d46c..924a63fc75 100644 --- a/zerocopy/zerocopy-derive/src/derive/try_from_bytes.rs +++ b/zerocopy/zerocopy-derive/src/derive/try_from_bytes.rs @@ -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::{ @@ -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 @@ -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() { @@ -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 } }); @@ -119,9 +133,8 @@ fn derive_try_from_bytes_struct( ) -> Result { 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, @@ -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 } ) });