|
36 | 36 | issue = "0")]
|
37 | 37 | #![allow(missing_docs)]
|
38 | 38 |
|
| 39 | +use crate::mem; |
| 40 | + |
39 | 41 | #[stable(feature = "drop_in_place", since = "1.8.0")]
|
40 | 42 | #[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
|
41 | 43 | since = "1.18.0")]
|
@@ -1323,6 +1325,26 @@ extern "rust-intrinsic" {
|
1323 | 1325 | // (`transmute` also falls into this category, but it cannot be wrapped due to the
|
1324 | 1326 | // check that `T` and `U` have the same size.)
|
1325 | 1327 |
|
| 1328 | +/// Checks whether `ptr` is properly aligned with respect to |
| 1329 | +/// `align_of::<T>()`. |
| 1330 | +pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool { |
| 1331 | + !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0 |
| 1332 | +} |
| 1333 | + |
| 1334 | +/// Checks whether the regions of memory starting at `src` and `dst` of size |
| 1335 | +/// `count * size_of::<T>()` overlap. |
| 1336 | +fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool { |
| 1337 | + let src_usize = src as usize; |
| 1338 | + let dst_usize = dst as usize; |
| 1339 | + let size = mem::size_of::<T>().checked_mul(count).unwrap(); |
| 1340 | + let diff = if src_usize > dst_usize { |
| 1341 | + src_usize - dst_usize |
| 1342 | + } else { |
| 1343 | + dst_usize - src_usize |
| 1344 | + }; |
| 1345 | + size > diff |
| 1346 | +} |
| 1347 | + |
1326 | 1348 | /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
|
1327 | 1349 | /// and destination must *not* overlap.
|
1328 | 1350 | ///
|
@@ -1412,7 +1434,11 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
1412 | 1434 | extern "rust-intrinsic" {
|
1413 | 1435 | fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
1414 | 1436 | }
|
1415 |
| - copy_nonoverlapping(src, dst, count); |
| 1437 | + |
| 1438 | + debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer"); |
| 1439 | + debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer"); |
| 1440 | + debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory"); |
| 1441 | + copy_nonoverlapping(src, dst, count) |
1416 | 1442 | }
|
1417 | 1443 |
|
1418 | 1444 | /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
|
@@ -1472,6 +1498,9 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
1472 | 1498 | extern "rust-intrinsic" {
|
1473 | 1499 | fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
1474 | 1500 | }
|
| 1501 | + |
| 1502 | + debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer"); |
| 1503 | + debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer"); |
1475 | 1504 | copy(src, dst, count)
|
1476 | 1505 | }
|
1477 | 1506 |
|
@@ -1553,5 +1582,7 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
1553 | 1582 | extern "rust-intrinsic" {
|
1554 | 1583 | fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
1555 | 1584 | }
|
| 1585 | + |
| 1586 | + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); |
1556 | 1587 | write_bytes(dst, val, count)
|
1557 | 1588 | }
|
0 commit comments