From 64bce66d6f142272415de5807f38c2b8a884c4c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Sep 2025 10:32:23 +0200 Subject: [PATCH] rust: migration: do not store raw pointers into VMStateSubsectionsWrapper Raw pointers were used to insert a NULL one at the end of the array. However, Option<&...> has the same layout and does not remove Sync from the type of the array. As an extra benefit, this enables validation of the terminator of the subsection array, because is_null() in const context would not be stable until Rust 1.84. Reviewed-by: Zhao Liu Signed-off-by: Paolo Bonzini --- rust/migration/src/vmstate.rs | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 2e320262f0..a6ee7e9385 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -470,33 +470,21 @@ macro_rules! impl_vmstate_struct { }; } -/// A transparent wrapper type for the `subsections` field of -/// [`VMStateDescription`]. -/// -/// This is necessary to be able to declare subsection descriptions as statics, -/// because the only way to implement `Sync` for a foreign type (and `*const` -/// pointers are foreign types in Rust) is to create a wrapper struct and -/// `unsafe impl Sync` for it. -/// -/// This struct is used in the -/// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation. -#[repr(transparent)] -pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]); - -unsafe impl Sync for VMStateSubsectionsWrapper {} +/// The type returned by [`vmstate_subsections!`](crate::vmstate_subsections). +pub type VMStateSubsections = &'static [Option<&'static crate::bindings::VMStateDescription>]; /// Helper macro to declare a list of subsections ([`VMStateDescription`]) /// into a static and return a pointer to the array of pointers it created. #[macro_export] macro_rules! vmstate_subsections { ($($subsection:expr),*$(,)*) => {{ - static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[ + static _SUBSECTIONS: $crate::vmstate::VMStateSubsections = &[ $({ static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection.get(); - ::core::ptr::addr_of!(_SUBSECTION) + Some(&_SUBSECTION) }),*, - ::core::ptr::null() - ]); + None, + ]; &_SUBSECTIONS }} } @@ -686,8 +674,9 @@ impl VMStateDescriptionBuilder { } #[must_use] - pub const fn subsections(mut self, subs: &'static VMStateSubsectionsWrapper) -> Self { - self.0.subsections = subs.0.as_ptr(); + pub const fn subsections(mut self, subs: &'static VMStateSubsections) -> Self { + let subs: *const Option<&bindings::VMStateDescription> = subs.as_ptr(); + self.0.subsections = subs.cast::<*const bindings::VMStateDescription>(); self }