From 03fe93ad1f5a5d8f3a132ea419e4a509069e2130 Mon Sep 17 00:00:00 2001 From: ace yan Date: Sun, 20 Feb 2022 14:57:34 +0800 Subject: [PATCH 01/10] Implement a safe offset_of macro function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original offset_of macro implementation reference to packed field is unaligned, and creating a misaligned reference is undefined behavior。 In the higher version of the rustc compiler, there will be a compilation warning prompt: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! Signed-off-by: Yan Wen --- util/src/offsetof.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/util/src/offsetof.rs b/util/src/offsetof.rs index c2696c8..a6b55d8 100644 --- a/util/src/offsetof.rs +++ b/util/src/offsetof.rs @@ -13,9 +13,17 @@ /// Macro: Calculate offset of specified field in a type. #[macro_export] macro_rules! __offset_of { - ($type_name:ty, $field:ident) => { - unsafe { &(*(std::ptr::null::<$type_name>())).$field as *const _ as usize } - }; + ($type_name:ty, $field:ident) => {{ + let tmp = core::mem::MaybeUninit::<$type_name>::uninit(); + let outer = tmp.as_ptr(); + // Safe because the pointer is valid and aligned, just not initialised; `addr_of` ensures that + // we don't actually read from `outer` (which would be UB) nor create an intermediate reference. + let inner = unsafe { core::ptr::addr_of!((*outer).$field) } as *const u8; + // Safe because the two pointers are within the same allocation block. + unsafe { + inner.offset_from(outer as *const u8) as usize + } + }}; } /// Macro: Calculate offset of a field in a recursive type. -- 2.25.1