Skip to content

Commit 359fe20

Browse files
Add challenge on memory safety of String (model-checking#55)
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Michael Tautschnig <[email protected]>
1 parent 62e241a commit 359fe20

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

doc/src/SUMMARY.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
- [Pointer Arithmetic](./challenges/0003-pointer-arithmentic.md)
1919
- [Memory safety of BTreeMap's `btree::node` module](./challenges/0004-btree-node.md)
2020
- [Inductive data type](./challenges/0005-linked-list.md)
21-
- [Contracts for SmallSort](./challenges/0008-smallsort.md)
21+
- [Contracts for SmallSort](./challenges/0008-smallsort.md)
22+
- [Memory safety of String](./challenges/0010-string.md)

doc/src/challenges/0010-string.md

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Challenge X: Memory safety of String
2+
3+
- **Status:** Open
4+
- **Tracking Issue:** [Link to issue](https://github.com/model-checking/verify-rust-std/issues/61)
5+
- **Start date:** *2024-08-19*
6+
- **End date:** *2024-12-10*
7+
8+
-------------------
9+
10+
## Goal
11+
12+
In this challenge, the goal is to verify the memory safety of `std::string::String`.
13+
Even though the majority of `String` methods are safe, many of them are safe abstractions over unsafe code.
14+
15+
For instance, the `insert` method is implemented as follows in v1.80.1:
16+
```rust
17+
pub fn insert(&mut self, idx: usize, ch: char) {
18+
assert!(self.is_char_boundary(idx));
19+
let mut bits = [0; 4];
20+
let bits = ch.encode_utf8(&mut bits).as_bytes();
21+
22+
unsafe {
23+
self.insert_bytes(idx, bits);
24+
}
25+
}
26+
```
27+
where `insert_bytes` has the following implementation:
28+
```rust
29+
unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
30+
let len = self.len();
31+
let amt = bytes.len();
32+
self.vec.reserve(amt);
33+
34+
unsafe {
35+
ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx);
36+
ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
37+
self.vec.set_len(len + amt);
38+
}
39+
}
40+
```
41+
The call to the unsafe `insert_bytes` method (which itself contains unsafe code) makes `insert` susceptible to undefined behavior.
42+
43+
### Success Criteria
44+
45+
Verify the memory safety of all public functions that are safe abstractions over unsafe code:
46+
47+
1. `from_utf16le` (unbounded)
48+
1. `from_utf16le_lossy`(unbounded)
49+
1. `from_utf16be` (unbounded)
50+
1. `from_utf16be_lossy` (unbounded)
51+
1. `pop`
52+
1. `remove`
53+
1. `remove_matches` (unbounded)
54+
1. `retain` (unbounded)
55+
1. `insert`
56+
1. `insert_str` (unbounded)
57+
1. `split_off` (unbounded)
58+
1. `drain`
59+
1. `replace_range` (unbounded)
60+
1. `into_boxed_str`
61+
1. `leak`
62+
63+
Ones marked as unbounded must be verified for any string/slice length.
64+
65+
### List of UBs
66+
67+
All proofs must automatically ensure the absence of the following [undefined behaviors](https://github.com/rust-lang/reference/blob/142b2ed77d33f37a9973772bd95e6144ed9dce43/src/behavior-considered-undefined.md):
68+
69+
* Accessing (loading from or storing to) a place that is dangling or based on a misaligned pointer.
70+
* Reading from uninitialized memory.
71+
* Mutating immutable bytes.
72+
* Producing an invalid value
73+
74+
Note: All solutions to verification challenges need to satisfy the criteria established in the [challenge book](../general-rules.md)
75+
in addition to the ones listed above.

0 commit comments

Comments
 (0)