Skip to content

Commit b6e1ec7

Browse files
authored
Merge pull request #138 from NULLx76/fix-soundness-bug
fix soundness bug
2 parents 75fe4f1 + ab69ea4 commit b6e1ec7

File tree

3 files changed

+77
-84
lines changed

3 files changed

+77
-84
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors = [
66
"Jonathan Dönszelmann <[email protected]>",
77
]
88
edition = "2021"
9-
rust-version = "1.59"
9+
rust-version = "1.79"
1010
description = "A fixed-size circular buffer"
1111
repository = "https://github.com/NULLx76/ringbuffer/"
1212
keywords = ["ring", "cyclic", "circular", "buffer", "no-std"]

src/ringbuffer_trait.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ mod iter {
395395
}
396396
}
397397

398-
impl<'rb, T, RB: RingBuffer<T>> Iterator for RingBufferDrainingIterator<'rb, T, RB> {
398+
impl<T, RB: RingBuffer<T>> Iterator for RingBufferDrainingIterator<'_, T, RB> {
399399
type Item = T;
400400

401401
fn next(&mut self) -> Option<T> {

src/with_const_generics.rs

Lines changed: 75 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::ringbuffer_trait::{RingBufferIntoIterator, RingBufferIterator, RingBufferMutIterator};
22
use crate::RingBuffer;
33
use core::iter::FromIterator;
4-
use core::mem;
54
use core::mem::MaybeUninit;
5+
use core::mem::{self, ManuallyDrop};
66
use core::ops::{Index, IndexMut};
77

88
/// The `ConstGenericRingBuffer` struct is a `RingBuffer` implementation which does not require `alloc` but
@@ -42,11 +42,14 @@ pub struct ConstGenericRingBuffer<T, const CAP: usize> {
4242

4343
impl<T, const CAP: usize> From<[T; CAP]> for ConstGenericRingBuffer<T, CAP> {
4444
fn from(value: [T; CAP]) -> Self {
45+
let v = ManuallyDrop::new(value);
4546
Self {
4647
// Safety:
4748
// T has the same layout as MaybeUninit<T>
4849
// [T; N] has the same layout as [MaybeUninit<T>; N]
49-
buf: unsafe { mem::transmute_copy(&value) },
50+
// Without ManuallyDrop this would be unsound as
51+
// transmute_copy doesn't take ownership
52+
buf: unsafe { mem::transmute_copy(&v) },
5053
readptr: 0,
5154
writeptr: CAP,
5255
}
@@ -178,12 +181,8 @@ impl<T, const CAP: usize> ConstGenericRingBuffer<T, CAP> {
178181
#[allow(clippy::let_unit_value)]
179182
let () = Self::ERROR_CAPACITY_IS_NOT_ALLOWED_TO_BE_ZERO;
180183

181-
// allow here since we are constructing an array of MaybeUninit<T>
182-
// which explicitly *is* defined behavior
183-
// https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init
184-
#[allow(clippy::uninit_assumed_init)]
185184
Self {
186-
buf: unsafe { MaybeUninit::uninit().assume_init() },
185+
buf: [const { MaybeUninit::<T>::uninit() }; CAP],
187186
writeptr: 0,
188187
readptr: 0,
189188
}
@@ -280,7 +279,6 @@ unsafe impl<T, const CAP: usize> RingBuffer<T> for ConstGenericRingBuffer<T, CAP
280279
// make sure we drop whatever is being overwritten
281280
// SAFETY: the buffer is full, so this must be initialized
282281
// : also, index has been masked
283-
// make sure we drop because it won't happen automatically
284282
ret = Some(unsafe { previous_value.assume_init() });
285283
self.readptr += 1;
286284
}
@@ -360,7 +358,10 @@ impl<T, const CAP: usize> IndexMut<usize> for ConstGenericRingBuffer<T, CAP> {
360358

361359
#[cfg(test)]
362360
mod tests {
363-
use super::*;
361+
use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer};
362+
use alloc::collections::{LinkedList, VecDeque};
363+
use alloc::string::ToString;
364+
use alloc::vec;
364365

365366
#[test]
366367
fn test_not_power_of_two() {
@@ -428,79 +429,71 @@ mod tests {
428429
}
429430
}
430431

431-
#[cfg(test)]
432-
mod tests {
433-
use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer};
434-
use alloc::collections::{LinkedList, VecDeque};
435-
use alloc::string::ToString;
436-
use alloc::vec;
437-
438-
#[test]
439-
fn from() {
440-
assert_eq!(
441-
ConstGenericRingBuffer::<i32, 3>::from([1, 2, 3]).to_vec(),
442-
vec![1, 2, 3]
443-
);
444-
445-
let v: &[i32; 3] = &[1, 2, 3];
446-
assert_eq!(
447-
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
448-
vec![1, 2, 3]
449-
);
450-
451-
let v: &[i32] = &[1, 2, 3];
452-
assert_eq!(
453-
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
454-
vec![1, 2, 3]
455-
);
456-
457-
let v: &mut [i32; 3] = &mut [1, 2, 3];
458-
assert_eq!(
459-
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
460-
vec![1, 2, 3]
461-
);
462-
463-
let v: &mut [i32] = &mut [1, 2, 3];
464-
assert_eq!(
465-
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
466-
vec![1, 2, 3]
467-
);
468-
469-
assert_eq!(
470-
ConstGenericRingBuffer::<i32, 3>::from(vec![1, 2, 3]).to_vec(),
471-
vec![1, 2, 3]
472-
);
473-
assert_eq!(
474-
ConstGenericRingBuffer::<i32, 3>::from(
475-
vec![1, 2, 3].into_iter().collect::<VecDeque<_>>()
476-
)
477-
.to_vec(),
478-
vec![1, 2, 3]
479-
);
480-
assert_eq!(
481-
ConstGenericRingBuffer::<i32, 3>::from(
482-
vec![1, 2, 3].into_iter().collect::<LinkedList<_>>()
483-
)
432+
#[test]
433+
fn from() {
434+
assert_eq!(
435+
ConstGenericRingBuffer::<i32, 3>::from([1, 2, 3]).to_vec(),
436+
vec![1, 2, 3]
437+
);
438+
439+
let v: &[i32; 3] = &[1, 2, 3];
440+
assert_eq!(
441+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
442+
vec![1, 2, 3]
443+
);
444+
445+
let v: &[i32] = &[1, 2, 3];
446+
assert_eq!(
447+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
448+
vec![1, 2, 3]
449+
);
450+
451+
let v: &mut [i32; 3] = &mut [1, 2, 3];
452+
assert_eq!(
453+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
454+
vec![1, 2, 3]
455+
);
456+
457+
let v: &mut [i32] = &mut [1, 2, 3];
458+
assert_eq!(
459+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
460+
vec![1, 2, 3]
461+
);
462+
463+
assert_eq!(
464+
ConstGenericRingBuffer::<i32, 3>::from(vec![1, 2, 3]).to_vec(),
465+
vec![1, 2, 3]
466+
);
467+
assert_eq!(
468+
ConstGenericRingBuffer::<i32, 3>::from(
469+
vec![1, 2, 3].into_iter().collect::<VecDeque<_>>()
470+
)
471+
.to_vec(),
472+
vec![1, 2, 3]
473+
);
474+
assert_eq!(
475+
ConstGenericRingBuffer::<i32, 3>::from(
476+
vec![1, 2, 3].into_iter().collect::<LinkedList<_>>()
477+
)
478+
.to_vec(),
479+
vec![1, 2, 3]
480+
);
481+
assert_eq!(
482+
ConstGenericRingBuffer::<_, 3>::from("abc".to_string()).to_vec(),
483+
vec!['a', 'b', 'c']
484+
);
485+
assert_eq!(
486+
ConstGenericRingBuffer::<_, 3>::from("abc").to_vec(),
487+
vec!['a', 'b', 'c']
488+
);
489+
assert_eq!(
490+
ConstGenericRingBuffer::<_, 3>::from(GrowableAllocRingBuffer::from(vec![1, 2, 3]))
484491
.to_vec(),
485-
vec![1, 2, 3]
486-
);
487-
assert_eq!(
488-
ConstGenericRingBuffer::<_, 3>::from("abc".to_string()).to_vec(),
489-
vec!['a', 'b', 'c']
490-
);
491-
assert_eq!(
492-
ConstGenericRingBuffer::<_, 3>::from("abc").to_vec(),
493-
vec!['a', 'b', 'c']
494-
);
495-
assert_eq!(
496-
ConstGenericRingBuffer::<_, 3>::from(GrowableAllocRingBuffer::from(vec![1, 2, 3]))
497-
.to_vec(),
498-
vec![1, 2, 3]
499-
);
500-
assert_eq!(
501-
ConstGenericRingBuffer::<_, 3>::from(AllocRingBuffer::from(vec![1, 2, 3])).to_vec(),
502-
vec![1, 2, 3]
503-
);
504-
}
492+
vec![1, 2, 3]
493+
);
494+
assert_eq!(
495+
ConstGenericRingBuffer::<_, 3>::from(AllocRingBuffer::from(vec![1, 2, 3])).to_vec(),
496+
vec![1, 2, 3]
497+
);
505498
}
506499
}

0 commit comments

Comments
 (0)