Skip to content

Commit d3ef481

Browse files
committed
Add loop contracts and harness for str::small_slice_eq
1 parent 61f68cf commit d3ef481

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@
263263
#![feature(tbm_target_feature)]
264264
#![feature(wasm_target_feature)]
265265
#![feature(x86_amx_intrinsics)]
266+
#![cfg_attr(kani, feature(proc_macro_hygiene))]
266267
// tidy-alphabetical-end
267268

268269
// allow using `core::` in intra-doc links

library/core/src/str/pattern.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ use crate::convert::TryInto as _;
4343
use crate::slice::memchr;
4444
use 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())]
18851893
unsafe 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+
}

scripts/run-kani.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ main() {
183183

184184
echo "Running Kani verify-std command..."
185185

186-
"$kani_path" verify-std -Z unstable-options ./library --target-dir "$temp_dir_target" -Z function-contracts -Z mem-predicates --output-format=terse $command_args
186+
"$kani_path" verify-std -Z unstable-options ./library --target-dir "$temp_dir_target" -Z function-contracts -Z mem-predicates -Z loop-contracts --output-format=terse $command_args --enable-unstable --cbmc-args --object-bits 8
187187
}
188188

189189
main

0 commit comments

Comments
 (0)