55//! the add operation wraps.
66//!
77//! Note that CBMC offset logic will wrap around the object bits, not the entire address space, when
8- //! computing the offset between pointers. Doing that is UB in Rust, so we should be OK
9- //! as long as Kani can detect UB in that case .
8+ //! computing the offset between pointers.
9+ //! See <https://github.com/model-checking/kani/issues/1150> for more details .
1010
1111use std:: convert:: TryInto ;
1212
@@ -15,15 +15,14 @@ fn original_harness() {
1515 let v: & [ u128 ] = & [ 0 ; 10 ] ;
1616 let v_0: * const u128 = & v[ 0 ] ;
1717 let high_offset = usize:: MAX / ( std:: mem:: size_of :: < u128 > ( ) * 4 ) ;
18- unsafe {
19- let v_wrap: * const u128 = v_0. wrapping_add ( high_offset) ;
20- // This should trigger UB!!
21- let wrapped_offset = unsafe { v_wrap. offset_from ( v_0) } ;
22- // Without UB detection, the offsets are the same, but CBMC pointer arithmetic
23- // would "wrap around" making this incorrect
24- // https://github.com/model-checking/kani/issues/1150
25- assert ! ( high_offset == wrapped_offset. try_into( ) . unwrap( ) ) ;
26- }
18+ let v_wrap: * const u128 = v_0. wrapping_add ( high_offset) ;
19+ // FIX-ME: This should trigger UB!!
20+ // https://github.com/model-checking/kani/issues/3756
21+ let wrapped_offset = unsafe { v_wrap. offset_from ( v_0) } ;
22+ // Without UB detection, the offsets are the same, but CBMC pointer arithmetic
23+ // would "wrap around" making this incorrect
24+ // https://github.com/model-checking/kani/issues/1150
25+ assert ! ( high_offset == wrapped_offset. try_into( ) . unwrap( ) ) ;
2726}
2827
2928/// This harness is similar to the `original_harness`, but we replace the `offset_from` with
@@ -33,27 +32,18 @@ fn harness_without_ub() {
3332 let v: & [ u128 ] = & [ 0 ; 10 ] ;
3433 let v_0: * const u128 = & v[ 0 ] ;
3534 let high_offset = usize:: MAX / ( size_of :: < u128 > ( ) * 4 ) ;
36- unsafe {
37- let v_wrap: * const u128 = v_0. wrapping_add ( high_offset) ;
38- // The only way to compute offset of pointers out of bounds is to convert them to integers.
39- let wrapped_offset = ( v_wrap. addr ( ) - v_0. addr ( ) ) / size_of :: < u128 > ( ) ;
40- // Now this should work
41- assert_eq ! ( high_offset, wrapped_offset) ;
42- }
35+ let v_wrap: * const u128 = v_0. wrapping_add ( high_offset) ;
36+ // The only way to compute offset of pointers out of bounds is to convert them to integers.
37+ let wrapped_offset = ( v_wrap. addr ( ) - v_0. addr ( ) ) / size_of :: < u128 > ( ) ;
38+ // Now this should work
39+ assert_eq ! ( high_offset, wrapped_offset) ;
4340}
4441
42+ /// Check that wrapping offset by `usize::MAX + 1` bytes will result in the same base pointer.
4543#[ kani:: proof]
46- fn check_wrap_ptr_max ( ) {
44+ fn check_wrap_around_ptr ( ) {
4745 let v: & [ u128 ] = & [ 0 ; 10 ] ;
4846 let orig_ptr: * const u128 = & v[ 0 ] ;
4947 let new_ptr: * const u128 = orig_ptr. wrapping_byte_add ( usize:: MAX ) . wrapping_byte_add ( 1 ) ;
5048 assert_eq ! ( orig_ptr as usize , new_ptr as usize ) ;
5149}
52-
53- #[ kani:: proof]
54- fn check_wrap_ptr_10_bits ( ) {
55- let v: & [ u128 ] = & [ 0 ; 10 ] ;
56- let orig_ptr: * const u128 = & v[ 0 ] ;
57- let new_ptr: * const u128 = orig_ptr. wrapping_byte_add ( 1 << 63 ) ;
58- assert_ne ! ( orig_ptr as usize , new_ptr as usize ) ;
59- }
0 commit comments