Skip to content

Commit 4674660

Browse files
jrey8343claude
andcommitted
Fix check_count_bytes harness: use kani::assume instead of array mutation
The original harness mutated a symbolic array at a symbolic index (bytes[len] = 0), which CBMC's array-store model doesn't reliably propagate when the array and index are both fully symbolic. This caused from_bytes_until_nul(...).unwrap() to fail spuriously. Rewrite using kani::assume to directly constrain the symbolic space: assume bytes[len] == 0 and bytes[i] != 0 for i < len. This is semantically equivalent but avoids the problematic symbolic store. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b2bc80d commit 4674660

1 file changed

Lines changed: 16 additions & 14 deletions

File tree

library/core/src/ffi/c_str.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,25 +1001,27 @@ mod verify {
10011001

10021002
// pub const fn count_bytes(&self) -> usize
10031003
#[kani::proof]
1004-
#[kani::unwind(32)]
1004+
#[kani::unwind(33)]
10051005
fn check_count_bytes() {
10061006
const MAX_SIZE: usize = 32;
1007-
let mut bytes: [u8; MAX_SIZE] = kani::any();
1008-
1009-
// Non-deterministically generate a length within the valid range [0, MAX_SIZE]
1010-
let mut len: usize = kani::any_where(|&x| x < MAX_SIZE);
1011-
1012-
// If a null byte exists before the generated length
1013-
// adjust len to its position
1014-
if let Some(pos) = bytes[..len].iter().position(|&x| x == 0) {
1015-
len = pos;
1016-
} else {
1017-
// If no null byte, insert one at the chosen length
1018-
bytes[len] = 0;
1007+
let bytes: [u8; MAX_SIZE] = kani::any();
1008+
1009+
// Non-deterministically choose the position of the null terminator.
1010+
let len: usize = kani::any_where(|&x: &usize| x < MAX_SIZE);
1011+
1012+
// Constrain bytes to form a valid C string of length `len`:
1013+
// bytes[0..len] must be non-null, bytes[len] must be 0.
1014+
// Using assume on the immutable array avoids the CBMC array-store
1015+
// issue that arises when mutating a symbolic array at a symbolic index.
1016+
kani::assume(bytes[len] == 0);
1017+
for i in 0..MAX_SIZE {
1018+
if i < len {
1019+
kani::assume(bytes[i] != 0);
1020+
}
10191021
}
10201022

10211023
let c_str = CStr::from_bytes_until_nul(&bytes).unwrap();
1022-
// Verify that count_bytes matches the adjusted length
1024+
// Verify that count_bytes matches the chosen null position
10231025
assert_eq!(c_str.count_bytes(), len);
10241026
assert!(c_str.is_safe());
10251027
}

0 commit comments

Comments
 (0)