summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-03-26 19:04:32 +0100
committerHampusM <hampus@hampusmat.com>2025-03-28 11:52:00 +0100
commitf0b4f036504a823ca673fee8f3bae47e1ad30894 (patch)
treeb97461c087f58e9415bd66317cd93de2f4931150 /src
parent1425685ad623d68484a11040802fe8d25aa95395 (diff)
feat: make unsized fields not cause UB
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs37
1 files changed, 34 insertions, 3 deletions
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::<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()
//{