Skip to content

Commit 7bae0b7

Browse files
Rollup merge of rust-lang#62103 - RalfJung:debug-assert, r=alexcrichton
Add debug assertions to write_bytes and copy* Looks like @nitnelave went MIA in rust-lang#58783, so I am re-submitting their PR, tweaked just a bit. I took care to preserve commit authorship. Cc rust-lang#53871
2 parents bfe2925 + d3e1bf9 commit 7bae0b7

File tree

7 files changed

+50
-9
lines changed

7 files changed

+50
-9
lines changed

src/libcore/intrinsics.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
issue = "0")]
3737
#![allow(missing_docs)]
3838

39+
use crate::mem;
40+
3941
#[stable(feature = "drop_in_place", since = "1.8.0")]
4042
#[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
4143
since = "1.18.0")]
@@ -1331,6 +1333,26 @@ extern "rust-intrinsic" {
13311333
// (`transmute` also falls into this category, but it cannot be wrapped due to the
13321334
// check that `T` and `U` have the same size.)
13331335

1336+
/// Checks whether `ptr` is properly aligned with respect to
1337+
/// `align_of::<T>()`.
1338+
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
1339+
!ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
1340+
}
1341+
1342+
/// Checks whether the regions of memory starting at `src` and `dst` of size
1343+
/// `count * size_of::<T>()` overlap.
1344+
fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
1345+
let src_usize = src as usize;
1346+
let dst_usize = dst as usize;
1347+
let size = mem::size_of::<T>().checked_mul(count).unwrap();
1348+
let diff = if src_usize > dst_usize {
1349+
src_usize - dst_usize
1350+
} else {
1351+
dst_usize - src_usize
1352+
};
1353+
size > diff
1354+
}
1355+
13341356
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
13351357
/// and destination must *not* overlap.
13361358
///
@@ -1420,7 +1442,11 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
14201442
extern "rust-intrinsic" {
14211443
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
14221444
}
1423-
copy_nonoverlapping(src, dst, count);
1445+
1446+
debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
1447+
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
1448+
debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
1449+
copy_nonoverlapping(src, dst, count)
14241450
}
14251451

14261452
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
@@ -1480,6 +1506,9 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
14801506
extern "rust-intrinsic" {
14811507
fn copy<T>(src: *const T, dst: *mut T, count: usize);
14821508
}
1509+
1510+
debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
1511+
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
14831512
copy(src, dst, count)
14841513
}
14851514

@@ -1561,6 +1590,8 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
15611590
extern "rust-intrinsic" {
15621591
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
15631592
}
1593+
1594+
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
15641595
write_bytes(dst, val, count)
15651596
}
15661597

src/libcore/slice/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
use crate::cmp::Ordering::{self, Less, Equal, Greater};
2626
use crate::cmp;
2727
use crate::fmt;
28-
use crate::intrinsics::{assume, exact_div, unchecked_sub};
28+
use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null};
2929
use crate::isize;
3030
use crate::iter::*;
3131
use crate::ops::{FnMut, Try, self};
@@ -5228,7 +5228,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
52285228
#[inline]
52295229
#[stable(feature = "rust1", since = "1.0.0")]
52305230
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
5231-
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice");
5231+
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
52325232
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
52335233
"attempt to create slice covering half the address space");
52345234
&*ptr::slice_from_raw_parts(data, len)
@@ -5249,7 +5249,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
52495249
#[inline]
52505250
#[stable(feature = "rust1", since = "1.0.0")]
52515251
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
5252-
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice");
5252+
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
52535253
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
52545254
"attempt to create slice covering half the address space");
52555255
&mut *ptr::slice_from_raw_parts_mut(data, len)

src/librustc_codegen_llvm/llvm/ffi.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,9 @@ extern "C" {
17361736
pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>);
17371737
pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
17381738

1739-
pub fn LLVMRustGetSectionName(SI: &SectionIterator<'_>, data: &mut *const c_char) -> size_t;
1739+
#[allow(improper_ctypes)]
1740+
pub fn LLVMRustGetSectionName(SI: &SectionIterator<'_>,
1741+
data: &mut Option<std::ptr::NonNull<c_char>>) -> size_t;
17401742

17411743
#[allow(improper_ctypes)]
17421744
pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);

src/librustc_codegen_llvm/metadata.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_data_structures::owning_ref::OwningRef;
88
use rustc_codegen_ssa::METADATA_FILENAME;
99

1010
use std::path::Path;
11-
use std::ptr;
1211
use std::slice;
1312
use rustc_fs_util::path_to_c_string;
1413

@@ -67,10 +66,16 @@ fn search_meta_section<'a>(of: &'a ObjectFile,
6766
unsafe {
6867
let si = mk_section_iter(of.llof);
6968
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
70-
let mut name_buf = ptr::null();
69+
let mut name_buf = None;
7170
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
72-
let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
73-
let name = String::from_utf8(name).unwrap();
71+
let name = name_buf.map_or(
72+
String::new(), // We got a NULL ptr, ignore `name_len`.
73+
|buf| String::from_utf8(
74+
slice::from_raw_parts(buf.as_ptr() as *const u8,
75+
name_len as usize)
76+
.to_vec()
77+
).unwrap()
78+
);
7479
debug!("get_metadata_section: name {}", name);
7580
if read_metadata_section_name(target) == name {
7681
let cbuf = llvm::LLVMGetSectionContents(si.llsi);

src/test/codegen/issue-45222.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// compile-flags: -O
2+
// ignore-debug: the debug assertions get in the way
23

34
#![crate_type = "lib"]
45

src/test/codegen/issue-45466.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// compile-flags: -O
2+
// ignore-debug: the debug assertions get in the way
23

34
#![crate_type="rlib"]
45

src/test/codegen/swap-small-types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// compile-flags: -O
22
// only-x86_64
3+
// ignore-debug: the debug assertions get in the way
34

45
#![crate_type = "lib"]
56

0 commit comments

Comments
 (0)