diff options
author | HampusM <hampus@hampusmat.com> | 2025-03-26 19:04:32 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-03-28 11:52:00 +0100 |
commit | f0b4f036504a823ca673fee8f3bae47e1ad30894 (patch) | |
tree | b97461c087f58e9415bd66317cd93de2f4931150 /src | |
parent | 1425685ad623d68484a11040802fe8d25aa95395 (diff) |
feat: make unsized fields not cause UB
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 37 |
1 files changed, 34 insertions, 3 deletions
@@ -42,6 +42,10 @@ impl Drop for OwnedAnyPtr { fn drop(&mut self) { + if self.size() == 0 { + return; + } + unsafe { dealloc( self.ptr.cast::<u8>(), @@ -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::<u8>(), *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::<u8>(), *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::<u8>(), 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() //{ |