stratovirt/0006-Implement-a-safe-offset_of-macro-function.patch

48 lines
1.8 KiB
Diff
Raw Normal View History

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