hypervisor: aarch64: remove undefined behaviour in offset__of

The variable tmp was never initialized. Calling assume_init when the
content is not yet initialized causes immediate undefined behaviour.

We also cannot create any intermediate references because they will be
subject to the same requirements for references -- the referred object
must be valid.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2021-11-15 16:50:05 +00:00 committed by Michael
parent d3526823db
commit 57cc8bc6fe

View File

@ -36,13 +36,23 @@ pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
macro_rules! offset__of {
($str:ty, $($field:ident)+) => ({
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
let tmp = unsafe { tmp.assume_init() };
let base = &tmp as *const _ as usize;
let member = &tmp.$($field)* as *const _ as usize;
let base = tmp.as_ptr();
member - base
// Avoid warnings when nesting `unsafe` blocks.
#[allow(unused_unsafe)]
// SAFETY: The pointer is valid and aligned, just not initialised. Using `addr_of` ensures
// that we don't actually read from `base` (which would be UB) nor create an intermediate
// reference.
let member = unsafe { core::ptr::addr_of!((*base).$($field)*) } as *const u8;
// Avoid warnings when nesting `unsafe` blocks.
#[allow(unused_unsafe)]
// SAFETY: The two pointers are within the same allocated object `tmp`. All requirements
// from offset_from are upheld.
unsafe { member.offset_from(base as *const u8) as usize }
});
}
// Get the ID of a core register
#[macro_export]
macro_rules! arm64_core_reg_id {