@@ -2617,22 +2617,22 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
26172617/// the occasional mistake, and this check should help them figure things out.
26182618#[ allow_internal_unstable( const_eval_select, delayed_debug_assertions) ] // permit this to be called in stably-const fn
26192619macro_rules! assert_unsafe_precondition {
2620- ( $name : expr, ( $( $i : ident: $ty: ty) ,* $( , ) ?) => $e: expr $( , ) ?) => {
2620+ ( $message : expr, ( $( $arg : expr => $name : ident: $ty: ty) ,* $( , ) ?) => $e: expr $( , ) ?) => {
26212621 {
26222622 #[ inline( never) ]
2623- fn precondition_check( $( $i: $ty) ,* ) {
2623+ #[ rustc_nounwind]
2624+ fn precondition_check( $( $name: $ty) ,* ) {
26242625 if !$e {
26252626 :: core:: panicking:: panic_nounwind(
2626- concat!( "unsafe precondition(s) violated: " , $name )
2627+ concat!( "unsafe precondition(s) violated: " , $message )
26272628 ) ;
26282629 }
26292630 }
2630- #[ allow( non_snake_case) ]
26312631 #[ inline]
26322632 const fn comptime( $( _: $ty) ,* ) { }
26332633
26342634 if :: core:: intrinsics:: debug_assertions( ) {
2635- :: core:: intrinsics:: const_eval_select( ( $( $i , ) * ) , comptime, precondition_check) ;
2635+ :: core:: intrinsics:: const_eval_select( ( $( $arg , ) * ) , comptime, precondition_check) ;
26362636 }
26372637 }
26382638 } ;
@@ -2643,7 +2643,32 @@ pub(crate) use assert_unsafe_precondition;
26432643/// `align_of::<T>()`.
26442644#[ inline]
26452645pub ( crate ) fn is_aligned_and_not_null ( ptr : * const ( ) , align : usize ) -> bool {
2646- ptr. is_aligned_to ( align) && !ptr. is_null ( )
2646+ !ptr. is_null ( ) && ptr. is_aligned_to ( align)
2647+ }
2648+
2649+ #[ inline]
2650+ pub ( crate ) fn is_valid_allocation_size ( size : usize , len : usize ) -> bool {
2651+ let max_len = if size == 0 { usize:: MAX } else { isize:: MAX as usize / size } ;
2652+ len <= max_len
2653+ }
2654+
2655+ pub ( crate ) fn is_nonoverlapping_mono (
2656+ src : * const ( ) ,
2657+ dst : * const ( ) ,
2658+ size : usize ,
2659+ count : usize ,
2660+ ) -> bool {
2661+ let src_usize = src. addr ( ) ;
2662+ let dst_usize = dst. addr ( ) ;
2663+ let Some ( size) = size. checked_mul ( count) else {
2664+ crate :: panicking:: panic_nounwind (
2665+ "is_nonoverlapping: `size_of::<T>() * count` overflows a usize" ,
2666+ )
2667+ } ;
2668+ let diff = src_usize. abs_diff ( dst_usize) ;
2669+ // If the absolute distance between the ptrs is at least as big as the size of the buffer,
2670+ // they do not overlap.
2671+ diff >= size
26472672}
26482673
26492674/// Checks whether the regions of memory starting at `src` and `dst` of size
@@ -2755,70 +2780,31 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
27552780#[ inline( always) ]
27562781#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
27572782#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
2758- #[ rustc_allow_const_fn_unstable( const_eval_select) ]
27592783pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
27602784 extern "rust-intrinsic" {
27612785 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.63.0" ) ]
27622786 #[ rustc_nounwind]
27632787 pub fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) ;
27642788 }
27652789
2766- const fn compiletime ( _: * const ( ) , _: * mut ( ) , _: usize , _: usize , _: usize ) { }
2767-
27682790 // SAFETY: the safety contract for `copy_nonoverlapping` must be
27692791 // upheld by the caller.
27702792 unsafe {
2771- if crate :: intrinsics:: debug_assertions ( ) {
2772- const_eval_select (
2773- (
2774- src as * const ( ) ,
2775- dst as * mut ( ) ,
2776- crate :: mem:: size_of :: < T > ( ) ,
2777- crate :: mem:: align_of :: < T > ( ) ,
2778- count,
2779- ) ,
2780- compiletime,
2781- check_aligned_nonoverlapping,
2782- ) ;
2783- }
2784- copy_nonoverlapping ( src, dst, count)
2785- }
2786- }
2787-
2788- #[ inline( never) ]
2789- pub ( crate ) fn check_aligned_nonoverlapping (
2790- src : * const ( ) ,
2791- dst : * mut ( ) ,
2792- size : usize ,
2793- align : usize ,
2794- count : usize ,
2795- ) {
2796- if src. is_null ( ) || dst. is_null ( ) {
2797- crate :: panicking:: panic_nounwind (
2798- "ptr::copy_nonoverlapping requires that both pointer arguments are non-null" ,
2799- ) ;
2800- }
2801- if !src. is_aligned_to ( align) || !dst. is_aligned_to ( align) {
2802- crate :: panicking:: panic_nounwind (
2803- "ptr::copy_nonoverlapping requires that both pointer arguments are aligned" ,
2804- ) ;
2805- }
2806- let src_usize = src. addr ( ) ;
2807- let dst_usize = dst. addr ( ) ;
2808- let Some ( size) = size. checked_mul ( count) else {
2809- crate :: panicking:: panic_nounwind (
2810- "is_nonoverlapping: `size_of::<T>() * count` overflows a usize" ,
2811- )
2812- } ;
2813- let diff = src_usize. abs_diff ( dst_usize) ;
2814- // If the absolute distance between the ptrs is at least as big as the size of the buffer,
2815- // they do not overlap.
2816- let is_nonoverlapping = diff >= size;
2817-
2818- if !is_nonoverlapping {
2819- crate :: panicking:: panic_nounwind (
2820- "ptr::copy_nonoverlapping requires the specified memory ranges do not overlap" ,
2793+ assert_unsafe_precondition ! (
2794+ "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2795+ and the specified memory ranges do not overlap",
2796+ (
2797+ src as * const ( ) => src: * const ( ) ,
2798+ dst as * mut ( ) => dst: * mut ( ) ,
2799+ size_of:: <T >( ) => size: usize ,
2800+ align_of:: <T >( ) => align: usize ,
2801+ count => count: usize ,
2802+ ) =>
2803+ is_aligned_and_not_null( src, align)
2804+ && is_aligned_and_not_null( dst, align)
2805+ && is_nonoverlapping_mono( src, dst, size, count)
28212806 ) ;
2807+ copy_nonoverlapping ( src, dst, count)
28222808 }
28232809}
28242810
@@ -2896,41 +2882,27 @@ pub(crate) fn check_aligned_nonoverlapping(
28962882#[ inline( always) ]
28972883#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
28982884#[ rustc_diagnostic_item = "ptr_copy" ]
2899- #[ rustc_allow_const_fn_unstable( const_eval_select) ]
29002885pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
29012886 extern "rust-intrinsic" {
29022887 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.63.0" ) ]
29032888 #[ rustc_nounwind]
29042889 fn copy < T > ( src : * const T , dst : * mut T , count : usize ) ;
29052890 }
29062891
2907- const fn compiletime ( _: * const ( ) , _: * mut ( ) , _: usize ) { }
2908-
29092892 // SAFETY: the safety contract for `copy` must be upheld by the caller.
29102893 unsafe {
2911- if crate :: intrinsics:: debug_assertions ( ) {
2912- const_eval_select (
2913- ( src as * const ( ) , dst as * mut ( ) , align_of :: < T > ( ) ) ,
2914- compiletime,
2915- check_valid_copy,
2916- ) ;
2917- }
2918- copy ( src, dst, count)
2919- }
2920- }
2921-
2922- #[ inline( never) ]
2923- #[ rustc_nounwind]
2924- fn check_valid_copy ( src : * const ( ) , dst : * mut ( ) , align : usize ) {
2925- if src. is_null ( ) || dst. is_null ( ) {
2926- crate :: panicking:: panic_nounwind (
2927- "ptr::copy requires that both pointer arguments are non-null" ,
2928- ) ;
2929- }
2930- if !src. is_aligned_to ( align) || !dst. is_aligned_to ( align) {
2931- crate :: panicking:: panic_nounwind (
2932- "ptr::copy requires that both pointer arguments are aligned" ,
2894+ assert_unsafe_precondition ! (
2895+ "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2896+ and the specified memory ranges do not overlap",
2897+ (
2898+ src as * const ( ) => src: * const ( ) ,
2899+ dst as * mut ( ) => dst: * mut ( ) ,
2900+ align_of:: <T >( ) => align: usize ,
2901+ ) =>
2902+ is_aligned_and_not_null( src, align)
2903+ && is_aligned_and_not_null( dst, align)
29332904 ) ;
2905+ copy ( src, dst, count)
29342906 }
29352907}
29362908
@@ -2997,13 +2969,14 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
29972969 fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) ;
29982970 }
29992971
3000- let addr = dst as * const ( ) ;
3001- let align = align_of :: < T > ( ) ;
30022972 // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
30032973 unsafe {
30042974 assert_unsafe_precondition ! (
30052975 "ptr::write_bytes requires that the destination pointer is aligned and non-null" ,
3006- ( addr: * const ( ) , align: usize ) => is_aligned_and_not_null( addr, align)
2976+ (
2977+ dst as * const ( ) => addr: * const ( ) ,
2978+ align_of:: <T >( ) => align: usize
2979+ ) => is_aligned_and_not_null( addr, align)
30072980 ) ;
30082981 write_bytes ( dst, val, count)
30092982 }
0 commit comments