From cf913358ce8134e7245be9a6d97ce12ee2a6a154 Mon Sep 17 00:00:00 2001 From: David Roundy Date: Sun, 6 Feb 2022 08:51:17 -0800 Subject: [PATCH] fix undefined behavior in SetU32 same as with SetU64 before --- src/setu32.rs | 60 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/setu32.rs b/src/setu32.rs index 034b4de..f0d3aba 100644 --- a/src/setu32.rs +++ b/src/setu32.rs @@ -60,10 +60,16 @@ impl_set_methods!(SetU32); #[repr(C)] #[derive(Debug)] struct S { + b: Sbeginning, + array: u32, +} + +#[repr(C)] +#[derive(Debug)] +struct Sbeginning { sz: u32, cap: u32, bits: u32, - array: u32, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -321,7 +327,7 @@ enum Internal<'a> { /// significant bits) giving the elements in the set, and in the most /// significant bits a value representing the offset of the bitmap. Heap { - s: &'a S, + s: &'a Sbeginning, a: &'a [u32], }, /// This is for the case where the maximum number in our set is so large @@ -332,7 +338,7 @@ enum Internal<'a> { /// unique value (which we change if that unique value gets added to the /// set). Big { - s: &'a S, + s: &'a Sbeginning, a: &'a [u32], }, // The data is stored as a bitmap. This is used when the number of elements @@ -346,11 +352,11 @@ enum InternalMut<'a> { Empty, Stack(Tiny), Heap { - s: &'a mut S, + s: &'a mut Sbeginning, a: &'a mut [u32], }, Big { - s: &'a mut S, + s: &'a mut Sbeginning, a: &'a mut [u32], }, Dense { @@ -740,8 +746,8 @@ impl SetU32 { if ptr == std::ptr::null_mut() { std::alloc::handle_alloc_error(layout_for_capacity(c)); } - (*ptr).cap = (*other.0).cap; - (*ptr).bits = (*other.0).bits; + (*ptr).b.cap = (*other.0).b.cap; + (*ptr).b.bits = (*other.0).b.bits; SetU32(ptr) } } else { @@ -836,15 +842,15 @@ impl SetU32 { let ptr = self.0; let cap = 1 + mx/32 + mx/128; - let oldcap = (*ptr).cap; + let oldcap = (*ptr).b.cap; self.0 = std::alloc::realloc(ptr as *mut u8, layout_for_capacity(oldcap as usize), bytes_for_capacity(cap as usize)) as *mut S; if self.0 as usize == 0 { std::alloc::handle_alloc_error(layout_for_capacity(cap as usize)); } - (*self.0).cap = cap; - (*self.0).sz += 1; + (*self.0).b.cap = cap; + (*self.0).b.sz += 1; match self.internal_mut() { InternalMut::Dense { a, .. } => { for i in oldcap as usize .. a.len() { @@ -861,8 +867,8 @@ impl SetU32 { // This should be stored in a dense bitset. unsafe { let x = SetU32(std::alloc::alloc_zeroed(layout_for_capacity(cap as usize)) as *mut S); - (*x.0).cap = cap; - (*x.0).bits = 32; + (*x.0).b.cap = cap; + (*x.0).b.bits = 32; x } } @@ -880,8 +886,8 @@ impl SetU32 { if cap > 0 { unsafe { let x = SetU32(std::alloc::alloc_zeroed(layout_for_capacity(cap)) as *mut S); - (*x.0).cap = cap as u32; - (*x.0).bits = if bits == 0 { + (*x.0).b.cap = cap as u32; + (*x.0).b.bits = if bits == 0 { let mut b = 0; while b <= 32 { b = crate::rand::rand32(); @@ -1259,13 +1265,14 @@ impl SetU32 { Internal::Stack(Tiny::from_usize(self.0 as usize)) } else { let s = unsafe { &*self.0 }; - let a = unsafe { std::slice::from_raw_parts(&s.array as *const u32, s.cap as usize) }; - if s.bits == 0 || s.bits > 32 { - Internal::Big { s, a } - } else if s.bits == 32 { - Internal::Dense { sz: s.sz, a } + let b = &s.b; + let a = unsafe { std::slice::from_raw_parts(&s.array as *const u32, b.cap as usize) }; + if b.bits == 0 || b.bits > 32 { + Internal::Big { s: b, a } + } else if b.bits == 32 { + Internal::Dense { sz: b.sz, a } } else { - Internal::Heap { s, a } + Internal::Heap { s: b, a } } } } @@ -1277,13 +1284,14 @@ impl SetU32 { InternalMut::Stack(Tiny::from_usize(self.0 as usize)) } else { let s = unsafe { &mut *self.0 }; - let a = unsafe { std::slice::from_raw_parts_mut(&mut s.array as *mut u32, s.cap as usize) }; - if s.bits == 0 || s.bits > 32 { - InternalMut::Big { s, a } - } else if s.bits == 32 { - InternalMut::Dense { sz: &mut s.sz, a } + let b = &mut s.b; + let a = unsafe { std::slice::from_raw_parts_mut(&mut s.array as *mut u32, b.cap as usize) }; + if b.bits == 0 || b.bits > 32 { + InternalMut::Big { s: b, a } + } else if b.bits == 32 { + InternalMut::Dense { sz: &mut b.sz, a } } else { - InternalMut::Heap { s, a } + InternalMut::Heap { s: b, a } } } }