Skip to content

Commit 053f45c

Browse files
zhassan-awsjaisnanartemagvanian
authored
Add a few examples of using shadow memory to check initialization of slices (rust-lang#3237)
A follow-up on rust-lang#3200: use API to check that slices produced by some slice operations that internally use `unsafe` are properly initialized. 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: Jaisurya Nanduri <[email protected]> Co-authored-by: Artem Agvanian <[email protected]>
1 parent ff91762 commit 053f45c

File tree

6 files changed

+100
-0
lines changed

6 files changed

+100
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zghost-state
4+
5+
// This test demonstrates a possible usage of the shadow memory API to check that
6+
// every element of an arbitrary slice of an array is initialized.
7+
// Since the instrumentation is done manually in the harness only but not inside
8+
// the library functions, the test only verifies that the slices point to memory
9+
// that is within the original array.
10+
11+
const N: usize = 16;
12+
13+
static mut SM: kani::shadow::ShadowMem<bool> = kani::shadow::ShadowMem::new(false);
14+
15+
#[kani::proof]
16+
#[kani::unwind(31)]
17+
fn check_slice_init() {
18+
let arr: [char; N] = kani::any();
19+
// tag every element of the array as initialized
20+
for i in &arr {
21+
unsafe {
22+
SM.set(i as *const char, true);
23+
}
24+
}
25+
// create an arbitrary slice of the array
26+
let end: usize = kani::any_where(|x| *x <= N);
27+
let begin: usize = kani::any_where(|x| *x < end);
28+
let slice = &arr[begin..end];
29+
30+
// verify that all elements of the slice are initialized
31+
for i in slice {
32+
assert!(unsafe { SM.get(i as *const char) });
33+
}
34+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zghost-state
4+
5+
// This test demonstrates a possible usage of the shadow memory API to check that
6+
// every element of a reversed array is initialized.
7+
// Since the instrumentation is done manually in the harness only but not inside
8+
// the `reverse` function, the test only verifies that the resulting array
9+
// occupies the same memory as the original one.
10+
11+
const N: usize = 32;
12+
13+
static mut SM: kani::shadow::ShadowMem<bool> = kani::shadow::ShadowMem::new(false);
14+
15+
#[kani::proof]
16+
fn check_reverse() {
17+
let mut a: [u16; N] = kani::any();
18+
for i in &a {
19+
unsafe { SM.set(i as *const u16, true) };
20+
}
21+
a.reverse();
22+
23+
for i in &a {
24+
unsafe {
25+
assert!(SM.get(i as *const u16));
26+
}
27+
}
28+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zghost-state
4+
5+
// This test demonstrates a possible usage of the shadow memory API to check that
6+
// every element of an array split into two slices is initialized.
7+
// Since the instrumentation is done manually in the harness only but not inside
8+
// the `split_at_checked` function, the test only verifies that the resulting
9+
// slices occupy the same memory as the original array.
10+
11+
const N: usize = 16;
12+
13+
static mut SM: kani::shadow::ShadowMem<bool> = kani::shadow::ShadowMem::new(false);
14+
15+
#[kani::proof]
16+
#[kani::unwind(17)]
17+
fn check_reverse() {
18+
let a: [bool; N] = kani::any();
19+
for i in &a {
20+
unsafe { SM.set(i as *const bool, true) };
21+
}
22+
let index: usize = kani::any_where(|x| *x <= N);
23+
let (s1, s2) = a.split_at_checked(index).unwrap();
24+
25+
for i in s1 {
26+
unsafe {
27+
assert!(SM.get(i as *const bool));
28+
}
29+
}
30+
for i in s2 {
31+
unsafe {
32+
assert!(SM.get(i as *const bool));
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)