rapx/verify/property_checker/
string.rs1#[cfg(not(rapx_has_skip_norm_wip))]
2use crate::compat::SkipNormWip;
3use z3::{SatResult, Solver, ast::Int};
4use crate::verify::contract::Property;
5use crate::verify::report::CheckResult;
6use crate::helpers::mir_scan::Checkpoint;
7use crate::verify::vm::state::VmState;
8
9use super::PropertyChecker;
10
11impl PropertyChecker {
12 pub(super) fn check_valid_string<'ctx, 'tcx>(
13 &self,
14 vm_state: &VmState<'ctx, 'tcx>,
15 solver: &Solver<'ctx>,
16 checkpoint: &Checkpoint<'tcx>,
17 property: &Property<'tcx>,
18 ) -> CheckResult {
19 if let Some(count) = property
21 .args()
22 .get(2)
23 .and_then(|a| self.resolve_arg_term(vm_state, checkpoint, a))
24 {
25 if count.as_u64() == Some(0) {
26 return CheckResult::Proved;
27 }
28 }
29
30 let Some(value) = self.target_value(vm_state, checkpoint, property) else {
31 return CheckResult::Proved;
32 };
33 let Some(alloc_id) = value.provenance_alloc_id() else {
34 return CheckResult::Proved;
35 };
36
37 if vm_state.alloc(alloc_id).dead {
39 return CheckResult::Failed;
40 }
41
42 let byte_pairs = vm_state.alloc_byte_values(alloc_id);
44 if byte_pairs.is_empty() {
45 return CheckResult::Proved; }
47 let bytes: Vec<Int<'ctx>> = byte_pairs.iter().map(|(_, t)| (*t).clone()).collect();
48 let valid = super::utf8_validity(vm_state.ctx, &bytes);
49
50 solver.push();
51 solver.assert(&valid);
52 let r = solver.check();
53 solver.pop(1);
54 match r {
55 SatResult::Unsat => CheckResult::Failed,
56 _ => CheckResult::Proved,
57 }
58 }
59}