@@ -99,29 +99,35 @@ macro_rules! generate_models {
9999 /// An offset model that checks UB.
100100 #[ kanitool:: fn_marker = "OffsetModel" ]
101101 pub fn offset<T , P : Ptr <T >, O : ToISize >( ptr: P , offset: O ) -> P {
102- let offset = offset. to_isize( ) ;
103102 let t_size = core:: mem:: size_of:: <T >( ) as isize ;
104- if offset == 0 || t_size == 0 {
103+ if t_size == 0 {
104+ // It's always safe to perform an offset on a ZST.
105+ return ptr;
106+ }
107+
108+ // Note that this check must come after the t_size check, c.f. https://github.com/model-checking/kani/issues/3896
109+ let offset = offset. to_isize( ) ;
110+ if offset == 0 {
105111 // It's always safe to perform an offset of length 0.
106- ptr
107- } else {
108- let ( byte_offset, overflow) = offset. overflowing_mul( t_size) ;
109- kani:: safety_check( !overflow, "Offset in bytes overflows isize" ) ;
110- let orig_ptr = ptr. to_const_ptr( ) ;
111- // NOTE: For CBMC, using the pointer addition can have unexpected behavior
112- // when the offset is higher than the object bits since it will wrap around.
113- // See for more details: https://github.com/model-checking/kani/issues/1150
114- //
115- // However, when I tried implementing this using usize operation, we got some
116- // unexpected failures that still require further debugging.
117- // let new_ptr = orig_ptr.addr().wrapping_add_signed(byte_offset) as *const T;
118- let new_ptr = orig_ptr. wrapping_byte_offset( byte_offset) ;
119- kani:: safety_check(
120- kani:: mem:: same_allocation_internal( orig_ptr, new_ptr) ,
121- "Offset result and original pointer must point to the same allocation" ,
122- ) ;
123- P :: from_const_ptr( new_ptr)
112+ return ptr;
124113 }
114+
115+ let ( byte_offset, overflow) = offset. overflowing_mul( t_size) ;
116+ kani:: safety_check( !overflow, "Offset in bytes overflows isize" ) ;
117+ let orig_ptr = ptr. to_const_ptr( ) ;
118+ // NOTE: For CBMC, using the pointer addition can have unexpected behavior
119+ // when the offset is higher than the object bits since it will wrap around.
120+ // See for more details: https://github.com/model-checking/kani/issues/1150
121+ //
122+ // However, when I tried implementing this using usize operation, we got some
123+ // unexpected failures that still require further debugging.
124+ // let new_ptr = orig_ptr.addr().wrapping_add_signed(byte_offset) as *const T;
125+ let new_ptr = orig_ptr. wrapping_byte_offset( byte_offset) ;
126+ kani:: safety_check(
127+ kani:: mem:: same_allocation_internal( orig_ptr, new_ptr) ,
128+ "Offset result and original pointer must point to the same allocation" ,
129+ ) ;
130+ P :: from_const_ptr( new_ptr)
125131 }
126132
127133 pub trait Ptr <T > {
0 commit comments