From fedcf84cb49bb9372eb440c17c9a5b808f40e7a9 Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Fri, 29 Nov 2019 10:42:57 +0100 Subject: [PATCH] Fix improper handling of overflow in `len_usize` (fix #128) This will lead to implausibly large lengths, nearly endless iterators and possibly unsound behaviour through the Drop implementation Switches the `truncate` method to refer to the common defintion of simply chopping of the test bits. (Implemented by `as`, which is defined to do this). Adds a new `saturate` method to replace the previous `truncate` method --- src/sealed.rs | 31 +++++++++++++++++++++++-------- src/spsc/mod.rs | 18 ++++++++++++++++-- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/sealed.rs b/src/sealed.rs index 82292434..46147c50 100644 --- a/src/sealed.rs +++ b/src/sealed.rs @@ -21,6 +21,9 @@ unsafe impl XCore for MultiCore { } pub unsafe trait Uxx: Into + Send { + #[doc(hidden)] + fn saturate(x: usize) -> Self; + #[doc(hidden)] fn truncate(x: usize) -> Self; @@ -39,15 +42,19 @@ pub unsafe trait Uxx: Into + Send { } unsafe impl Uxx for u8 { - fn truncate(x: usize) -> Self { - let max = ::core::u8::MAX; + fn saturate(x: usize) -> Self { + let max = Self::max_value() as usize; if x >= usize::from(max) { - max + max as Self } else { - x as u8 + x as Self } } + fn truncate(x: usize) -> Self { + x as Self + } + unsafe fn load_acquire(x: *const Self) -> Self where C: XCore, @@ -79,15 +86,19 @@ unsafe impl Uxx for u8 { } unsafe impl Uxx for u16 { - fn truncate(x: usize) -> Self { - let max = ::core::u16::MAX; + fn saturate(x: usize) -> Self { + let max = Self::max_value() as usize; if x >= usize::from(max) { - max + max as Self } else { - x as u16 + x as Self } } + fn truncate(x: usize) -> Self { + x as Self + } + unsafe fn load_acquire(x: *const Self) -> Self where C: XCore, @@ -119,6 +130,10 @@ unsafe impl Uxx for u16 { } unsafe impl Uxx for usize { + fn saturate(x: usize) -> Self { + x + } + fn truncate(x: usize) -> Self { x } diff --git a/src/spsc/mod.rs b/src/spsc/mod.rs index 444d75ac..73c86838 100644 --- a/src/spsc/mod.rs +++ b/src/spsc/mod.rs @@ -174,7 +174,7 @@ where { /// Returns the maximum number of elements the queue can hold pub fn capacity(&self) -> U { - U::truncate(N::to_usize()) + U::saturate(N::to_usize()) } /// Returns `true` if the queue has a length of 0 @@ -205,7 +205,7 @@ where let head = self.0.head.load_relaxed().into(); let tail = self.0.tail.load_relaxed().into(); - tail.wrapping_sub(head) + U::truncate(tail.wrapping_sub(head)).into() } } @@ -693,6 +693,20 @@ mod tests { assert_eq!(items.next(), None); } + #[test] + fn iter_overflow() { + let mut rb: Queue = Queue::u8(); + + rb.enqueue(0).unwrap(); + for _ in 0..300 { + let mut items = rb.iter_mut(); + assert_eq!(items.next(), Some(&mut 0)); + assert_eq!(items.next(), None); + rb.dequeue().unwrap(); + rb.enqueue(0).unwrap(); + } + } + #[test] fn iter_mut() { let mut rb: Queue = Queue::new();