@@ -43,6 +43,13 @@ use crate::convert::TryInto as _;
43
43
use crate :: slice:: memchr;
44
44
use crate :: { cmp, fmt} ;
45
45
46
+ use safety:: { requires, ensures} ;
47
+
48
+ #[ cfg( kani) ]
49
+ use crate :: kani;
50
+ #[ cfg( kani) ]
51
+ use crate :: kani:: mem:: same_allocation;
52
+
46
53
// Pattern
47
54
48
55
/// A string pattern.
@@ -1880,8 +1887,9 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
1880
1887
/// # Safety
1881
1888
///
1882
1889
/// 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
1884
1891
#[ inline]
1892
+ #[ requires( x. len( ) == y. len( ) ) ]
1885
1893
unsafe fn small_slice_eq ( x : & [ u8 ] , y : & [ u8 ] ) -> bool {
1886
1894
debug_assert_eq ! ( x. len( ) , y. len( ) ) ;
1887
1895
// This function is adapted from
@@ -1926,6 +1934,10 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
1926
1934
unsafe {
1927
1935
let ( mut px, mut py) = ( x. as_ptr ( ) , y. as_ptr ( ) ) ;
1928
1936
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 ) ) ) ]
1929
1941
while px < pxend {
1930
1942
let vx = ( px as * const u32 ) . read_unaligned ( ) ;
1931
1943
let vy = ( py as * const u32 ) . read_unaligned ( ) ;
@@ -1940,3 +1952,39 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
1940
1952
vx == vy
1941
1953
}
1942
1954
}
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