From f0b4f036504a823ca673fee8f3bae47e1ad30894 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 26 Mar 2025 19:04:32 +0100 Subject: feat: make unsized fields not cause UB --- src/lib.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cdbb7b0..a8d5e82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,10 @@ impl Drop for OwnedAnyPtr { fn drop(&mut self) { + if self.size() == 0 { + return; + } + unsafe { dealloc( self.ptr.cast::(), @@ -153,6 +157,8 @@ impl MultiVec ) { if self.capacity != 0 { + assert_eq!(fields.as_ref().len(), self.field_arr_byte_offsets.len()); + if self.capacity == self.length { self.grow_amortized(1, &fields); } @@ -245,8 +251,10 @@ impl MultiVec let (new_layout, new_field_arr_byte_offsets) = Self::create_layout(new_capacity, &fields); - let Some(new_ptr) = NonNull::new(unsafe { - realloc(self.ptr.as_ptr().cast::(), *layout, new_layout.size()) + let Some(new_ptr) = NonNull::new(if layout.size() == 0 { + std::ptr::dangling_mut() + } else { + unsafe { realloc(self.ptr.as_ptr().cast::(), *layout, new_layout.size()) } }) else { handle_alloc_error(new_layout); }; @@ -280,7 +288,11 @@ impl MultiVec { let (layout, field_arr_byte_offsets) = Self::create_layout(capacity, fields); - let Some(ptr) = NonNull::new(unsafe { alloc(layout) }) else { + let Some(ptr) = NonNull::new(if layout.size() == 0 { + std::ptr::dangling_mut() + } else { + unsafe { alloc(layout) } + }) else { handle_alloc_error(layout); }; @@ -386,6 +398,10 @@ impl Drop for MultiVec for index in 0..self.length { for (field_index, field_size) in self.field_sizes.iter().enumerate() { + if *field_size == 0 { + continue; + } + let field_arr_byte_offset = self.field_arr_byte_offsets[field_index]; let field_arr_ptr = unsafe { self.ptr.byte_add(field_arr_byte_offset) }; @@ -403,6 +419,10 @@ impl Drop for MultiVec } if let Some(layout) = self.layout { + if layout.size() == 0 { + return; + } + unsafe { std::alloc::dealloc(self.ptr.as_ptr().cast::(), layout); } @@ -530,6 +550,17 @@ mod tests ); } + #[test] + fn push_all_unsized_fields_work() + { + struct UnsizedThing; + + let mut multi_vec = MultiVec::new(); + + multi_vec.push([OwnedAnyPtr::new(()), OwnedAnyPtr::new(UnsizedThing)]); + multi_vec.push([OwnedAnyPtr::new(()), OwnedAnyPtr::new(UnsizedThing)]); + } + //#[test] //fn multiple_pushes_in_preallocated_works() //{ -- cgit v1.2.3-18-g5258