diff --git a/src/bitset/serialization.rs b/src/bitset/serialization.rs index bf4715b..7152b0c 100644 --- a/src/bitset/serialization.rs +++ b/src/bitset/serialization.rs @@ -29,7 +29,10 @@ where let mut block_indices: BlockIndices = unsafe{MaybeUninit::zeroed().assume_init()}; mask.for_each_bit(|i|{ block_indices.as_mut()[i] = *index_offset; - *index_offset += Primitive::ONE; + // Allowed to overflow here, on the very last round with + // BlockIndices::Item=u8 and 256bit config. + // (root level with 256 items) + *index_offset = index_offset.wrapping_add(Primitive::ONE); }); block_indices }; diff --git a/src/primitive.rs b/src/primitive.rs index e26daef..333bbf6 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -36,6 +36,7 @@ pub trait Primitive: fn trailing_zeros(self) -> u32; fn wrapping_neg(self) -> Self; + fn wrapping_add(self, rhs: Self) -> Self; fn is_zero(self) -> bool; } @@ -69,6 +70,11 @@ macro_rules! impl_primitive { self.wrapping_neg() } + #[inline] + fn wrapping_add(self, rhs: Self) -> Self { + self.wrapping_add(rhs) + } + #[inline] fn is_zero(self) -> bool { self == 0 diff --git a/tests/serde.rs b/tests/serde.rs index 019feac..57c2674 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -1,9 +1,11 @@ use rand::{thread_rng, Rng}; -type BitSet = hi_sparse_bitset::BitSet; - +/// For issue https://github.com/tower120/hi_sparse_bitset/pull/47 #[test] -fn serde() { +#[cfg_attr(miri, ignore)] +fn regression_deserialization_256bit_arithmetic_overflow() { + type BitSet = hi_sparse_bitset::BitSet; + let mut rng = thread_rng(); let bitset: BitSet = (0..BitSet::max_capacity()) .filter(|_| rng.gen())