mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-11 14:33:32 +00:00
Avoid returning a slice with a null pointer from Iter.as_slice()
core::slice::Iter.ptr can be null when iterating a slice of zero-sized elements, but the pointer value used for the slice itself cannot. Handle this case by always returning a dummy pointer for slices of zero-sized elements.
This commit is contained in:
parent
e1e34e9275
commit
f2614f5858
@ -728,29 +728,29 @@ macro_rules! iterator {
|
||||
}
|
||||
|
||||
macro_rules! make_slice {
|
||||
($t: ty => $result: ty: $start: expr, $end: expr) => {{
|
||||
let diff = ($end as usize).wrapping_sub($start as usize);
|
||||
let len = if mem::size_of::<T>() == 0 {
|
||||
diff
|
||||
($start: expr, $end: expr) => {{
|
||||
let start = $start;
|
||||
let diff = ($end as usize).wrapping_sub(start as usize);
|
||||
if size_from_ptr(start) == 0 {
|
||||
// use a non-null pointer value
|
||||
unsafe { from_raw_parts(1 as *const _, diff) }
|
||||
} else {
|
||||
diff / mem::size_of::<$t>()
|
||||
};
|
||||
unsafe {
|
||||
from_raw_parts($start, len)
|
||||
let len = diff / size_from_ptr(start);
|
||||
unsafe { from_raw_parts(start, len) }
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! make_mut_slice {
|
||||
($t: ty => $result: ty: $start: expr, $end: expr) => {{
|
||||
let diff = ($end as usize).wrapping_sub($start as usize);
|
||||
let len = if mem::size_of::<T>() == 0 {
|
||||
diff
|
||||
($start: expr, $end: expr) => {{
|
||||
let start = $start;
|
||||
let diff = ($end as usize).wrapping_sub(start as usize);
|
||||
if size_from_ptr(start) == 0 {
|
||||
// use a non-null pointer value
|
||||
unsafe { from_raw_parts_mut(1 as *mut _, diff) }
|
||||
} else {
|
||||
diff / mem::size_of::<$t>()
|
||||
};
|
||||
unsafe {
|
||||
from_raw_parts_mut($start, len)
|
||||
let len = diff / size_from_ptr(start);
|
||||
unsafe { from_raw_parts_mut(start, len) }
|
||||
}
|
||||
}}
|
||||
}
|
||||
@ -773,7 +773,7 @@ impl<'a, T> Iter<'a, T> {
|
||||
/// iterator can continue to be used while this exists.
|
||||
#[unstable(feature = "core")]
|
||||
pub fn as_slice(&self) -> &'a [T] {
|
||||
make_slice!(T => &'a [T]: self.ptr, self.end)
|
||||
make_slice!(self.ptr, self.end)
|
||||
}
|
||||
|
||||
// Helper function for Iter::nth
|
||||
@ -841,12 +841,12 @@ impl<'a, T> IterMut<'a, T> {
|
||||
/// restricted lifetimes that do not consume the iterator.
|
||||
#[unstable(feature = "core")]
|
||||
pub fn into_slice(self) -> &'a mut [T] {
|
||||
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
|
||||
make_mut_slice!(self.ptr, self.end)
|
||||
}
|
||||
|
||||
// Helper function for IterMut::nth
|
||||
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
|
||||
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
|
||||
match make_mut_slice!(self.ptr, self.end).get_mut(n) {
|
||||
Some(elem_ref) => unsafe {
|
||||
self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
|
||||
Some(slice_ref!(elem_ref))
|
||||
|
@ -10,8 +10,26 @@
|
||||
|
||||
// compile-flags: -C debug-assertions
|
||||
|
||||
#![feature(core)]
|
||||
|
||||
use std::slice;
|
||||
|
||||
fn foo<T>(v: &[T]) -> Option<&[T]> {
|
||||
let mut it = v.iter();
|
||||
for _ in 0..5 {
|
||||
let _ = it.next();
|
||||
}
|
||||
Some(it.as_slice())
|
||||
}
|
||||
|
||||
fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> {
|
||||
let mut it = v.iter_mut();
|
||||
for _ in 0..5 {
|
||||
let _ = it.next();
|
||||
}
|
||||
Some(it.into_slice())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// In a slice of zero-size elements the pointer is meaningless.
|
||||
// Ensure iteration still works even if the pointer is at the end of the address space.
|
||||
@ -24,11 +42,19 @@ pub fn main() {
|
||||
assert!(it.nth(5).is_some());
|
||||
assert_eq!(it.count(), 4);
|
||||
|
||||
// Converting Iter to a slice should never have a null pointer
|
||||
assert!(foo(slice).is_some());
|
||||
|
||||
// Test mutable iterators as well
|
||||
let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) };
|
||||
assert_eq!(slice.len(), 10);
|
||||
assert_eq!(slice.iter_mut().count(), 10);
|
||||
|
||||
let mut it = slice.iter_mut();
|
||||
assert!(it.nth(5).is_some());
|
||||
assert_eq!(it.count(), 4);
|
||||
{
|
||||
let mut it = slice.iter_mut();
|
||||
assert!(it.nth(5).is_some());
|
||||
assert_eq!(it.count(), 4);
|
||||
}
|
||||
|
||||
assert!(foo_mut(slice).is_some())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user