提交 f2614f58 编写于 作者: K Kevin Ballard

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.
上级 e1e34e92
...@@ -728,29 +728,29 @@ fn next_back(&mut self) -> Option<$elem> { ...@@ -728,29 +728,29 @@ fn next_back(&mut self) -> Option<$elem> {
} }
macro_rules! make_slice { macro_rules! make_slice {
($t: ty => $result: ty: $start: expr, $end: expr) => {{ ($start: expr, $end: expr) => {{
let diff = ($end as usize).wrapping_sub($start as usize); let start = $start;
let len = if mem::size_of::<T>() == 0 { let diff = ($end as usize).wrapping_sub(start as usize);
diff if size_from_ptr(start) == 0 {
// use a non-null pointer value
unsafe { from_raw_parts(1 as *const _, diff) }
} else { } else {
diff / mem::size_of::<$t>() let len = diff / size_from_ptr(start);
}; unsafe { from_raw_parts(start, len) }
unsafe {
from_raw_parts($start, len)
} }
}} }}
} }
macro_rules! make_mut_slice { macro_rules! make_mut_slice {
($t: ty => $result: ty: $start: expr, $end: expr) => {{ ($start: expr, $end: expr) => {{
let diff = ($end as usize).wrapping_sub($start as usize); let start = $start;
let len = if mem::size_of::<T>() == 0 { let diff = ($end as usize).wrapping_sub(start as usize);
diff if size_from_ptr(start) == 0 {
// use a non-null pointer value
unsafe { from_raw_parts_mut(1 as *mut _, diff) }
} else { } else {
diff / mem::size_of::<$t>() let len = diff / size_from_ptr(start);
}; unsafe { from_raw_parts_mut(start, len) }
unsafe {
from_raw_parts_mut($start, len)
} }
}} }}
} }
...@@ -773,7 +773,7 @@ impl<'a, T> Iter<'a, T> { ...@@ -773,7 +773,7 @@ impl<'a, T> Iter<'a, T> {
/// iterator can continue to be used while this exists. /// iterator can continue to be used while this exists.
#[unstable(feature = "core")] #[unstable(feature = "core")]
pub fn as_slice(&self) -> &'a [T] { 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 // Helper function for Iter::nth
...@@ -841,12 +841,12 @@ impl<'a, T> IterMut<'a, T> { ...@@ -841,12 +841,12 @@ impl<'a, T> IterMut<'a, T> {
/// restricted lifetimes that do not consume the iterator. /// restricted lifetimes that do not consume the iterator.
#[unstable(feature = "core")] #[unstable(feature = "core")]
pub fn into_slice(self) -> &'a mut [T] { 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 // Helper function for IterMut::nth
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> { 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 { Some(elem_ref) => unsafe {
self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
Some(slice_ref!(elem_ref)) Some(slice_ref!(elem_ref))
......
...@@ -10,8 +10,26 @@ ...@@ -10,8 +10,26 @@
// compile-flags: -C debug-assertions // compile-flags: -C debug-assertions
#![feature(core)]
use std::slice; 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() { pub fn main() {
// In a slice of zero-size elements the pointer is meaningless. // 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. // Ensure iteration still works even if the pointer is at the end of the address space.
...@@ -24,11 +42,19 @@ pub fn main() { ...@@ -24,11 +42,19 @@ pub fn main() {
assert!(it.nth(5).is_some()); assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4); 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) }; let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) };
assert_eq!(slice.len(), 10); assert_eq!(slice.len(), 10);
assert_eq!(slice.iter_mut().count(), 10); assert_eq!(slice.iter_mut().count(), 10);
let mut it = slice.iter_mut(); {
assert!(it.nth(5).is_some()); let mut it = slice.iter_mut();
assert_eq!(it.count(), 4); assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4);
}
assert!(foo_mut(slice).is_some())
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册