Skip to content

Commit 8a2dec6

Browse files
committed
Auto merge of rust-lang#53804 - RalfJung:ptr-invalid, r=nagisa
fix some uses of pointer intrinsics with invalid pointers [Found by miri](rust-lang/miri#446): * `Vec::into_iter` calls `ptr::read` (and the underlying `copy_nonoverlapping`) with an unaligned pointer to a ZST. [According to LLVM devs](https://bugs.llvm.org/show_bug.cgi?id=38583), this is UB because it contradicts the metadata we are attaching to that pointer. * `HashMap` creation calls `ptr:.write_bytes` on a NULL pointer with a count of 0. This is likely not currently UB *currently*, but it violates the rules we are setting in rust-lang#53783, and we might want to exploit those rules later (e.g. with more `nonnull` attributes for LLVM). Probably what `HashMap` really should do is use `NonNull::dangling()` instead of 0 for the empty case, but that would require a more careful analysis of the code. It seems like ideally, we should do a review of usage of such intrinsics all over libstd to ensure that they use valid pointers even when the size is 0. Is it worth opening an issue for that?
2 parents d3cba9b + 357c5da commit 8a2dec6

File tree

2 files changed

+7
-7
lines changed

2 files changed

+7
-7
lines changed

src/liballoc/vec.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -2410,9 +2410,8 @@ impl<T> Iterator for IntoIter<T> {
24102410
// same pointer.
24112411
self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T;
24122412

2413-
// Use a non-null pointer value
2414-
// (self.ptr might be null because of wrapping)
2415-
Some(ptr::read(1 as *mut T))
2413+
// Make up a value of this ZST.
2414+
Some(mem::zeroed())
24162415
} else {
24172416
let old = self.ptr;
24182417
self.ptr = self.ptr.offset(1);
@@ -2451,9 +2450,8 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
24512450
// See above for why 'ptr.offset' isn't used
24522451
self.end = arith_offset(self.end as *const i8, -1) as *mut T;
24532452

2454-
// Use a non-null pointer value
2455-
// (self.end might be null because of wrapping)
2456-
Some(ptr::read(1 as *mut T))
2453+
// Make up a value of this ZST.
2454+
Some(mem::zeroed())
24572455
} else {
24582456
self.end = self.end.offset(-1);
24592457

src/libstd/collections/hash/table.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,9 @@ impl<K, V> RawTable<K, V> {
742742
) -> Result<RawTable<K, V>, CollectionAllocErr> {
743743
unsafe {
744744
let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?;
745-
ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
745+
if capacity > 0 {
746+
ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
747+
}
746748
Ok(ret)
747749
}
748750
}

0 commit comments

Comments
 (0)