From 32bd99d20329b7614e54dbaab6c565f856e4944b Mon Sep 17 00:00:00 2001 From: Tim Denk Date: Fri, 10 Jul 2026 12:08:58 +0200 Subject: [PATCH] add missing {forward,backward}_overflowing impls --- src/addr.rs | 44 +++++++++++++++++++++++++++ src/structures/paging/page.rs | 40 +++++++++++++++++++++++++ src/structures/paging/page_table.rs | 46 +++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/src/addr.rs b/src/addr.rs index b0b544b6..d9cc4fcf 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -485,6 +485,30 @@ impl Step for VirtAddr { fn backward_checked(start: Self, count: usize) -> Option { Self::backward_checked_u64(start, u64::try_from(count).ok()?) } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + #[inline] + fn forward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::forward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + #[inline] + fn backward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::backward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } } #[cfg(kani)] @@ -936,6 +960,26 @@ mod tests { ); } + #[test] + #[cfg(feature = "step_trait")] + fn virtaddr_step_overflowing() { + assert_eq!( + Step::forward_overflowing(VirtAddr(0x7fff_ffff_ffff), 1), + (VirtAddr(0xffff_8000_0000_0000), false) + ); + assert_eq!( + Step::backward_overflowing(VirtAddr(0xffff_8000_0000_0000), 1), + (VirtAddr(0x7fff_ffff_ffff), false) + ); + assert_eq!( + Step::forward_overflowing(VirtAddr(0), 0), + (VirtAddr(0), false) + ); + + assert!(Step::forward_overflowing(VirtAddr(0xffff_ffff_ffff_ffff), 1).1); + assert!(Step::backward_overflowing(VirtAddr(0), 1).1); + } + #[test] pub fn test_align_up() { // align 1 diff --git a/src/structures/paging/page.rs b/src/structures/paging/page.rs index 42e0fa94..b4e7a4e6 100644 --- a/src/structures/paging/page.rs +++ b/src/structures/paging/page.rs @@ -322,6 +322,28 @@ impl Step for Page { size: PhantomData, }) } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + fn forward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::forward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + fn backward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::backward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } } /// A range of pages with exclusive upper bound. @@ -914,6 +936,24 @@ mod tests { assert_eq!(Step::steps_between(&start, &end), (lower, upper)); } } + + #[test] + #[cfg(feature = "step_trait")] + fn page_step_overflowing() { + let page = |addr| Page::::from_start_address(VirtAddr::new(addr)).unwrap(); + + assert_eq!( + Step::forward_overflowing(page(0x7fff_ffff_f000), 1), + (page(0xffff_8000_0000_0000), false) + ); + assert_eq!( + Step::backward_overflowing(page(0xffff_8000_0000_0000), 1), + (page(0x7fff_ffff_f000), false) + ); + + assert!(Step::forward_overflowing(page(0xffff_ffff_ffff_f000), 1).1); + assert!(Step::backward_overflowing(page(0), 1).1); + } } #[cfg(kani)] diff --git a/src/structures/paging/page_table.rs b/src/structures/paging/page_table.rs index 5ccfe536..43cb4b33 100644 --- a/src/structures/paging/page_table.rs +++ b/src/structures/paging/page_table.rs @@ -388,6 +388,30 @@ impl Step for PageTableIndex { let idx = usize::from(start).checked_sub(count)?; Some(Self::new(idx as u16)) } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + #[inline] + fn forward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::forward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } + + // Kani's bundled toolchain predates these methods being added to `Step`. + // Exclude them there so the crate still compiles under `cargo kani`. + // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later. + #[cfg(not(kani))] + #[inline] + fn backward_overflowing(start: Self, count: usize) -> (Self, bool) { + match Self::backward_checked(start, count) { + Some(next) => (next, false), + None => (start, true), + } + } } /// A 12-bit offset into a 4KiB Page. @@ -485,3 +509,25 @@ impl PageTableLevel { 1u64 << (((self as u8 - 1) * 9) + 12) } } + +#[cfg(all(test, feature = "step_trait"))] +mod tests { + use super::*; + use core::iter::Step; + + #[test] + fn page_table_index_step_overflowing() { + assert_eq!( + Step::forward_overflowing(PageTableIndex::new(0), 511), + (PageTableIndex::new(511), false) + ); + assert_eq!( + Step::backward_overflowing(PageTableIndex::new(511), 511), + (PageTableIndex::new(0), false) + ); + + // Overflow the 0..512 range: only the flag is specified. + assert!(Step::forward_overflowing(PageTableIndex::new(511), 1).1); + assert!(Step::backward_overflowing(PageTableIndex::new(0), 1).1); + } +}