Skip to content

Commit 5738b90

Browse files
committed
Merge remote-tracking branch 'origin/main' into verify-intrinsics
2 parents 24495a4 + c4a1f45 commit 5738b90

File tree

13 files changed

+388
-66
lines changed

13 files changed

+388
-66
lines changed

.github/workflows/kani.yml

+37-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# This workflow is responsible for verifying the standard library with Kani.
2-
31
name: Kani
2+
43
on:
54
workflow_dispatch:
65
pull_request:
@@ -9,30 +8,60 @@ on:
98
paths:
109
- 'library/**'
1110
- '.github/workflows/kani.yml'
12-
- 'scripts/check_kani.sh'
11+
- 'scripts/run-kani.sh'
1312

1413
defaults:
1514
run:
1615
shell: bash
1716

1817
jobs:
19-
build:
18+
check-kani-on-std:
19+
name: Verify std library
2020
runs-on: ${{ matrix.os }}
2121
strategy:
2222
matrix:
23-
# Kani does not support windows.
2423
os: [ubuntu-latest, macos-latest]
2524
include:
2625
- os: ubuntu-latest
2726
base: ubuntu
2827
- os: macos-latest
2928
base: macos
3029
steps:
31-
- name: Checkout Library
30+
# Step 1: Check out the repository
31+
- name: Checkout Repository
3232
uses: actions/checkout@v4
3333
with:
3434
path: head
3535
submodules: true
3636

37-
- name: Run Kani Script
38-
run: bash ./head/scripts/check_kani.sh ${{github.workspace}}/head
37+
# Step 2: Run Kani on the std library (default configuration)
38+
- name: Run Kani Verification
39+
run: head/scripts/run-kani.sh --path ${{github.workspace}}/head
40+
41+
test-kani-script:
42+
name: Test Kani script
43+
runs-on: ${{ matrix.os }}
44+
strategy:
45+
matrix:
46+
os: [ubuntu-latest, macos-latest]
47+
include:
48+
- os: ubuntu-latest
49+
base: ubuntu
50+
- os: macos-latest
51+
base: macos
52+
steps:
53+
# Step 1: Check out the repository
54+
- name: Checkout Repository
55+
uses: actions/checkout@v4
56+
with:
57+
path: head
58+
submodules: true
59+
60+
# Step 2: Test Kani verification script with specific arguments
61+
- name: Test Kani script (Custom Args)
62+
run: head/scripts/run-kani.sh -p ${{github.workspace}}/head --kani-args --harness ptr --output-format=terse
63+
64+
# Step 3: Test Kani verification script in the repository directory
65+
- name: Test Kani script (In Repo Directory)
66+
working-directory: ${{github.workspace}}/head
67+
run: scripts/run-kani.sh --kani-args --harness ptr::verify::check_read_u128 --harness ptr --output-format=terse

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Session.vim
1919
## Build
2020
/book/
2121
/build/
22+
/kani_build/
2223
/target
2324
library/target
2425
*.rlib

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ See [the Rust repository](https://github.com/rust-lang/rust) for details.
4747

4848
## Introducing a New Tool
4949

50-
Please use the [template available in this repository](.github/TOOL_REQUEST_TEMPLATE.md) to introduce a new verification tool.
50+
Please use the [template available in this repository](./doc/src/tool_template.md) to introduce a new verification tool.

library/alloc/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ edition = "2021"
1111
[dependencies]
1212
core = { path = "../core" }
1313
compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] }
14+
safety = { path = "../contracts/safety" }
1415

1516
[dev-dependencies]
1617
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
//
9292
// Library features:
9393
// tidy-alphabetical-start
94+
#![cfg_attr(kani, feature(kani))]
9495
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
9596
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
9697
#![feature(alloc_layout_extra)]

library/core/src/num/int_macros.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,7 @@ macro_rules! int_impl {
21602160
without modifying the original"]
21612161
#[inline(always)]
21622162
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
2163+
#[ensures(|result| *result == self << (rhs & (Self::BITS - 1)))]
21632164
pub const fn wrapping_shl(self, rhs: u32) -> Self {
21642165
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
21652166
// out of bounds
@@ -2190,6 +2191,7 @@ macro_rules! int_impl {
21902191
without modifying the original"]
21912192
#[inline(always)]
21922193
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
2194+
#[ensures(|result| *result == self >> (rhs & (Self::BITS - 1)))]
21932195
pub const fn wrapping_shr(self, rhs: u32) -> Self {
21942196
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
21952197
// out of bounds

library/core/src/num/mod.rs

+140-2
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,51 @@ mod verify {
16571657
}
16581658
}
16591659
}
1660+
1661+
/// A macro to generate Kani proof harnesses for the `carrying_mul` method,
1662+
///
1663+
/// The macro creates multiple harnesses for different ranges of input values,
1664+
/// allowing testing of both small and large inputs.
1665+
///
1666+
/// # Parameters:
1667+
/// - `$type`: The integer type (e.g., u8, u16) for which the `carrying_mul` function is being tested.
1668+
/// - `$wide_type`: A wider type to simulate the multiplication (e.g., u16 for u8, u32 for u16).
1669+
/// - `$harness_name`: The name of the Kani harness to be generated.
1670+
/// - `$min`: The minimum value for the range of inputs for `lhs`, `rhs`, and `carry_in`.
1671+
/// - `$max`: The maximum value for the range of inputs for `lhs`, `rhs`, and `carry_in`.
1672+
macro_rules! generate_carrying_mul_intervals {
1673+
($type:ty, $wide_type:ty, $($harness_name:ident, $min:expr, $max:expr),+) => {
1674+
$(
1675+
#[kani::proof]
1676+
pub fn $harness_name() {
1677+
let lhs: $type = kani::any::<$type>();
1678+
let rhs: $type = kani::any::<$type>();
1679+
let carry_in: $type = kani::any::<$type>();
1680+
1681+
kani::assume(lhs >= $min && lhs <= $max);
1682+
kani::assume(rhs >= $min && rhs <= $max);
1683+
kani::assume(carry_in >= $min && carry_in <= $max);
1684+
1685+
// Perform the carrying multiplication
1686+
let (result, carry_out) = lhs.carrying_mul(rhs, carry_in);
1687+
1688+
// Manually compute the expected result and carry using wider type
1689+
let wide_result = (lhs as $wide_type)
1690+
.wrapping_mul(rhs as $wide_type)
1691+
.wrapping_add(carry_in as $wide_type);
1692+
1693+
let expected_result = wide_result as $type;
1694+
let expected_carry = (wide_result >> <$type>::BITS) as $type;
1695+
1696+
// Assert the result and carry are correct
1697+
assert_eq!(result, expected_result);
1698+
assert_eq!(carry_out, expected_carry);
1699+
}
1700+
)+
1701+
}
1702+
}
1703+
1704+
16601705

16611706
// Part 2 : Nested unsafe functions Generation Macros --> https://github.com/verify-rust-std/blob/main/doc/src/challenges/0011-floats-ints.md
16621707

@@ -1687,6 +1732,19 @@ mod verify {
16871732
}
16881733
}
16891734

1735+
// Verify `wrapping_{shl, shr}` which internally uses `unchecked_{shl,shr}`
1736+
macro_rules! generate_wrapping_shift_harness {
1737+
($type:ty, $method:ident, $harness_name:ident) => {
1738+
#[kani::proof_for_contract($type::$method)]
1739+
pub fn $harness_name() {
1740+
let num1: $type = kani::any::<$type>();
1741+
let num2: u32 = kani::any::<u32>();
1742+
1743+
let _ = num1.$method(num2);
1744+
}
1745+
}
1746+
}
1747+
16901748
// `unchecked_add` proofs
16911749
//
16921750
// Target types:
@@ -1728,7 +1786,7 @@ mod verify {
17281786
generate_unchecked_neg_harness!(i128, checked_unchecked_neg_i128);
17291787
generate_unchecked_neg_harness!(isize, checked_unchecked_neg_isize);
17301788

1731-
// unchecked_mul proofs
1789+
// `unchecked_mul` proofs
17321790
//
17331791
// Target types:
17341792
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total, with different interval checks for each.
@@ -1879,8 +1937,37 @@ mod verify {
18791937
generate_unchecked_math_harness!(u128, unchecked_sub, checked_unchecked_sub_u128);
18801938
generate_unchecked_math_harness!(usize, unchecked_sub, checked_unchecked_sub_usize);
18811939

1940+
1941+
// Part_2 `carrying_mul` proofs
1942+
//
1943+
// ====================== u8 Harnesses ======================
1944+
/// Kani proof harness for `carrying_mul` on `u8` type with full range of values.
1945+
generate_carrying_mul_intervals!(u8, u16,
1946+
carrying_mul_u8_full_range, 0u8, u8::MAX
1947+
);
1948+
1949+
// ====================== u16 Harnesses ======================
1950+
/// Kani proof harness for `carrying_mul` on `u16` type with full range of values.
1951+
generate_carrying_mul_intervals!(u16, u32,
1952+
carrying_mul_u16_full_range, 0u16, u16::MAX
1953+
);
1954+
1955+
// ====================== u32 Harnesses ======================
1956+
generate_carrying_mul_intervals!(u32, u64,
1957+
carrying_mul_u32_small, 0u32, 10u32,
1958+
carrying_mul_u32_large, u32::MAX - 10u32, u32::MAX,
1959+
carrying_mul_u32_mid_edge, (u32::MAX / 2) - 10u32, (u32::MAX / 2) + 10u32
1960+
);
1961+
1962+
// ====================== u64 Harnesses ======================
1963+
generate_carrying_mul_intervals!(u64, u128,
1964+
carrying_mul_u64_small, 0u64, 10u64,
1965+
carrying_mul_u64_large, u64::MAX - 10u64, u64::MAX,
1966+
carrying_mul_u64_mid_edge, (u64::MAX / 2) - 10u64, (u64::MAX / 2) + 10u64
1967+
);
1968+
18821969

1883-
// Part 2 : Proof harnesses
1970+
// Part_2 `widening_mul` proofs
18841971

18851972
// ====================== u8 Harnesses ======================
18861973
generate_widening_mul_intervals!(u8, u16, widening_mul_u8, 0u8, u8::MAX);
@@ -1905,4 +1992,55 @@ mod verify {
19051992
widening_mul_u64_large, u64::MAX - 10u64, u64::MAX,
19061993
widening_mul_u64_mid_edge, (u64::MAX / 2) - 10u64, (u64::MAX / 2) + 10u64
19071994
);
1995+
1996+
// Part_2 `wrapping_shl` proofs
1997+
//
1998+
// Target types:
1999+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
2000+
//
2001+
// Target contracts:
2002+
// #[ensures(|result| *result == self << (rhs & (Self::BITS - 1)))]
2003+
//
2004+
// Target function:
2005+
// pub const fn wrapping_shl(self, rhs: u32) -> Self
2006+
//
2007+
// This function performs an panic-free bitwise left shift operation.
2008+
generate_wrapping_shift_harness!(i8, wrapping_shl, checked_wrapping_shl_i8);
2009+
generate_wrapping_shift_harness!(i16, wrapping_shl, checked_wrapping_shl_i16);
2010+
generate_wrapping_shift_harness!(i32, wrapping_shl, checked_wrapping_shl_i32);
2011+
generate_wrapping_shift_harness!(i64, wrapping_shl, checked_wrapping_shl_i64);
2012+
generate_wrapping_shift_harness!(i128, wrapping_shl, checked_wrapping_shl_i128);
2013+
generate_wrapping_shift_harness!(isize, wrapping_shl, checked_wrapping_shl_isize);
2014+
generate_wrapping_shift_harness!(u8, wrapping_shl, checked_wrapping_shl_u8);
2015+
generate_wrapping_shift_harness!(u16, wrapping_shl, checked_wrapping_shl_u16);
2016+
generate_wrapping_shift_harness!(u32, wrapping_shl, checked_wrapping_shl_u32);
2017+
generate_wrapping_shift_harness!(u64, wrapping_shl, checked_wrapping_shl_u64);
2018+
generate_wrapping_shift_harness!(u128, wrapping_shl, checked_wrapping_shl_u128);
2019+
generate_wrapping_shift_harness!(usize, wrapping_shl, checked_wrapping_shl_usize);
2020+
2021+
// Part_2 `wrapping_shr` proofs
2022+
//
2023+
// Target types:
2024+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
2025+
//
2026+
// Target contracts:
2027+
// #[ensures(|result| *result == self >> (rhs & (Self::BITS - 1)))]
2028+
// Target function:
2029+
// pub const fn wrapping_shr(self, rhs: u32) -> Self {
2030+
//
2031+
// This function performs an panic-free bitwise right shift operation.
2032+
generate_wrapping_shift_harness!(i8, wrapping_shr, checked_wrapping_shr_i8);
2033+
generate_wrapping_shift_harness!(i16, wrapping_shr, checked_wrapping_shr_i16);
2034+
generate_wrapping_shift_harness!(i32, wrapping_shr, checked_wrapping_shr_i32);
2035+
generate_wrapping_shift_harness!(i64, wrapping_shr, checked_wrapping_shr_i64);
2036+
generate_wrapping_shift_harness!(i128, wrapping_shr, checked_wrapping_shr_i128);
2037+
generate_wrapping_shift_harness!(isize, wrapping_shr, checked_wrapping_shr_isize);
2038+
generate_wrapping_shift_harness!(u8, wrapping_shr, checked_wrapping_shr_u8);
2039+
generate_wrapping_shift_harness!(u16, wrapping_shr, checked_wrapping_shr_u16);
2040+
generate_wrapping_shift_harness!(u32, wrapping_shr, checked_wrapping_shr_u32);
2041+
generate_wrapping_shift_harness!(u64, wrapping_shr, checked_wrapping_shr_u64);
2042+
generate_wrapping_shift_harness!(u128, wrapping_shr, checked_wrapping_shr_u128);
2043+
generate_wrapping_shift_harness!(usize, wrapping_shr, checked_wrapping_shr_usize);
2044+
19082045
}
2046+

library/core/src/num/uint_macros.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,7 @@ macro_rules! uint_impl {
21382138
without modifying the original"]
21392139
#[inline(always)]
21402140
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
2141+
#[ensures(|result| *result == self << (rhs & (Self::BITS - 1)))]
21412142
pub const fn wrapping_shl(self, rhs: u32) -> Self {
21422143
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
21432144
// out of bounds
@@ -2171,6 +2172,7 @@ macro_rules! uint_impl {
21712172
without modifying the original"]
21722173
#[inline(always)]
21732174
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
2175+
#[ensures(|result| *result == self >> (rhs & (Self::BITS - 1)))]
21742176
pub const fn wrapping_shr(self, rhs: u32) -> Self {
21752177
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
21762178
// out of bounds

library/std/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ hashbrown = { version = "0.14", default-features = false, features = [
2626
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [
2727
'rustc-dep-of-std',
2828
] }
29+
safety = { path = "../contracts/safety" }
2930

3031
# Dependencies of the `backtrace` crate
3132
rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] }

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@
269269
#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))]
270270
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
271271
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
272+
#![cfg_attr(kani, feature(kani))]
272273
//
273274
// Language features:
274275
// tidy-alphabetical-start

scripts/check_kani.sh

-55
This file was deleted.

0 commit comments

Comments
 (0)