From: Paolo Bonzini Date: Thu, 25 Sep 2025 08:32:23 +0000 (+0200) Subject: rust: migration: do not store raw pointers into VMStateSubsectionsWrapper X-Git-Tag: v10.2.0-rc1~64^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64bce66d6f142272415de5807f38c2b8a884c4c2;p=thirdparty%2Fqemu.git 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 --- 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 }