Skip to content

Commit 1469016

Browse files
committed
fix soundness bug
1 parent 3ace401 commit 1469016

File tree

1 file changed

+75
-78
lines changed

1 file changed

+75
-78
lines changed

src/with_const_generics.rs

Lines changed: 75 additions & 78 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
}
@@ -183,7 +186,7 @@ impl<T, const CAP: usize> ConstGenericRingBuffer<T, CAP> {
183186
// https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init
184187
#[allow(clippy::uninit_assumed_init)]
185188
Self {
186-
buf: unsafe { MaybeUninit::uninit().assume_init() },
189+
buf: [const { MaybeUninit::<T>::uninit() }; CAP],
187190
writeptr: 0,
188191
readptr: 0,
189192
}
@@ -280,7 +283,6 @@ unsafe impl<T, const CAP: usize> RingBuffer<T> for ConstGenericRingBuffer<T, CAP
280283
// make sure we drop whatever is being overwritten
281284
// SAFETY: the buffer is full, so this must be initialized
282285
// : also, index has been masked
283-
// make sure we drop because it won't happen automatically
284286
ret = Some(unsafe { previous_value.assume_init() });
285287
self.readptr += 1;
286288
}
@@ -360,7 +362,10 @@ impl<T, const CAP: usize> IndexMut<usize> for ConstGenericRingBuffer<T, CAP> {
360362

361363
#[cfg(test)]
362364
mod tests {
363-
use super::*;
365+
use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer};
366+
use alloc::collections::{LinkedList, VecDeque};
367+
use alloc::string::ToString;
368+
use alloc::vec;
364369

365370
#[test]
366371
fn test_not_power_of_two() {
@@ -428,79 +433,71 @@ mod tests {
428433
}
429434
}
430435

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-
)
436+
#[test]
437+
fn from() {
438+
assert_eq!(
439+
ConstGenericRingBuffer::<i32, 3>::from([1, 2, 3]).to_vec(),
440+
vec![1, 2, 3]
441+
);
442+
443+
let v: &[i32; 3] = &[1, 2, 3];
444+
assert_eq!(
445+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
446+
vec![1, 2, 3]
447+
);
448+
449+
let v: &[i32] = &[1, 2, 3];
450+
assert_eq!(
451+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
452+
vec![1, 2, 3]
453+
);
454+
455+
let v: &mut [i32; 3] = &mut [1, 2, 3];
456+
assert_eq!(
457+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
458+
vec![1, 2, 3]
459+
);
460+
461+
let v: &mut [i32] = &mut [1, 2, 3];
462+
assert_eq!(
463+
ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(),
464+
vec![1, 2, 3]
465+
);
466+
467+
assert_eq!(
468+
ConstGenericRingBuffer::<i32, 3>::from(vec![1, 2, 3]).to_vec(),
469+
vec![1, 2, 3]
470+
);
471+
assert_eq!(
472+
ConstGenericRingBuffer::<i32, 3>::from(
473+
vec![1, 2, 3].into_iter().collect::<VecDeque<_>>()
474+
)
475+
.to_vec(),
476+
vec![1, 2, 3]
477+
);
478+
assert_eq!(
479+
ConstGenericRingBuffer::<i32, 3>::from(
480+
vec![1, 2, 3].into_iter().collect::<LinkedList<_>>()
481+
)
482+
.to_vec(),
483+
vec![1, 2, 3]
484+
);
485+
assert_eq!(
486+
ConstGenericRingBuffer::<_, 3>::from("abc".to_string()).to_vec(),
487+
vec!['a', 'b', 'c']
488+
);
489+
assert_eq!(
490+
ConstGenericRingBuffer::<_, 3>::from("abc").to_vec(),
491+
vec!['a', 'b', 'c']
492+
);
493+
assert_eq!(
494+
ConstGenericRingBuffer::<_, 3>::from(GrowableAllocRingBuffer::from(vec![1, 2, 3]))
484495
.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-
}
496+
vec![1, 2, 3]
497+
);
498+
assert_eq!(
499+
ConstGenericRingBuffer::<_, 3>::from(AllocRingBuffer::from(vec![1, 2, 3])).to_vec(),
500+
vec![1, 2, 3]
501+
);
505502
}
506503
}

0 commit comments

Comments
 (0)