@@ -43,6 +43,13 @@ use crate::convert::TryInto as _;
4343use crate :: slice:: memchr;
4444use crate :: { cmp, fmt} ;
4545
46+ use safety:: { requires, ensures} ;
47+
48+ #[ cfg( kani) ]
49+ use crate :: kani;
50+ #[ cfg( kani) ]
51+ use crate :: kani:: mem:: same_allocation;
52+
4653// Pattern
4754
4855/// A string pattern.
@@ -1880,8 +1887,9 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
18801887/// # Safety
18811888///
18821889/// Both slices must have the same length.
1883- #[ cfg( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ] // only called on x86
1890+ #[ cfg( all( target_arch = "x86_64" , any ( kani , target_feature = "sse2" ) ) ) ] // only called on x86
18841891#[ inline]
1892+ #[ requires( x. len( ) == y. len( ) ) ]
18851893unsafe fn small_slice_eq ( x : & [ u8 ] , y : & [ u8 ] ) -> bool {
18861894 debug_assert_eq ! ( x. len( ) , y. len( ) ) ;
18871895 // This function is adapted from
@@ -1926,6 +1934,10 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
19261934 unsafe {
19271935 let ( mut px, mut py) = ( x. as_ptr ( ) , y. as_ptr ( ) ) ;
19281936 let ( pxend, pyend) = ( px. add ( x. len ( ) - 4 ) , py. add ( y. len ( ) - 4 ) ) ;
1937+ #[ cfg_attr( kani, kani:: loop_invariant( same_allocation( x. as_ptr( ) , px) && same_allocation( y. as_ptr( ) , py)
1938+ && px as isize >= x. as_ptr( ) as isize
1939+ && py as isize >= y. as_ptr( ) as isize
1940+ && px as isize - x. as_ptr( ) as isize == ( py as isize - y. as_ptr( ) as isize ) ) ) ]
19291941 while px < pxend {
19301942 let vx = ( px as * const u32 ) . read_unaligned ( ) ;
19311943 let vy = ( py as * const u32 ) . read_unaligned ( ) ;
@@ -1940,3 +1952,39 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
19401952 vx == vy
19411953 }
19421954}
1955+
1956+ #[ cfg( kani) ]
1957+ #[ unstable( feature = "kani" , issue = "none" ) ]
1958+ pub mod verify {
1959+ use super :: * ;
1960+
1961+ // Copied from https://github.com/model-checking/kani/blob/main/library/kani/src/slice.rs
1962+ // should be removed when these functions are moved to `kani_core`
1963+ pub fn any_slice_of_array < T , const LENGTH : usize > ( arr : & [ T ; LENGTH ] ) -> & [ T ] {
1964+ let ( from, to) = any_range :: < LENGTH > ( ) ;
1965+ & arr[ from..to]
1966+ }
1967+
1968+ fn any_range < const LENGTH : usize > ( ) -> ( usize , usize ) {
1969+ let from: usize = kani:: any ( ) ;
1970+ let to: usize = kani:: any ( ) ;
1971+ kani:: assume ( to <= LENGTH ) ;
1972+ kani:: assume ( from <= to) ;
1973+ ( from, to)
1974+ }
1975+
1976+ #[ cfg( all( kani, target_arch = "x86_64" ) ) ] // only called on x86
1977+ #[ kani:: proof]
1978+ #[ kani:: unwind( 4 ) ]
1979+ pub fn check_small_slice_eq ( ) {
1980+ const ARR_SIZE : usize = 1000 ;
1981+ let x: [ u8 ; ARR_SIZE ] = kani:: any ( ) ;
1982+ let y: [ u8 ; ARR_SIZE ] = kani:: any ( ) ;
1983+ let xs = any_slice_of_array ( & x) ;
1984+ let ys = any_slice_of_array ( & y) ;
1985+ kani:: assume ( xs. len ( ) == ys. len ( ) ) ;
1986+ unsafe {
1987+ small_slice_eq ( xs, ys) ;
1988+ }
1989+ }
1990+ }
0 commit comments