Skip to content

Commit 4e24588

Browse files
committed
Merge remote-tracking branch 'origin/main' into iter-range-rs-contracts
2 parents 44bf92b + b4f59e8 commit 4e24588

File tree

185 files changed

+9785
-5984
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+9785
-5984
lines changed

.github/workflows/kani-metrics.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ jobs:
2626
python-version: '3.x'
2727

2828
- name: Compute Kani Metrics
29-
run: ./scripts/run-kani.sh --run metrics --with-autoharness --path ${{github.workspace}}
29+
run: |
30+
./scripts/run-kani.sh --run metrics --with-autoharness --path ${{github.workspace}}
31+
rm kani-list.json
3032
3133
- name: Create Pull Request
3234
uses: peter-evans/create-pull-request@v7

.github/workflows/kani.yml

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
- name: Run Kani Verification
5454
run: head/scripts/run-kani.sh --path ${{github.workspace}}/head
5555

56-
kani-autoharness:
56+
kani_autoharness:
5757
name: Verify std library using autoharness
5858
runs-on: ${{ matrix.os }}
5959
strategy:
@@ -78,11 +78,18 @@ jobs:
7878
# possible functions as that may take a lot longer than expected. Instead,
7979
# explicitly list all functions (or prefixes thereof) the proofs of which
8080
# are known to pass.
81+
# Notes:
82+
# - We use >::disjoint_bitor (and >::unchecked_disjoint_bitor) as pattern
83+
# as whitespace is not supported, cf.
84+
# https://github.com/model-checking/kani/issues/4046
8185
- name: Run Kani Verification
8286
run: |
8387
scripts/run-kani.sh --run autoharness --kani-args \
88+
--include-pattern ">::disjoint_bitor" \
89+
--include-pattern ">::unchecked_disjoint_bitor" \
8490
--include-pattern "iter::range::Step>::backward_unchecked" \
8591
--include-pattern "iter::range::Step>::forward_unchecked" \
92+
--include-pattern alloc::__default_lib_allocator:: \
8693
--include-pattern alloc::layout::Layout::from_size_align \
8794
--include-pattern ascii::ascii_char::AsciiChar::from_u8 \
8895
--include-pattern char::convert::from_u32_unchecked \
@@ -126,7 +133,121 @@ jobs:
126133
--exclude-pattern ::precondition_check \
127134
--harness-timeout 10m \
128135
--default-unwind 1000 \
129-
--jobs=3 --output-format=terse
136+
--jobs=3 --output-format=terse | tee autoharness-verification.log
137+
gzip autoharness-verification.log
138+
139+
- name: Upload Autoharness Verification Log
140+
uses: actions/upload-artifact@v4
141+
with:
142+
name: ${{ matrix.os }}-autoharness-verification.log.gz
143+
path: autoharness-verification.log.gz
144+
if-no-files-found: error
145+
# Aggressively short retention: we don't really need these
146+
retention-days: 3
147+
148+
run_kani_metrics:
149+
name: Kani Metrics
150+
runs-on: ${{ matrix.os }}
151+
strategy:
152+
matrix:
153+
os: [ubuntu-latest, macos-latest]
154+
include:
155+
- os: ubuntu-latest
156+
base: ubuntu
157+
- os: macos-latest
158+
base: macos
159+
fail-fast: true
160+
161+
steps:
162+
# Step 1: Check out the repository
163+
- name: Checkout Repository
164+
uses: actions/checkout@v4
165+
with:
166+
submodules: true
167+
168+
# The Kani metrics collection uses a Python script (kani_std_analysis.py), so make sure Python is installed
169+
- name: Set up Python
170+
uses: actions/setup-python@v4
171+
with:
172+
python-version: '3.x'
173+
174+
# Step 2: Run list on the std library
175+
- name: Run Kani Metrics
176+
run: |
177+
scripts/run-kani.sh --run metrics --with-autoharness
178+
pushd /tmp/std_lib_analysis
179+
tar czf results.tar.gz results
180+
popd
181+
182+
- name: Upload kani-list.json
183+
uses: actions/upload-artifact@v4
184+
with:
185+
name: ${{ matrix.os }}-kani-list.json
186+
path: kani-list.json
187+
if-no-files-found: error
188+
# Aggressively short retention: we don't really need these
189+
retention-days: 3
190+
191+
- name: Upload scanner results
192+
uses: actions/upload-artifact@v4
193+
with:
194+
name: ${{ matrix.os }}-results.tar.gz
195+
path: /tmp/std_lib_analysis/results.tar.gz
196+
if-no-files-found: error
197+
# Aggressively short retention: we don't really need these
198+
retention-days: 3
199+
200+
run-log-analysis:
201+
name: Build JSON from logs
202+
needs: [run_kani_metrics, kani_autoharness]
203+
runs-on: ${{ matrix.os }}
204+
strategy:
205+
matrix:
206+
os: [ubuntu-latest, macos-latest]
207+
include:
208+
- os: ubuntu-latest
209+
base: ubuntu
210+
- os: macos-latest
211+
base: macos
212+
fail-fast: false
213+
214+
steps:
215+
- name: Checkout Repository
216+
uses: actions/checkout@v4
217+
with:
218+
submodules: false
219+
220+
- name: Download log
221+
uses: actions/download-artifact@v4
222+
with:
223+
name: ${{ matrix.os }}-autoharness-verification.log.gz
224+
225+
- name: Download kani-list.json
226+
uses: actions/download-artifact@v4
227+
with:
228+
name: ${{ matrix.os }}-kani-list.json
229+
230+
- name: Download scanner results
231+
uses: actions/download-artifact@v4
232+
with:
233+
name: ${{ matrix.os }}-results.tar.gz
234+
235+
- name: Run log parser
236+
run: |
237+
gunzip autoharness-verification.log.gz
238+
tar xzf results.tar.gz
239+
python3 scripts/kani-std-analysis/log_parser.py \
240+
--kani-list-file kani-list.json \
241+
--analysis-results-dir results/ \
242+
autoharness-verification.log \
243+
-o results.json
244+
245+
- name: Upload JSON
246+
uses: actions/upload-artifact@v4
247+
with:
248+
name: ${{ matrix.os }}-results.json
249+
path: results.json
250+
if-no-files-found: error
130251

131252
run-kani-list:
132253
name: Kani List
@@ -178,12 +299,14 @@ jobs:
178299
# Step 3: Add output to job summary
179300
- name: Add Autoharness Analyzer output to job summary
180301
run: |
302+
pushd scripts/autoharness_analyzer
181303
echo "# Autoharness Failure Summary" >> "$GITHUB_STEP_SUMMARY"
182304
echo "## Crate core, all functions" >> "$GITHUB_STEP_SUMMARY"
183-
cat autoharness_analyzer/core_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
305+
cat core_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
184306
echo "## Crate core, unsafe functions" >> "$GITHUB_STEP_SUMMARY"
185-
cat autoharness_analyzer/core_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
307+
cat core_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
186308
echo "## Crate std, all functions" >> "$GITHUB_STEP_SUMMARY"
187-
cat autoharness_analyzer/std_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
309+
cat std_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
188310
echo "## Crate std, unsafe functions" >> "$GITHUB_STEP_SUMMARY"
189-
cat autoharness_analyzer/std_unsafe_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
311+
cat std_unsafe_autoharness_data.md >> "$GITHUB_STEP_SUMMARY"
312+
popd

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Session.vim
2222
/kani_build/
2323
/target
2424
library/target
25+
scripts/autoharness_analyzer/target/
2526
*.rlib
2627
*.rmeta
2728
*.mir

doc/mdbook-metrics/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ edition = "2021"
55

66
[dependencies]
77
mdbook = { version = "^0.4" }
8+
mdbook-linkcheck = "0.7.7"
89
serde_json = "1.0.132"

doc/src/SUMMARY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,8 @@
3232
- [16: Verify the safety of Iterator functions](./challenges/0016-iter.md)
3333
- [17: Verify the safety of slice functions](./challenges/0017-slice.md)
3434
- [18: Verify the safety of slice iter functions](./challenges/0018-slice-iter.md)
35+
- [19: Safety of `RawVec`](./challenges/0019-rawvec.md)
36+
- [20: Verify the safety of char-related functions in str::pattern](./challenges/0020-str-pattern-pt1.md)
37+
- [21: Verify the safety of substring-related functions in str::pattern](./challenges/0021-str-pattern-pt2.md)
38+
- [22: Verify the safety of str iter functions](./challenges/0022-str-iter.md)
39+
- [25: Verify the safety of `VecDeque` functions](./challenges/0025-vecdeque.md)

doc/src/challenges/0007-atomic-types.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,18 @@ Write and verify safety contracts for the unsafe functions:
8787
- `atomic_umax`
8888
- `atomic_umin`
8989

90+
##### Panicking (Optional)
9091
Then, for each of the safe abstractions that invoke the unsafe functions listed above, write contracts that ensure that they are not invoked with `order`s that would cause panics.
9192

9293
For example, `atomic_store` panics if invoked with `Acquire` or `AcqRel` ordering.
9394
In this case, you would write contracts on the safe `store` methods that enforce that they are not called with either of those `order`s.
9495

96+
This section is not required to complete the challenge, since panicking is not undefined behavior.
97+
However, it would be incorrect for someone to call these functions with the wrong arguments, so we encourage providing these specifications.
98+
9599
#### Part 3: Atomic Intrinsics
96100

97-
Write and verify safety contracts for the intrinsics invoked by the unsafe functions from Part 2 (in `core::intrinsics`):
101+
Write safety contracts for the intrinsics invoked by the unsafe functions from Part 2 (in `core::intrinsics`):
98102

99103
| Operations | Functions |
100104
|-----------------------|-------------|

doc/src/challenges/0019-rawvec.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Challenge 25: Verify the safety of `RawVec` functions
2+
3+
- **Status:** Open
4+
- **Tracking Issue:** [#283](https://github.com/model-checking/verify-rust-std/issues/283)
5+
- **Start date:** *2025-03-07*
6+
- **End date:** *2025-10-17*
7+
- **Reward:** *10000 USD*
8+
9+
-------------------
10+
11+
12+
## Goal
13+
14+
Verify the safety of `RawVec` functions in (library/alloc/src/raw_vec/mod.rs).
15+
16+
## Motivation
17+
18+
`RawVec` is the type of the main component of both `Vec` and `VecDeque`: the buffer. Therefore, the safety of the functions of `Vec` and `VecDeque` depend on the safety of `RawVec`.
19+
20+
### Success Criteria
21+
22+
Verify the safety of the following functions in (library/alloc/src/raw_vec/mod.rs):
23+
24+
Write and prove the contract for the safety of the following unsafe functions:
25+
26+
| Function |
27+
|---------|
28+
|new_cap|
29+
|into_box|
30+
|from_raw_parts_in|
31+
|from_nonnull_in|
32+
|set_ptr_and_cap|
33+
|shrink_unchecked|
34+
|deallocate|
35+
36+
Prove the absence of undefined behavior for following safe abstractions:
37+
38+
| Function |
39+
|---------|
40+
|drop|
41+
|new_in|
42+
|with_capacity_in|
43+
|try_allocate_in|
44+
|current_memory|
45+
|try_reserve|
46+
|try_reserve_exact|
47+
|grow_amortized|
48+
|grow_exact|
49+
|shrink|
50+
|finish_grow|
51+
52+
The verification must be unbounded---it must hold for slices of arbitrary length.
53+
54+
The verification must hold for generic type `T` (no monomorphization).
55+
56+
### List of UBs
57+
58+
All proofs must automatically ensure the absence of the following undefined behaviors [ref](https://github.com/rust-lang/reference/blob/142b2ed77d33f37a9973772bd95e6144ed9dce43/src/behavior-considered-undefined.md):
59+
60+
* Accessing (loading from or storing to) a place that is dangling or based on a misaligned pointer.
61+
* Reading from uninitialized memory except for padding or unions.
62+
* Mutating immutable bytes.
63+
* Producing an invalid value
64+
65+
66+
Note: All solutions to verification challenges need to satisfy the criteria established in the [challenge book](../general-rules.md)
67+
in addition to the ones listed above.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Challenge 20: Verify the safety of char-related functions in str::pattern
2+
3+
- **Status:** Open
4+
- **Tracking Issue:** [#277](https://github.com/model-checking/verify-rust-std/issues/277)
5+
- **Start date:** *2025-03-07*
6+
- **End date:** *2025-10-17*
7+
- **Reward:** *25000 USD*
8+
9+
-------------------
10+
## Goal
11+
Verify the safety of char-related `Searcher` methods in `str::pattern`.
12+
13+
## Motivation
14+
15+
String and `str` types are widely used in Rust programs, so it is important that their associated functions do not cause undefined behavior.
16+
17+
## Description
18+
19+
The following str library functions are generic over the `Pattern` trait (https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html):
20+
- `contains`
21+
- `starts_with`
22+
- `ends_with`
23+
- `find`
24+
- `rfind`
25+
- `split`
26+
- `split_inclusive`
27+
- `rsplit`
28+
- `split_terminator`
29+
- `rsplit_terminator`
30+
- `splitn`
31+
- `rsplitn`
32+
- `split_once`
33+
- `rsplit_once`
34+
- `rmatches`
35+
- `match_indices`
36+
- `rmatch_indices`
37+
- `trim_matches`
38+
- `trim_start_matches`
39+
- `strip_prefix`
40+
- `strip_suffix`
41+
- `trim_end_matches`
42+
These functions accept a pattern as input, then call [into_searcher](https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html#tymethod.into_searcher) to create a [Searcher](https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html#associatedtype.Searcher) for the pattern. They use this `Searcher` to perform their desired operations (split, find, etc.).
43+
Those functions are implemented in (library/core/src/str/mod.rs), but the core of them are the searching algorithms which are implemented in (library/core/src/str/pattern.rs).
44+
45+
### Assumptions
46+
47+
**Important note:** for this challenge, you can assume:
48+
1. The safety and functional correctness of all functions in `slice` module.
49+
2. That all functions in (library/core/src/str/validations.rs) are functionally correct (consistent with the UTF-8 encoding description in https://en.wikipedia.org/wiki/UTF-8).
50+
3. That all the Searchers in (library/core/src/str/iter.rs) are created by the into_searcher(_, haystack) with haystack being a valid UTF-8 string (str). You can assume any UTF-8 string property of haystack.
51+
52+
Verify the safety of the functions in (library/core/src/str/pattern.rs) listed in the next section.
53+
54+
The safety properties we are targeting are:
55+
1. No undefined behavior occurs after the Searcher is created.
56+
2. The impls of unsafe traits `Searcher` and `ReverseSearcher` satisfy the SAFETY condition stated in the file:
57+
```
58+
/// The trait is marked unsafe because the indices returned by the
59+
/// [`next()`][Searcher::next] methods are required to lie on valid utf8
60+
/// boundaries in the haystack. This enables consumers of this trait to
61+
/// slice the haystack without additional runtime checks.
62+
```
63+
This property should hold for next_back() of `ReverseSearcher` too.
64+
65+
66+
### Success Criteria
67+
68+
Verify the safety of the following functions in (library/core/src/str/pattern.rs) :
69+
- `next`
70+
- `next_match`
71+
- `next_back`
72+
- `next_match_back`
73+
- `next_reject`
74+
- `next_back_reject`
75+
for the following `Searcher`s:
76+
- `CharSearcher`
77+
- `MultiCharEqSearcher`
78+
- `CharArraySearcher`
79+
- `CharArrayRefSearcher`
80+
- `CharSliceSearcher`
81+
- `CharPredicateSearcher`
82+
83+
The verification is considered successful if for each `Searcher` above, you can specify a condition (a "type invariant") `C` and prove that:
84+
1. If the `Searcher` is created from any valid UTF-8 haystack, it satisfies `C`.
85+
2. If the `Searcher` satisfies `C`, it ensures the two safety properties mentioned in the previous section.
86+
3. If the `Searcher` satisfies `C`, after it calls any function above and gets modified, it still satisfies `C`.
87+
88+
Furthermore, you must prove the absence of undefined behaviors listed in the next section.
89+
90+
The verification must be unbounded---it must hold for inputs of arbitrary size.
91+
92+
### List of UBs
93+
94+
All proofs must automatically ensure the absence of the following undefined behaviors [ref](https://github.com/rust-lang/reference/blob/142b2ed77d33f37a9973772bd95e6144ed9dce43/src/behavior-considered-undefined.md):
95+
96+
* Accessing (loading from or storing to) a place that is dangling or based on a misaligned pointer.
97+
* Reading from uninitialized memory except for padding or unions.
98+
* Mutating immutable bytes.
99+
* Producing an invalid value
100+
101+
102+
Note: All solutions to verification challenges need to satisfy the criteria established in the [challenge book](../general-rules.md)
103+
in addition to the ones listed above.

0 commit comments

Comments
 (0)