Skip to content

Commit 31570cb

Browse files
committed
librustc: Don't create &[T] slices with NULL as the ptr.
1 parent e646188 commit 31570cb

File tree

2 files changed

+17
-19
lines changed

2 files changed

+17
-19
lines changed

src/libcollections/vec.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ use {Collection, Mutable};
2727
use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
2828
use slice::{Items, MutItems};
2929

30+
31+
#[doc(hidden)]
32+
pub static PTR_MARKER: u8 = 0;
33+
3034
/// An owned, growable vector.
3135
///
3236
/// # Examples
@@ -71,7 +75,13 @@ impl<T> Vec<T> {
7175
/// ```
7276
#[inline]
7377
pub fn new() -> Vec<T> {
74-
Vec { len: 0, cap: 0, ptr: 0 as *mut T }
78+
// If we have a 0-sized vector, then the base pointer should not be NULL
79+
// because an iterator over the slice will attempt to yield the base
80+
// pointer as the first element in the vector, but this will end up
81+
// being Some(NULL) which is optimized to None. So instead we set ptr
82+
// to some arbitrary non-null value which is fine since we never call
83+
// deallocate on the ptr if cap is 0.
84+
Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T }
7585
}
7686

7787
/// Constructs a new, empty `Vec` with the specified capacity.
@@ -88,7 +98,7 @@ impl<T> Vec<T> {
8898
#[inline]
8999
pub fn with_capacity(capacity: uint) -> Vec<T> {
90100
if mem::size_of::<T>() == 0 {
91-
Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
101+
Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T }
92102
} else if capacity == 0 {
93103
Vec::new()
94104
} else {
@@ -1206,15 +1216,7 @@ impl<T> Vec<T> {
12061216
/// would also make any pointers to it invalid.
12071217
#[inline]
12081218
pub fn as_ptr(&self) -> *const T {
1209-
// If we have a 0-sized vector, then the base pointer should not be NULL
1210-
// because an iterator over the slice will attempt to yield the base
1211-
// pointer as the first element in the vector, but this will end up
1212-
// being Some(NULL) which is optimized to None.
1213-
if mem::size_of::<T>() == 0 {
1214-
1 as *const T
1215-
} else {
1216-
self.ptr as *const T
1217-
}
1219+
self.ptr as *const T
12181220
}
12191221

12201222
/// Returns a mutable unsafe pointer to the vector's buffer.
@@ -1226,12 +1228,7 @@ impl<T> Vec<T> {
12261228
/// would also make any pointers to it invalid.
12271229
#[inline]
12281230
pub fn as_mut_ptr(&mut self) -> *mut T {
1229-
// see above for the 0-size check
1230-
if mem::size_of::<T>() == 0 {
1231-
1 as *mut T
1232-
} else {
1233-
self.ptr
1234-
}
1231+
self.ptr
12351232
}
12361233

12371234
/// Retains only the elements specified by the predicate.

src/librustc/middle/trans/tvec.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ pub fn trans_slice_vstore<'a>(
155155
let llcount = C_uint(ccx, count);
156156
let llfixed;
157157
if count == 0 {
158-
// Zero-length array: just use NULL as the data pointer
159-
llfixed = C_null(vt.llunit_ty.ptr_to());
158+
// Just create a zero-sized alloca to preserve
159+
// the non-null invariant of the inner slice ptr
160+
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
160161
} else {
161162
// Make a fixed-length backing array and allocate it on the stack.
162163
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);

0 commit comments

Comments
 (0)