From 7afef5fb91c4b55296adee0d7f2e950d0bd9652e Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Thu, 23 Apr 2026 18:07:05 +0200 Subject: [PATCH 1/5] Remove usage of the deprecated push method --- fuzz/fuzz_targets/arbitrary_ops/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzz/fuzz_targets/arbitrary_ops/mod.rs b/fuzz/fuzz_targets/arbitrary_ops/mod.rs index b53731d7..c162c945 100644 --- a/fuzz/fuzz_targets/arbitrary_ops/mod.rs +++ b/fuzz/fuzz_targets/arbitrary_ops/mod.rs @@ -272,7 +272,7 @@ impl MutableBitmapOperation { if should_push { x.add(n); } - assert_eq!(should_push, y.push(n)); + assert_eq!(should_push, y.try_push(n).is_ok()); } MutableBitmapOperation::Remove(Num(n)) => { let expected = x.remove_checked(n); From 55fd8e384da3d9a339a4a9e82e26a738844b6ab0 Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Thu, 23 Apr 2026 18:07:28 +0200 Subject: [PATCH 2/5] Bump the roaring patch version --- fuzz/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index fc33a58f..ee227195 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -139,7 +139,7 @@ checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "roaring" -version = "0.11.2" +version = "0.11.3" dependencies = [ "bytemuck", "byteorder", From f862f6b62719a74a0ed319d735ae0d4c4f6908d0 Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Thu, 23 Apr 2026 18:10:25 +0200 Subject: [PATCH 3/5] Add a test to repro the bug --- roaring/src/bitmap/store/interval_store.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/roaring/src/bitmap/store/interval_store.rs b/roaring/src/bitmap/store/interval_store.rs index 86b20223..1da52a68 100644 --- a/roaring/src/bitmap/store/interval_store.rs +++ b/roaring/src/bitmap/store/interval_store.rs @@ -2477,6 +2477,27 @@ mod tests { assert_eq!(iter.nth(u16::MAX as usize), None); } + // Regression test for https://github.com/RoaringBitmap/roaring-rs/issues/352 + #[test] + #[allow(clippy::iter_nth_zero)] + fn iter_nth_single_element_intervals() { + // A RunStore made of single-element intervals {0,0}, {2,2}, ..., {246,246}. + // nth(123) must return 246 (index 123 in the sequence 0, 2, 4, ...). + // The buggy code returned 244 (index 122). + let intervals: alloc::vec::Vec<_> = + (0u16..=246).step_by(2).map(|v| Interval::new_unchecked(v, v)).collect(); + let interval_store = IntervalStore(intervals); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(0), Some(0)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(1), Some(2)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(123), Some(246)); + } + #[test] fn iter_advance_to() { let interval_store = IntervalStore(alloc::vec![ From 631ffcbb220060071069df3dd6df88657e6cf197 Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Thu, 23 Apr 2026 18:27:17 +0200 Subject: [PATCH 4/5] Fix the bug --- roaring/src/bitmap/store/interval_store.rs | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/roaring/src/bitmap/store/interval_store.rs b/roaring/src/bitmap/store/interval_store.rs index 1da52a68..2cb508fc 100644 --- a/roaring/src/bitmap/store/interval_store.rs +++ b/roaring/src/bitmap/store/interval_store.rs @@ -862,23 +862,23 @@ impl> Iterator for RunIter { self.backward_offset = 0; return None; } - if let Some(skip) = n.checked_sub(1) { - let mut to_skip = skip as u64; - loop { - let full_first_interval_len = self.intervals.as_slice().first()?.run_len(); - let consumed_len = u64::from(self.forward_offset) - + if self.intervals.as_slice().len() == 1 { - u64::from(self.backward_offset) - } else { - 0 - }; - let to_remove = (full_first_interval_len - consumed_len).min(to_skip); - to_skip -= to_remove; - self.forward_offset += to_remove as u16; + let mut to_skip = n as u64; + loop { + let full_first_interval_len = self.intervals.as_slice().first()?.run_len(); + let consumed_len = u64::from(self.forward_offset) + + if self.intervals.as_slice().len() == 1 { + u64::from(self.backward_offset) + } else { + 0 + }; + let to_remove = (full_first_interval_len - consumed_len).min(to_skip); + to_skip -= to_remove; + self.forward_offset += to_remove as u16; + if consumed_len + to_remove >= full_first_interval_len { self.move_next(); - if to_skip == 0 { - break; - } + } + if to_skip == 0 { + break; } } self.next() From 63738a19dc93b2fb13a830215856e836618b2915 Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Thu, 23 Apr 2026 18:37:59 +0200 Subject: [PATCH 5/5] Bump the version to 0.11.4 --- fuzz/Cargo.lock | 2 +- roaring/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index ee227195..8545b3f4 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -139,7 +139,7 @@ checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "roaring" -version = "0.11.3" +version = "0.11.4" dependencies = [ "bytemuck", "byteorder", diff --git a/roaring/Cargo.toml b/roaring/Cargo.toml index f4f9310d..17f74493 100644 --- a/roaring/Cargo.toml +++ b/roaring/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "roaring" -version = "0.11.3" +version = "0.11.4" # When changing this value don't forget to change the MSRV test in `.github/workflows/test.yml`!! rust-version = "1.90.0" authors = ["Wim Looman ", "Kerollmops "]