Skip to content

Commit 2eca14d

Browse files
committed
Add extra tests for copy + delayed ub, split copy tests into multiple
1 parent f46f1cb commit 2eca14d

17 files changed

+311
-119
lines changed

copy_test.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#[repr(C)]
2+
#[derive(kani::Arbitrary)]
3+
struct S(u32, u8); // 5 bytes of data + 3 bytes of padding.
4+
5+
// #[kani::proof]
6+
// fn delayed_ub_double_copy() {
7+
// unsafe {
8+
// let mut value: u128 = 0;
9+
// let ptr = &mut value as *mut _ as *mut (u8, u32, u64);
10+
// // Use `copy_nonoverlapping` in an attempt to remove the taint.
11+
// std::ptr::write(ptr, (4, 4, 4));
12+
// // Instead of assigning the value into a delayed UB place, copy it from another delayed UB
13+
// // place.
14+
// let mut value_2: u128 = 0;
15+
// let ptr_2 = &mut value_2 as *mut _ as *mut (u8, u32, u64);
16+
// std::ptr::copy(ptr_2, ptr, 1); // This should not trigger UB since the copy is untyped.
17+
// assert!(value_2 > 0); // UB: This reads a padding value!
18+
// }
19+
// }
20+
21+
// #[kani::proof]
22+
// fn delayed_ub_trigger_copy() {
23+
// unsafe {
24+
// let mut value: u128 = 0;
25+
// let ptr = &mut value as *mut _ as *mut u8; // This cast should not be a delayed UB source.
26+
// let mut value_different_padding: (u8, u32, u64) = (4, 4, 4);
27+
// let ptr_different_padding = &mut value_different_padding as *mut _ as *mut u8;
28+
// std::ptr::copy(ptr_different_padding, ptr, std::mem::size_of::<u128>()); // This is a delayed UB source.
29+
// assert!(value > 0); // UB: This reads a padding value!
30+
// }
31+
// }
32+
33+
#[kani::proof]
34+
/// This checks that reading copied uninitialized bytes fails an assertion.
35+
unsafe fn expose_padding_via_copy_convoluted() {
36+
unsafe fn copy_and_read_helper(from_ptr: *const S, to_ptr: *mut u64) -> u64 {
37+
// This should not cause UB since `copy` is untyped.
38+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<S>());
39+
// This reads uninitialized bytes, which is UB.
40+
let padding: u64 = std::ptr::read(to_ptr);
41+
padding
42+
}
43+
44+
unsafe fn partial_copy_and_read_helper(from_ptr: *const S, to_ptr: *mut u64) -> u32 {
45+
// This should not cause UB since `copy` is untyped.
46+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<u32>());
47+
// This does not read uninitialized bytes.
48+
let not_padding: u32 = std::ptr::read(to_ptr as *mut u32);
49+
not_padding
50+
}
51+
52+
let flag: bool = kani::any();
53+
54+
let from: S = kani::any();
55+
let mut to: u64 = kani::any();
56+
57+
let from_ptr = &from as *const S;
58+
let to_ptr = &mut to as *mut u64;
59+
60+
if flag {
61+
copy_and_read_helper(from_ptr, to_ptr);
62+
} else {
63+
partial_copy_and_read_helper(from_ptr, to_ptr);
64+
}
65+
}

tests/expected/uninit/copy/copy.rs

Lines changed: 0 additions & 87 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Complete - 1 successfully verified harnesses, 0 failures, 1 total.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Z uninit-checks
4+
5+
#[repr(C)]
6+
#[derive(kani::Arbitrary)]
7+
struct S(u32, u8); // 5 bytes of data + 3 bytes of padding.
8+
9+
#[kani::proof]
10+
/// This checks that reading copied initialized bytes verifies correctly.
11+
unsafe fn copy_without_padding() {
12+
let from: S = kani::any();
13+
let mut to: u64 = kani::any();
14+
15+
let from_ptr = &from as *const S;
16+
let to_ptr = &mut to as *mut u64;
17+
18+
// This should not cause UB since `copy` is untyped.
19+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<u32>());
20+
21+
// Since the previous copy only copied 4 bytes, no padding was copied, so no padding is read.
22+
let data: u64 = std::ptr::read(to_ptr);
23+
}

tests/expected/uninit/copy/expected

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
std::ptr::read::<u64>.assertion.1\
2+
- Status: FAILURE\
3+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `*const u64`"\
4+
5+
std::ptr::read::<u64>.assertion.2\
6+
- Status: FAILURE\
7+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `u64`"\
8+
9+
Summary:
10+
Verification failed for - expose_padding_via_copy
11+
Complete - 0 successfully verified harnesses, 1 failures, 1 total.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Z uninit-checks
4+
5+
#[repr(C)]
6+
#[derive(kani::Arbitrary)]
7+
struct S(u32, u8); // 5 bytes of data + 3 bytes of padding.
8+
9+
/// This checks that reading copied uninitialized bytes fails an assertion.
10+
#[kani::proof]
11+
unsafe fn expose_padding_via_copy() {
12+
let from: S = kani::any();
13+
let mut to: u64 = kani::any();
14+
15+
let from_ptr = &from as *const S;
16+
let to_ptr = &mut to as *mut u64;
17+
18+
// This should not cause UB since `copy` is untyped.
19+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<S>());
20+
21+
// This reads uninitialized bytes, which is UB.
22+
let padding: u64 = std::ptr::read(to_ptr);
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
std::ptr::read::<u64>.assertion.1\
2+
- Status: FAILURE\
3+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `*const u64`"\
4+
5+
std::ptr::read::<u64>.assertion.2\
6+
- Status: FAILURE\
7+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `u64`"\
8+
9+
Summary:
10+
Verification failed for - expose_padding_via_copy_convoluted
11+
Complete - 0 successfully verified harnesses, 1 failures, 1 total.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Z uninit-checks
4+
5+
#[repr(C)]
6+
#[derive(kani::Arbitrary)]
7+
struct S(u32, u8); // 5 bytes of data + 3 bytes of padding.
8+
9+
10+
/// This checks that reading copied uninitialized bytes fails an assertion even if pointer are
11+
/// passed around different functions.
12+
#[kani::proof]
13+
unsafe fn expose_padding_via_copy_convoluted() {
14+
unsafe fn copy_and_read_helper(from_ptr: *const S, to_ptr: *mut u64) -> u64 {
15+
// This should not cause UB since `copy` is untyped.
16+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<S>());
17+
// This reads uninitialized bytes, which is UB.
18+
let padding: u64 = std::ptr::read(to_ptr);
19+
padding
20+
}
21+
22+
unsafe fn partial_copy_and_read_helper(from_ptr: *const S, to_ptr: *mut u64) -> u32 {
23+
// This should not cause UB since `copy` is untyped.
24+
std::ptr::copy(from_ptr as *const u8, to_ptr as *mut u8, std::mem::size_of::<u32>());
25+
// This does not read uninitialized bytes.
26+
let not_padding: u32 = std::ptr::read(to_ptr as *mut u32);
27+
not_padding
28+
}
29+
30+
let flag: bool = kani::any();
31+
32+
let from: S = kani::any();
33+
let mut to: u64 = kani::any();
34+
35+
let from_ptr = &from as *const S;
36+
let to_ptr = &mut to as *mut u64;
37+
38+
if flag {
39+
copy_and_read_helper(from_ptr, to_ptr);
40+
} else {
41+
partial_copy_and_read_helper(from_ptr, to_ptr);
42+
}
43+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
std::ptr::read::<u64>.assertion.1\
2+
- Status: FAILURE\
3+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `*const u64`"\
4+
5+
std::ptr::read::<u64>.assertion.2\
6+
- Status: FAILURE\
7+
- Description: "Undefined Behavior: Reading from an uninitialized pointer of type `u64`"\
8+
9+
Summary:
10+
Verification failed for - expose_padding_via_non_byte_copy
11+
Complete - 0 successfully verified harnesses, 1 failures, 1 total.

0 commit comments

Comments
 (0)