Skip to content

Commit 9f7b015

Browse files
committed
Fix: do bounds checking in index and index_mut
1 parent c3d6b9a commit 9f7b015

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

src/lib.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,10 @@ where
365365
/// Methods for volatile slices
366366
#[cfg(feature = "unstable")]
367367
impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
368+
pub fn len(&self) -> usize {
369+
self.pointer.len()
370+
}
371+
368372
/// Applies the index operation on the wrapped slice.
369373
///
370374
/// Returns a shared `Volatile` reference to the resulting subslice.
@@ -401,17 +405,27 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
401405
/// let subslice = volatile.index(1..);
402406
/// assert_eq!(subslice.index(0).read(), 2);
403407
/// ```
404-
pub fn index<I>(&self, index: I) -> VolatilePtr<I::Output, Access<R, access::NoAccess>>
408+
pub fn index<I>(
409+
&self,
410+
index: I,
411+
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, access::NoAccess>>
405412
where
406-
I: SliceIndex<[T]>,
413+
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
407414
{
415+
bounds_check(self.pointer.len(), index.clone());
416+
408417
unsafe { self.map(|slice| slice.get_unchecked_mut(index)) }
409418
}
410419

411-
pub fn index_mut<I>(&mut self, index: I) -> VolatilePtr<I::Output, Access<R, W>>
420+
pub fn index_mut<I>(
421+
&mut self,
422+
index: I,
423+
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, W>>
412424
where
413-
I: SliceIndex<[T]>,
425+
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
414426
{
427+
bounds_check(self.pointer.len(), index.clone());
428+
415429
unsafe { self.map_mut(|slice| slice.get_unchecked_mut(index)) }
416430
}
417431

@@ -913,3 +927,11 @@ where
913927
.finish()
914928
}
915929
}
930+
931+
#[cfg(feature = "unstable")]
932+
fn bounds_check(len: usize, index: impl SliceIndex<[()]>) {
933+
const MAX_ARRAY: [(); usize::MAX] = [(); usize::MAX];
934+
935+
let bound_check_slice = &MAX_ARRAY[..len];
936+
&bound_check_slice[index];
937+
}

src/tests.rs

+44
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,50 @@ fn test_slice() {
194194
assert_eq!(dst, [2, 2, 3]);
195195
}
196196

197+
#[cfg(feature = "unstable")]
198+
#[test]
199+
#[should_panic]
200+
fn test_bounds_check_1() {
201+
let val: &mut [u32] = &mut [1, 2, 3];
202+
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
203+
volatile.index_mut(3);
204+
}
205+
206+
#[cfg(feature = "unstable")]
207+
#[test]
208+
#[should_panic]
209+
fn test_bounds_check_2() {
210+
let val: &mut [u32] = &mut [1, 2, 3];
211+
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
212+
volatile.index_mut(2..1);
213+
}
214+
215+
#[cfg(feature = "unstable")]
216+
#[test]
217+
#[should_panic]
218+
fn test_bounds_check_3() {
219+
let val: &mut [u32] = &mut [1, 2, 3];
220+
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
221+
volatile.index_mut(4..); // `3..` is is still ok (see next test)
222+
}
223+
224+
#[cfg(feature = "unstable")]
225+
#[test]
226+
fn test_bounds_check_4() {
227+
let val: &mut [u32] = &mut [1, 2, 3];
228+
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
229+
assert_eq!(volatile.index_mut(3..).len(), 0);
230+
}
231+
232+
#[cfg(feature = "unstable")]
233+
#[test]
234+
#[should_panic]
235+
fn test_bounds_check_5() {
236+
let val: &mut [u32] = &mut [1, 2, 3];
237+
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
238+
volatile.index_mut(..4);
239+
}
240+
197241
#[cfg(feature = "unstable")]
198242
#[test]
199243
fn test_chunks() {

0 commit comments

Comments
 (0)