From 03fe93ad1f5a5d8f3a132ea419e4a509069e2130 Mon Sep 17 00:00:00 2001
From: ace yan <yan_ace62@126.com>
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 <yan_ace62@126.com>
---
 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

