rapx/verify/property_checker/
string.rs1use crate::helpers::mir_scan::Checkpoint;
4use crate::verify::contract::Property;
5use crate::verify::report::CheckResult;
6use crate::verify::vm::state::VmState;
7use z3::{SatResult, Solver};
8
9use super::PropertyChecker;
10
11impl PropertyChecker {
12 fn check_utf8_alloc<'z3, 'tcx>(
16 &self,
17 vm_state: &VmState<'z3, 'tcx>,
18 solver: &Solver<'z3>,
19 alloc_id: crate::verify::vm::state::AllocId,
20 ) -> CheckResult {
21 if vm_state.alloc(alloc_id).facts.dead {
22 return CheckResult::Failed;
23 }
24 if vm_state.is_utf8_trusted(alloc_id) {
25 return CheckResult::ProvedByRule;
26 }
27 let Some(valid) = vm_state.utf8_validity(alloc_id) else {
28 return CheckResult::ProvedByRule; };
30
31 solver.push();
32 solver.assert(&valid);
33 let r = solver.check();
34 solver.pop(1);
35 match r {
36 SatResult::Unsat => CheckResult::Failed,
37 _ => CheckResult::ProvedByRule,
38 }
39 }
40
41 pub(super) fn check_valid_string<'z3, 'tcx>(
42 &self,
43 vm_state: &VmState<'z3, 'tcx>,
44 solver: &Solver<'z3>,
45 checkpoint: &Checkpoint<'tcx>,
46 property: &Property<'tcx>,
47 ) -> CheckResult {
48 if let Some(count) = property
50 .args()
51 .get(2)
52 .and_then(|a| self.resolve_arg_term(vm_state, checkpoint, a))
53 {
54 if count.as_u64() == Some(0) {
55 return CheckResult::ProvedByRule;
56 }
57 }
58
59 let Some(value) = self.target_value(vm_state, checkpoint, property) else {
60 return CheckResult::ProvedByRule;
61 };
62 if let Some(alloc_id) = value.provenance_alloc_id() {
63 return self.check_utf8_alloc(vm_state, solver, alloc_id);
64 }
65
66 if let Some(local) = vm_state.find_local_by_address(&value.z3_term) {
70 if let Some((alloc_id, _end_offset)) = vm_state.iter_utf8_buffer(local) {
71 return self.check_utf8_alloc(vm_state, solver, alloc_id);
72 }
73 }
74 CheckResult::ProvedByRule
75 }
76}