Skip to content

Commit 6f01099

Browse files
committed
Make Vec.ptr() return the ptr field always
Don't special-case zero-sized values in Vec.ptr(). Doing that prevents the following from working: // v is a Vec<T> let newv = Vec::from_raw_parts(v.len(), v.cap(), v.mut_ptr()); mem::forget(v); Instead, teach slice::Items/MutItems to handle zero-sized values better.
1 parent 81c0223 commit 6f01099

File tree

2 files changed

+21
-28
lines changed

2 files changed

+21
-28
lines changed

src/libcore/slice.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,17 +1257,18 @@ macro_rules! iterator {
12571257
if self.ptr == self.end {
12581258
None
12591259
} else {
1260-
let old = self.ptr;
1261-
self.ptr = if mem::size_of::<T>() == 0 {
1260+
if mem::size_of::<T>() == 0 {
12621261
// purposefully don't use 'ptr.offset' because for
12631262
// vectors with 0-size elements this would return the
12641263
// same pointer.
1265-
transmute(self.ptr as uint + 1)
1264+
self.ptr = transmute(self.ptr as uint + 1);
1265+
Some(transmute(1u)) // Use a non-NULL pointer value
12661266
} else {
1267-
self.ptr.offset(1)
1268-
};
1267+
let old = self.ptr;
1268+
self.ptr = self.ptr.offset(1);
12691269

1270-
Some(transmute(old))
1270+
Some(transmute(old))
1271+
}
12711272
}
12721273
}
12731274
}
@@ -1289,13 +1290,14 @@ macro_rules! iterator {
12891290
if self.end == self.ptr {
12901291
None
12911292
} else {
1292-
self.end = if mem::size_of::<T>() == 0 {
1293-
// See above for why 'ptr.offset' isn't used
1294-
transmute(self.end as uint - 1)
1293+
if mem::size_of::<T>() == 0 {
1294+
// See above for why `ptr.offset` isn't used
1295+
self.end = transmute(self.end as uint - 1);
1296+
Some(transmute(1u)) // Use a non-NULL pointer value
12951297
} else {
1296-
self.end.offset(-1)
1297-
};
1298-
Some(transmute(self.end))
1298+
self.end = self.end.offset(-1);
1299+
Some(transmute(self.end))
1300+
}
12991301
}
13001302
}
13011303
}
@@ -1314,7 +1316,11 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
13141316
fn idx(&mut self, index: uint) -> Option<&'a T> {
13151317
unsafe {
13161318
if index < self.indexable() {
1317-
transmute(self.ptr.offset(index as int))
1319+
if mem::size_of::<T>() == 0 {
1320+
Some(transmute(1u)) // Use a non-NULL pointer value
1321+
} else {
1322+
Some(transmute(self.ptr.offset(index as int)))
1323+
}
13181324
} else {
13191325
None
13201326
}

src/libstd/vec.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,15 +1184,7 @@ impl<T> Vec<T> {
11841184
/// would also make any pointers to it invalid.
11851185
#[inline]
11861186
pub fn as_ptr(&self) -> *T {
1187-
// If we have a 0-sized vector, then the base pointer should not be NULL
1188-
// because an iterator over the slice will attempt to yield the base
1189-
// pointer as the first element in the vector, but this will end up
1190-
// being Some(NULL) which is optimized to None.
1191-
if mem::size_of::<T>() == 0 {
1192-
1 as *T
1193-
} else {
1194-
self.ptr as *T
1195-
}
1187+
self.ptr as *T
11961188
}
11971189

11981190
/// Returns a mutable unsafe pointer to the vector's buffer.
@@ -1204,12 +1196,7 @@ impl<T> Vec<T> {
12041196
/// would also make any pointers to it invalid.
12051197
#[inline]
12061198
pub fn as_mut_ptr(&mut self) -> *mut T {
1207-
// see above for the 0-size check
1208-
if mem::size_of::<T>() == 0 {
1209-
1 as *mut T
1210-
} else {
1211-
self.ptr
1212-
}
1199+
self.ptr
12131200
}
12141201

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

0 commit comments

Comments
 (0)