Skip to content

Refinement of guard based on antecedent of implication statement #6434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions regression/cbmc-primitives/implication_statement_checks_1/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// clang-format off
int main(int argc, char **argv)
{
int y;

__CPROVER_assert(
y != 0 ==> 10 / y <= 10,
"10 / y is expected to succeed");
}
// clang-format on
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CORE
--div-by-zero-check
test.c
^EXIT=0$
^SIGNAL=0$
\[main\.assertion\.1\] line \d 10 / y is expected to succeed: SUCCESS
\[main\.division-by-zero\.1\] line \d division by zero in 10 / y: SUCCESS
^VERIFICATION SUCCESSFUL$
--
\[main\.division-by-zero\.1\] line \d division by zero in 10 / y: FAILURE
--
Without the change that drives the refinement of the guard for a `ID_implies`
statement in `goto-check`, this will fail with a counterexample of `y = 0`.
With the bug fix, the `--div-by-zero-check` will succeed because the
antecedent of the conditional is becoming the guard for the consequent,
guarding any checks performed there.
4 changes: 3 additions & 1 deletion src/analyses/goto_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,8 @@ void goto_checkt::check_rec_address(const exprt &expr, guardt &guard)

void goto_checkt::check_rec_logical_op(const exprt &expr, guardt &guard)
{
PRECONDITION(
expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_implies);
INVARIANT(
expr.is_boolean(),
"'" + expr.id_string() + "' must be Boolean, but got " + expr.pretty());
Expand Down Expand Up @@ -1736,7 +1738,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard)
check_rec_address(to_address_of_expr(expr).object(), guard);
return;
}
else if(expr.id() == ID_and || expr.id() == ID_or)
else if(expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_implies)
{
check_rec_logical_op(expr, guard);
return;
Expand Down