@@ -204,7 +204,9 @@ impl Invariant for &CStr {
204
204
let bytes: & [ c_char ] = & self . inner ;
205
205
let len = bytes. len ( ) ;
206
206
207
- !bytes. is_empty ( ) && bytes[ len - 1 ] == 0 && !bytes[ ..len - 1 ] . contains ( & 0 )
207
+ !bytes. is_empty ( )
208
+ && bytes[ len - 1 ] == 0
209
+ && forall ! ( |i in ( 0 , len - 1 ) | unsafe { * bytes. as_ptr( ) . wrapping_add( i) } != 0 )
208
210
}
209
211
}
210
212
@@ -880,13 +882,13 @@ mod verify {
880
882
// Helper function
881
883
fn arbitrary_cstr ( slice : & [ u8 ] ) -> & CStr {
882
884
// At a minimum, the slice has a null terminator to form a valid CStr.
885
+ let len = slice. len ( ) ;
883
886
kani:: assume ( slice. len ( ) > 0 && slice[ slice. len ( ) - 1 ] == 0 ) ;
884
- let result = CStr :: from_bytes_until_nul ( & slice) ;
885
- // Given the assumption, from_bytes_until_nul should never fail
886
- assert ! ( result. is_ok( ) ) ;
887
- let c_str = result. unwrap ( ) ;
888
- assert ! ( c_str. is_safe( ) ) ;
889
- c_str
887
+ kani:: assume ( forall ! ( |i in ( 0 , len-1 ) | unsafe { * slice. as_ptr( ) . wrapping_add( i) } != 0 ) ) ;
888
+ let ptr = slice. as_ptr ( ) as * const c_char ;
889
+ unsafe {
890
+ CStr :: from_ptr ( ptr) ;
891
+ }
890
892
}
891
893
892
894
// pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError>
@@ -908,7 +910,7 @@ mod verify {
908
910
909
911
// pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr
910
912
#[ kani:: proof_for_contract( CStr :: from_bytes_with_nul_unchecked) ]
911
- #[ kani:: solver ( cvc5 ) ]
913
+ #[ kani:: unwind ( 33 ) ]
912
914
fn check_from_bytes_with_nul_unchecked ( ) {
913
915
const MAX_SIZE : usize = 32 ;
914
916
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -927,8 +929,7 @@ mod verify {
927
929
928
930
// pub fn bytes(&self) -> Bytes<'_>
929
931
#[ kani:: proof]
930
- #[ kani:: solver( cvc5) ]
931
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
932
+ #[ kani:: unwind( 32 ) ]
932
933
fn check_bytes ( ) {
933
934
const MAX_SIZE : usize = 32 ;
934
935
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -946,8 +947,7 @@ mod verify {
946
947
947
948
// pub const fn to_str(&self) -> Result<&str, str::Utf8Error>
948
949
#[ kani:: proof]
949
- #[ kani:: solver( cvc5) ]
950
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
950
+ #[ kani:: unwind( 32 ) ]
951
951
fn check_to_str ( ) {
952
952
const MAX_SIZE : usize = 32 ;
953
953
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -964,8 +964,7 @@ mod verify {
964
964
965
965
// pub const fn as_ptr(&self) -> *const c_char
966
966
#[ kani:: proof]
967
- #[ kani:: solver( cvc5) ]
968
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
967
+ #[ kani:: unwind( 33 ) ]
969
968
fn check_as_ptr ( ) {
970
969
const MAX_SIZE : usize = 32 ;
971
970
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -1015,15 +1014,8 @@ mod verify {
1015
1014
1016
1015
// Non-deterministically generate a length within the valid range [0, MAX_SIZE]
1017
1016
let mut len: usize = kani:: any_where ( |& x| x < MAX_SIZE ) ;
1018
-
1019
- // If a null byte exists before the generated length
1020
- // adjust len to its position
1021
- if let Some ( pos) = bytes[ ..len] . iter ( ) . position ( |& x| x == 0 ) {
1022
- len = pos;
1023
- } else {
1024
- // If no null byte, insert one at the chosen length
1025
- bytes[ len] = 0 ;
1026
- }
1017
+ kani:: assume ( forall ! ( |i in ( 0 , len) | unsafe { * bytes. as_ptr( ) . wrapping_add( i) } != 0 ) ) ;
1018
+ bytes[ len] = 0 ;
1027
1019
1028
1020
let c_str = CStr :: from_bytes_until_nul ( & bytes) . unwrap ( ) ;
1029
1021
// Verify that count_bytes matches the adjusted length
@@ -1033,8 +1025,7 @@ mod verify {
1033
1025
1034
1026
// pub const fn to_bytes(&self) -> &[u8]
1035
1027
#[ kani:: proof]
1036
- #[ kani:: solver( cvc5) ]
1037
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
1028
+ #[ kani:: unwind( 32 ) ]
1038
1029
fn check_to_bytes ( ) {
1039
1030
const MAX_SIZE : usize = 32 ;
1040
1031
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -1050,8 +1041,7 @@ mod verify {
1050
1041
1051
1042
// pub const fn to_bytes_with_nul(&self) -> &[u8]
1052
1043
#[ kani:: proof]
1053
- #[ kani:: solver( cvc5) ]
1054
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
1044
+ #[ kani:: unwind( 33 ) ]
1055
1045
fn check_to_bytes_with_nul ( ) {
1056
1046
const MAX_SIZE : usize = 32 ;
1057
1047
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -1067,8 +1057,7 @@ mod verify {
1067
1057
1068
1058
// const unsafe fn strlen(ptr: *const c_char) -> usize
1069
1059
#[ kani:: proof_for_contract( super :: strlen) ]
1070
- #[ kani:: solver( cvc5) ]
1071
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
1060
+ #[ kani:: unwind( 33 ) ]
1072
1061
fn check_strlen_contract ( ) {
1073
1062
const MAX_SIZE : usize = 32 ;
1074
1063
let mut string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -1081,8 +1070,7 @@ mod verify {
1081
1070
1082
1071
// pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr
1083
1072
#[ kani:: proof_for_contract( CStr :: from_ptr) ]
1084
- #[ kani:: solver( cvc5) ]
1085
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
1073
+ #[ kani:: unwind( 33 ) ]
1086
1074
fn check_from_ptr_contract ( ) {
1087
1075
const MAX_SIZE : usize = 32 ;
1088
1076
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
@@ -1095,8 +1083,7 @@ mod verify {
1095
1083
1096
1084
// pub const fn is_empty(&self) -> bool
1097
1085
#[ kani:: proof]
1098
- #[ kani:: solver( cvc5) ]
1099
- #[ cfg( not( all( target_arch = "x86_64" , target_feature = "sse2" ) ) ) ]
1086
+ #[ kani:: unwind( 33 ) ]
1100
1087
fn check_is_empty ( ) {
1101
1088
const MAX_SIZE : usize = 32 ;
1102
1089
let string: [ u8 ; MAX_SIZE ] = kani:: any ( ) ;
0 commit comments