From e58e5e15263d3a27f1a86101a9cb49e1b69bd69c Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Wed, 13 Apr 2022 11:37:36 +0200 Subject: [PATCH 1/4] fix `VirtAddr::align_up` & `VirtAddr::align_down` --- src/addr.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/addr.rs b/src/addr.rs index e6179268a..a13fa6a18 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -158,12 +158,17 @@ impl VirtAddr { /// Aligns the virtual address upwards to the given alignment. /// /// See the `align_up` function for more information. + /// + /// # Panics + /// + /// This function panics if the resulting address is higher than + /// `0xffff_ffff_ffff_ffff`. #[inline] pub fn align_up(self, align: U) -> Self where U: Into, { - VirtAddr(align_up(self.0, align.into())) + VirtAddr::new_truncate(align_up(self.0, align.into())) } /// Aligns the virtual address downwards to the given alignment. @@ -174,7 +179,7 @@ impl VirtAddr { where U: Into, { - VirtAddr(align_down(self.0, align.into())) + VirtAddr::new_truncate(align_down(self.0, align.into())) } /// Checks whether the virtual address has the demanded alignment. @@ -791,4 +796,22 @@ mod tests { assert_eq!(align_up(0, 2), 0); assert_eq!(align_up(0, 0x8000_0000_0000_0000), 0); } + + #[test] + fn test_virt_addr_align_up() { + // Make sure the 47th bit is extended. + assert_eq!( + VirtAddr::new(0x7fff_ffff_ffff).align_up(2u64), + VirtAddr::new(0xffff_8000_0000_0000) + ); + } + + #[test] + fn test_virt_addr_align_down() { + // Make sure the 47th bit is extended. + assert_eq!( + VirtAddr::new(0xffff_8000_0000_0000).align_down(1u64 << 48), + VirtAddr::new(0) + ); + } } From e0c56797a04ed7c9769d6cafec40bde4c7137186 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Wed, 13 Apr 2022 11:42:07 +0200 Subject: [PATCH 2/4] fix `PhysAddr::align_up` --- src/addr.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/addr.rs b/src/addr.rs index a13fa6a18..d1549770d 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -483,12 +483,17 @@ impl PhysAddr { /// Aligns the physical address upwards to the given alignment. /// /// See the `align_up` function for more information. + /// + /// # Panics + /// + /// This function panics if the resulting address has a bit in the range 52 + /// to 64 set. #[inline] pub fn align_up(self, align: U) -> Self where U: Into, { - PhysAddr(align_up(self.0, align.into())) + PhysAddr::new(align_up(self.0, align.into())) } /// Aligns the physical address downwards to the given alignment. From 9e377c406af228c363fca2927ca8a59f5594d53d Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Thu, 14 Apr 2022 09:54:50 +0200 Subject: [PATCH 3/4] explicitly check for overflow --- src/addr.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/addr.rs b/src/addr.rs index d1549770d..1b2087284 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -647,7 +647,7 @@ pub const fn align_down(addr: u64, align: u64) -> u64 { /// /// Returns the smallest `x` with alignment `align` so that `x >= addr`. /// -/// Panics if the alignment is not a power of two. +/// Panics if the alignment is not a power of two or if an overflow occurs. #[inline] pub const fn align_up(addr: u64, align: u64) -> u64 { assert!(align.is_power_of_two(), "`align` must be a power of two"); @@ -655,7 +655,12 @@ pub const fn align_up(addr: u64, align: u64) -> u64 { if addr & align_mask == 0 { addr // already aligned } else { - (addr | align_mask) + 1 + // FIXME: Replace with .expect, once `Option::expect` is const. + if let Some(aligned) = (addr | align_mask).checked_add(1) { + aligned + } else { + panic!("attempt to add with overflow") + } } } From 49b920493c423b6a2cd7a226fe1dc22c8b472e08 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Thu, 14 Apr 2022 09:55:11 +0200 Subject: [PATCH 4/4] add overflow tests --- src/addr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/addr.rs b/src/addr.rs index 1b2087284..d3bec6a8b 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -824,4 +824,16 @@ mod tests { VirtAddr::new(0) ); } + + #[test] + #[should_panic] + fn test_virt_addr_align_up_overflow() { + VirtAddr::new(0xffff_ffff_ffff_ffff).align_up(2u64); + } + + #[test] + #[should_panic] + fn test_phys_addr_align_up_overflow() { + PhysAddr::new(0x000f_ffff_ffff_ffff).align_up(2u64); + } }