Skip to content

Commit

Permalink
SMT2 back-end: detect when solver returns unexpected model
Browse files Browse the repository at this point in the history
We have seen examples of Z3 responding with
```
((B1502 (forall ((|main::tmp_cc$0!0@1#0| (_ BitVec 64)))
  (let ((a!1 (or (and (not (bvule #x000000000000000c |main::tmp_cc$0!0@1#0|))
                      (bvule #x000000000000000b |main::tmp_cc$0!0@1#0|)
[...]
```
when we expected just `true` or `false` as model (which Bitwuzla seemed
to get right on the very same input program). Report these as errors
rather than using the incomplete assignment. Such an incomplete
assignment would make us re-try forever without making progress.

Fixes: #8365
  • Loading branch information
tautschnig committed Jul 12, 2024
1 parent 629dbcd commit 2ec4974
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE smt-backend no-new-smt
KNOWNBUG smt-backend no-new-smt
smt_missing_range_check.c
--no-malloc-may-fail --pointer-check -z3
^EXIT=10$
Expand All @@ -9,7 +9,10 @@ smt_missing_range_check.c
--
--
Check that memory checks fail for pointer dereferences inside an existential
qualifier, for out of bounds memory access, when using the smt backend and
quantifier, for out of bounds memory access, when using the smt backend and
the range of the index is unbound. Note that this test is not expected to work
with the SAT backend at the time of writing, as the SAT backend does not support
qualifiers in this form.
quantifiers in this form.

Neither Z3 nor CVC5 currently return complete models, and Bitwuzla does not
complete in more than 5 minutes.
45 changes: 34 additions & 11 deletions src/solvers/smt2/smt2_dec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,22 +236,45 @@ decision_proceduret::resultt smt2_dect::read_result(std::istream &in)
{
const std::string boolean_identifier =
convert_identifier("B" + std::to_string(v));
boolean_assignment[v] = [&]() {
const auto found_parsed_value =
parsed_values.find(drop_quotes(boolean_identifier));
if(found_parsed_value != parsed_values.end())
{
return found_parsed_value->second.id() == ID_true;
const irept &value = found_parsed_value->second;

if(value.id() != ID_true && value.id() != ID_false)
{
messaget log{message_handler};
log.error() << "SMT2 solver returned non-Boolean value for variable "
<< boolean_identifier << messaget::eom;
return decision_proceduret::resultt::D_ERROR;
}
boolean_assignment[v] = value.id() == ID_true;
}
else
{
// Work out the value based on what set_to was called with.
const auto found_set_value = set_values.find(boolean_identifier);
if(found_set_value != set_values.end())
boolean_assignment[v] = found_set_value->second;
else
{
// Old code used the computation
// const irept &value=values["B"+std::to_string(v)];
// boolean_assignment[v]=(value.id()==ID_true);
const irept &value = parsed_values[boolean_identifier];

if(value.id() != ID_true && value.id() != ID_false)
{
messaget log{message_handler};
log.error()
<< "SMT2 solver returned non-Boolean value for variable "
<< boolean_identifier << messaget::eom;
return decision_proceduret::resultt::D_ERROR;
}
boolean_assignment[v] = value.id() == ID_true;
}
}
// Work out the value based on what set_to was called with.
const auto found_set_value = set_values.find(boolean_identifier);
if(found_set_value != set_values.end())
return found_set_value->second;
// Old code used the computation
// const irept &value=values["B"+std::to_string(v)];
// boolean_assignment[v]=(value.id()==ID_true);
return parsed_values[boolean_identifier].id() == ID_true;
}();
}

return res;
Expand Down

0 comments on commit 2ec4974

Please sign in to comment.