use crate::helpers::mir_scan::Checkpoint;
use crate::verify::contract::Property;
use crate::verify::report::CheckResult;
use crate::verify::vm::state::VmState;
use z3::{SatResult, Solver, ast::Int};
use super::PropertyChecker;
impl PropertyChecker {
pub(super) fn check_valid_string<'ctx, 'tcx>(
&self,
vm_state: &VmState<'ctx, 'tcx>,
solver: &Solver<'ctx>,
checkpoint: &Checkpoint<'tcx>,
property: &Property<'tcx>,
) -> CheckResult {
if let Some(count) = property
.args()
.get(2)
.and_then(|a| self.resolve_arg_term(vm_state, checkpoint, a))
{
if count.as_u64() == Some(0) {
return CheckResult::Proved;
}
}
let Some(value) = self.target_value(vm_state, checkpoint, property) else {
return CheckResult::Proved;
};
let Some(alloc_id) = value.provenance_alloc_id() else {
return CheckResult::Proved;
};
if vm_state.alloc(alloc_id).dead {
return CheckResult::Failed;
}
let byte_pairs = vm_state.alloc_byte_values(alloc_id);
if byte_pairs.is_empty() {
return CheckResult::Proved; }
let bytes: Vec<Int<'ctx>> = byte_pairs.iter().map(|(_, t)| (*t).clone()).collect();
let valid = super::utf8_validity(vm_state.ctx, &bytes);
solver.push();
solver.assert(&valid);
let r = solver.check();
solver.pop(1);
match r {
SatResult::Unsat => CheckResult::Failed,
_ => CheckResult::Proved,
}
}
}