Skip to content

Commit 009aca9

Browse files
authored
Merge pull request #1115 from heftig/no-offset
glib: Do not use ptr::offset/offset_from for private/impl offset
2 parents c86404b + 4e2a5e5 commit 009aca9

File tree

1 file changed

+66
-31
lines changed

1 file changed

+66
-31
lines changed

glib/src/subclass/types.rs

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,57 @@ pub unsafe trait InstanceStructExt: InstanceStruct {
8888
fn class(&self) -> &<Self::Type as ObjectSubclass>::Class;
8989
}
9090

91+
// rustdoc-stripper-ignore-next
92+
/// Offset `ptr` by `offset` *bytes* and cast the result to `*const U`.
93+
///
94+
/// The result must be a correctly aligned pointer to a valid value of type `U`.
95+
///
96+
/// # Panics:
97+
///
98+
/// This function panics if debug assertions are enabled if adding `offset` causes `ptr` to
99+
/// overflow or if the resulting pointer is not correctly aligned.
100+
#[inline]
101+
fn offset_ptr_by_bytes<T, U>(ptr: *const T, offset: isize) -> *const U {
102+
// FIXME: Use `ptr::expose_addr()` once stable
103+
let ptr = ptr as usize;
104+
let ptr = if offset < 0 {
105+
ptr - (-offset) as usize
106+
} else {
107+
ptr + offset as usize
108+
};
109+
debug_assert_eq!(ptr & (mem::align_of::<U>() - 1), 0);
110+
ptr as *const U
111+
}
112+
113+
// rustdoc-stripper-ignore-next
114+
/// Offset `ptr` by `offset` *bytes* and cast the result to `*mut U`.
115+
///
116+
/// The result must be a correctly aligned pointer to a valid value of type `U`.
117+
///
118+
/// # Panics:
119+
///
120+
/// This function panics if debug assertions are enabled if adding `offset` causes `ptr` to
121+
/// overflow or if the resulting pointer is not correctly aligned.
122+
#[inline]
123+
fn offset_ptr_by_bytes_mut<T, U>(ptr: *mut T, offset: isize) -> *mut U {
124+
// FIXME: Use `ptr::expose_addr()` once stable
125+
let ptr = ptr as usize;
126+
let ptr = if offset < 0 {
127+
ptr - (-offset) as usize
128+
} else {
129+
ptr + offset as usize
130+
};
131+
debug_assert_eq!(ptr & (mem::align_of::<U>() - 1), 0);
132+
ptr as *mut U
133+
}
134+
91135
unsafe impl<T: InstanceStruct> InstanceStructExt for T {
92136
#[inline]
93137
fn imp(&self) -> &Self::Type {
94138
unsafe {
95139
let data = Self::Type::type_data();
96140
let private_offset = data.as_ref().impl_offset();
97-
let ptr: *const u8 = self as *const _ as *const u8;
98-
let imp_ptr = ptr.offset(private_offset);
99-
let imp = imp_ptr as *const Self::Type;
100-
141+
let imp = offset_ptr_by_bytes::<T, Self::Type>(self, private_offset);
101142
&*imp
102143
}
103144
}
@@ -717,17 +758,15 @@ impl<T: ObjectSubclass> ObjectSubclassExt for T {
717758
debug_assert!(type_.is_valid());
718759

719760
let offset = -data.as_ref().impl_offset();
720-
721-
let ptr = self as *const Self as *const u8;
722-
let ptr = ptr.offset(offset);
723-
let ptr = ptr as *mut u8 as *mut <Self::Type as ObjectType>::GlibType;
761+
let ptr =
762+
offset_ptr_by_bytes::<Self, <Self::Type as ObjectType>::GlibType>(self, offset);
724763

725764
// The object might just be finalized, and in that case it's unsafe to access
726765
// it and use any API on it. This can only happen from inside the Drop impl
727766
// of Self.
728-
debug_assert_ne!((*(ptr as *mut gobject_ffi::GObject)).ref_count, 0);
767+
debug_assert_ne!((*(ptr as *const gobject_ffi::GObject)).ref_count, 0);
729768

730-
crate::BorrowedObject::new(ptr)
769+
crate::BorrowedObject::new(mut_override(ptr))
731770
}
732771
}
733772

@@ -752,10 +791,7 @@ impl<T: ObjectSubclass> ObjectSubclassExt for T {
752791
debug_assert!(self_type_.is_valid());
753792

754793
let offset = -type_data.as_ref().private_imp_offset;
755-
756-
let ptr = self as *const Self as *const u8;
757-
let ptr = ptr.offset(offset);
758-
let ptr = ptr as *const PrivateStruct<Self>;
794+
let ptr = offset_ptr_by_bytes::<Self, PrivateStruct<Self>>(self, offset);
759795
let priv_ = &*ptr;
760796

761797
match priv_.instance_data {
@@ -821,9 +857,10 @@ impl<T: ObjectSubclass> InitializingObject<T> {
821857

822858
let offset = type_data.as_ref().private_offset;
823859

824-
let ptr = self.0.as_ptr() as *mut u8;
825-
let ptr = ptr.offset(offset);
826-
let ptr = ptr as *mut PrivateStruct<T>;
860+
let ptr = offset_ptr_by_bytes_mut::<
861+
<<T as ObjectSubclass>::Type as ObjectType>::GlibType,
862+
PrivateStruct<T>,
863+
>(self.0.as_ptr(), offset);
827864
let priv_ = &mut *ptr;
828865

829866
if priv_.instance_data.is_none() {
@@ -885,8 +922,10 @@ unsafe extern "C" fn instance_init<T: ObjectSubclass>(
885922
// and actually store it in that place.
886923
let mut data = T::type_data();
887924
let private_offset = data.as_mut().private_offset;
888-
let ptr = obj as *mut u8;
889-
let priv_ptr = ptr.offset(private_offset);
925+
let priv_ptr = offset_ptr_by_bytes_mut::<gobject_ffi::GTypeInstance, PrivateStruct<T>>(
926+
obj,
927+
private_offset,
928+
);
890929

891930
assert!(
892931
priv_ptr as usize & (mem::align_of::<PrivateStruct<T>>() - 1) == 0,
@@ -897,13 +936,11 @@ unsafe extern "C" fn instance_init<T: ObjectSubclass>(
897936
2 * mem::size_of::<usize>(),
898937
);
899938

900-
let priv_storage = priv_ptr as *mut PrivateStruct<T>;
901-
902939
let klass = &*(klass as *const T::Class);
903940

904941
let imp = T::with_class(klass);
905942
ptr::write(
906-
priv_storage,
943+
priv_ptr,
907944
PrivateStruct {
908945
imp,
909946
instance_data: None,
@@ -925,11 +962,10 @@ unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject)
925962
// Retrieve the private struct and drop it for freeing all associated memory.
926963
let mut data = T::type_data();
927964
let private_offset = data.as_mut().private_offset;
928-
let ptr = obj as *mut u8;
929-
let priv_ptr = ptr.offset(private_offset);
930-
let priv_storage = &mut *(priv_ptr as *mut PrivateStruct<T>);
931-
ptr::drop_in_place(&mut priv_storage.imp);
932-
ptr::drop_in_place(&mut priv_storage.instance_data);
965+
let priv_ptr =
966+
offset_ptr_by_bytes_mut::<gobject_ffi::GObject, PrivateStruct<T>>(obj, private_offset);
967+
ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).imp));
968+
ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).instance_data));
933969

934970
// Chain up to the parent class' finalize implementation, if any.
935971
let parent_class = &*(data.as_ref().parent_class() as *const gobject_ffi::GObjectClass);
@@ -996,11 +1032,10 @@ pub fn register_type<T: ObjectSubclass>() -> Type {
9961032
// some hoops because Rust doesn't have an offsetof operator yet.
9971033
data.as_mut().private_imp_offset = {
9981034
// Must not be a dangling pointer so let's create some uninitialized memory
999-
let priv_ = std::mem::MaybeUninit::<PrivateStruct<T>>::uninit();
1035+
let priv_ = mem::MaybeUninit::<PrivateStruct<T>>::uninit();
10001036
let ptr = priv_.as_ptr();
1001-
let imp_ptr = std::ptr::addr_of!((*ptr).imp) as *const u8;
1002-
let ptr = ptr as *const u8;
1003-
imp_ptr.offset_from(ptr)
1037+
let imp_ptr = ptr::addr_of!((*ptr).imp);
1038+
(imp_ptr as isize) - (ptr as isize)
10041039
};
10051040

10061041
let iface_types = T::Interfaces::iface_infos();

0 commit comments

Comments
 (0)