Skip to content

Commit

Permalink
Rollup merge of rust-lang#62103 - RalfJung:debug-assert, r=alexcrichton
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Centril authored Jun 26, 2019
2 parents 943a17c + d3e1bf9 commit adb4d4a
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 9 deletions.
33 changes: 32 additions & 1 deletion src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
issue = "0")]
#![allow(missing_docs)]

use crate::mem;

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

/// Checks whether `ptr` is properly aligned with respect to
/// `align_of::<T>()`.
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
!ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
}

/// Checks whether the regions of memory starting at `src` and `dst` of size
/// `count * size_of::<T>()` overlap.
fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
let src_usize = src as usize;
let dst_usize = dst as usize;
let size = mem::size_of::<T>().checked_mul(count).unwrap();
let diff = if src_usize > dst_usize {
src_usize - dst_usize
} else {
dst_usize - src_usize
};
size > diff
}

/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
/// and destination must *not* overlap.
///
Expand Down Expand Up @@ -1420,7 +1442,11 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
extern "rust-intrinsic" {
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}
copy_nonoverlapping(src, dst, count);

debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
copy_nonoverlapping(src, dst, count)
}

/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
Expand Down Expand Up @@ -1480,6 +1506,9 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
extern "rust-intrinsic" {
fn copy<T>(src: *const T, dst: *mut T, count: usize);
}

debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
copy(src, dst, count)
}

Expand Down Expand Up @@ -1561,6 +1590,8 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
extern "rust-intrinsic" {
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
}

debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
write_bytes(dst, val, count)
}

Expand Down
6 changes: 3 additions & 3 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
use crate::cmp::Ordering::{self, Less, Equal, Greater};
use crate::cmp;
use crate::fmt;
use crate::intrinsics::{assume, exact_div, unchecked_sub};
use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null};
use crate::isize;
use crate::iter::*;
use crate::ops::{FnMut, Try, self};
Expand Down Expand Up @@ -5213,7 +5213,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice");
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
"attempt to create slice covering half the address space");
&*ptr::slice_from_raw_parts(data, len)
Expand All @@ -5234,7 +5234,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice");
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
"attempt to create slice covering half the address space");
&mut *ptr::slice_from_raw_parts_mut(data, len)
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,9 @@ extern "C" {
pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>);
pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);

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

#[allow(improper_ctypes)]
pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
Expand Down
13 changes: 9 additions & 4 deletions src/librustc_codegen_llvm/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use rustc_data_structures::owning_ref::OwningRef;
use rustc_codegen_ssa::METADATA_FILENAME;

use std::path::Path;
use std::ptr;
use std::slice;
use rustc_fs_util::path_to_c_string;

Expand Down Expand Up @@ -67,10 +66,16 @@ fn search_meta_section<'a>(of: &'a ObjectFile,
unsafe {
let si = mk_section_iter(of.llof);
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let mut name_buf = ptr::null();
let mut name_buf = None;
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
let name = String::from_utf8(name).unwrap();
let name = name_buf.map_or(
String::new(), // We got a NULL ptr, ignore `name_len`.
|buf| String::from_utf8(
slice::from_raw_parts(buf.as_ptr() as *const u8,
name_len as usize)
.to_vec()
).unwrap()
);
debug!("get_metadata_section: name {}", name);
if read_metadata_section_name(target) == name {
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
Expand Down
1 change: 1 addition & 0 deletions src/test/codegen/issue-45222.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// compile-flags: -O
// ignore-debug: the debug assertions get in the way

#![crate_type = "lib"]

Expand Down
1 change: 1 addition & 0 deletions src/test/codegen/issue-45466.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// compile-flags: -O
// ignore-debug: the debug assertions get in the way

#![crate_type="rlib"]

Expand Down
1 change: 1 addition & 0 deletions src/test/codegen/swap-small-types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// compile-flags: -O
// only-x86_64
// ignore-debug: the debug assertions get in the way

#![crate_type = "lib"]

Expand Down

0 comments on commit adb4d4a

Please sign in to comment.