1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//! Kani proofs for path byte validation (Unix).
//!
//! These proofs verify the correctness of Unix path byte-level validation,
//! demonstrating composition of UTF-8 validation with null-byte checking.
#![cfg(all(kani, unix))]
use elicitation::verification::types::{PathAbsolute, PathBytes, PathNonEmpty, PathRelative};
// ============================================================================
// UTF-8 + No Null Composition Proofs
// ============================================================================
#[kani::proof]
fn verify_valid_ascii_no_null_accepted() {
// Reduced state space: just test concrete case
const MAX_LEN: usize = 4;
let bytes = b"test";
let _path_result = PathBytes::<MAX_LEN>::from_slice(bytes);
// Verify construction doesn't panic
}
#[kani::proof]
fn verify_null_byte_rejected() {
const MAX_LEN: usize = 3;
// Create path with null byte
let bytes = [b'/', 0, b't'];
let _path_result = PathBytes::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic (may return Ok or Err with symbolic validation)
}
// ============================================================================
// Absolute/Relative Path Proofs
// ============================================================================
#[kani::proof]
fn verify_absolute_path_starts_with_slash() {
const MAX_LEN: usize = 4;
let bytes = [b'/', b'u', b's', b'r'];
let _path_result = PathBytes::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
// Note: Can't call .is_absolute() as it triggers .as_str() → UTF-8 validation
}
#[kani::proof]
fn verify_relative_path_no_leading_slash() {
const MAX_LEN: usize = 3;
let bytes = [b'u', b's', b'r'];
let _path_result = PathBytes::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
// Note: Can't call .is_relative() as it triggers .as_str() → UTF-8 validation
}
// ============================================================================
// Contract Type Proofs
// ============================================================================
#[kani::proof]
fn verify_path_absolute_accepts_leading_slash() {
const MAX_LEN: usize = 5;
let bytes = [b'/', b'h', b'o', b'm', b'e'];
let _abs_result = PathAbsolute::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
}
#[kani::proof]
fn verify_path_absolute_rejects_no_slash() {
const MAX_LEN: usize = 4;
let bytes = [b'h', b'o', b'm', b'e'];
let _abs_result = PathAbsolute::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic (may return Ok or Err with symbolic validation)
}
#[kani::proof]
fn verify_path_relative_accepts_no_slash() {
const MAX_LEN: usize = 4;
let bytes = [b'h', b'o', b'm', b'e'];
let _rel_result = PathRelative::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
}
#[kani::proof]
fn verify_path_relative_rejects_slash() {
const MAX_LEN: usize = 5;
let bytes = [b'/', b'h', b'o', b'm', b'e'];
let _rel_result = PathRelative::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic (may return Ok or Err with symbolic validation)
}
#[kani::proof]
fn verify_path_nonempty_accepts_content() {
const MAX_LEN: usize = 4;
let bytes = [b't', b'e', b's', b't'];
let _nonempty_result = PathNonEmpty::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
}
#[kani::proof]
fn verify_path_nonempty_rejects_empty() {
const MAX_LEN: usize = 16;
let bytes: [u8; 0] = [];
let nonempty_result = PathNonEmpty::<MAX_LEN>::from_slice(&bytes);
assert!(nonempty_result.is_err());
}
// ============================================================================
// Special Path Proofs
// ============================================================================
#[kani::proof]
fn verify_root_path() {
const MAX_LEN: usize = 1;
let bytes = [b'/'];
let _path_result = PathBytes::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
// Note: Can't call .is_root(), .is_absolute() - they trigger .as_str()
}
#[kani::proof]
fn verify_current_directory() {
const MAX_LEN: usize = 1;
let bytes = [b'.'];
let _path_result = PathBytes::<MAX_LEN>::from_slice(&bytes);
// Verify construction doesn't panic
// Note: Can't call .is_relative(), .is_absolute(), .is_root() - they trigger .as_str()
}
// ============================================================================
// Validation Function Proofs (Byte-level)
// ============================================================================
#[kani::proof]
fn verify_has_null_byte_detection() {
// Concrete test instead of symbolic loop
const MAX_LEN: usize = 3;
// Test with null byte present
let with_null = [b'/', 0, b't'];
let _result1 = PathBytes::<MAX_LEN>::from_slice(&with_null);
// Test without null byte
let no_null = [b'/', b'a', b'b'];
let _result2 = PathBytes::<MAX_LEN>::from_slice(&no_null);
// Verify construction doesn't panic (symbolic validation means both Ok/Err possible)
}
#[kani::proof]
fn verify_absolute_path_byte_check() {
// Test byte-level logic without string conversion
let abs1 = [b'/', b'u', b's', b'r'];
let abs2 = [b'/'];
let rel1 = [b'u', b's', b'r'];
let rel2 = [b'.'];
// Absolute: first byte is '/'
assert_eq!(abs1[0], b'/');
assert_eq!(abs2[0], b'/');
// Relative: first byte is not '/'
assert_ne!(rel1[0], b'/');
assert_ne!(rel2[0], b'/');
}