mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-28 04:50:34 +00:00
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
This commit is contained in:
parent
5ffd0df2cc
commit
fedcf84cb4
@ -21,6 +21,9 @@ unsafe impl XCore for MultiCore {
|
||||
}
|
||||
|
||||
pub unsafe trait Uxx: Into<usize> + Send {
|
||||
#[doc(hidden)]
|
||||
fn saturate(x: usize) -> Self;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn truncate(x: usize) -> Self;
|
||||
|
||||
@ -39,15 +42,19 @@ pub unsafe trait Uxx: Into<usize> + 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<C>(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<C>(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
|
||||
}
|
||||
|
@ -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<i32, U4, u8> = 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<i32, U4> = Queue::new();
|
||||
|
Loading…
x
Reference in New Issue
Block a user