|
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")]
|
@@ -1331,6 +1333,26 @@ extern "rust-intrinsic" {
|
1331 | 1333 | // (`transmute` also falls into this category, but it cannot be wrapped due to the
|
1332 | 1334 | // check that `T` and `U` have the same size.)
|
1333 | 1335 |
|
| 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 | + |
1334 | 1356 | /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
|
1335 | 1357 | /// and destination must *not* overlap.
|
1336 | 1358 | ///
|
@@ -1420,7 +1442,11 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
1420 | 1442 | extern "rust-intrinsic" {
|
1421 | 1443 | fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
1422 | 1444 | }
|
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) |
1424 | 1450 | }
|
1425 | 1451 |
|
1426 | 1452 | /// 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) {
|
1480 | 1506 | extern "rust-intrinsic" {
|
1481 | 1507 | fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
1482 | 1508 | }
|
| 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"); |
1483 | 1512 | copy(src, dst, count)
|
1484 | 1513 | }
|
1485 | 1514 |
|
@@ -1561,6 +1590,8 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
1561 | 1590 | extern "rust-intrinsic" {
|
1562 | 1591 | fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
1563 | 1592 | }
|
| 1593 | + |
| 1594 | + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); |
1564 | 1595 | write_bytes(dst, val, count)
|
1565 | 1596 | }
|
1566 | 1597 |
|
|
0 commit comments