Skip to content

Commit 065a56b

Browse files
committed
Ignore false assertion during loop invariant synthesis
1 parent a22c2de commit 065a56b

File tree

5 files changed

+64
-22
lines changed

5 files changed

+64
-22
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <stdlib.h>
2+
#include <stdbool.h>
3+
4+
void main()
5+
{
6+
long x = 0;
7+
long y;
8+
__CPROVER_assume(y > 1);
9+
10+
while(y > 0)
11+
{
12+
x = 1;
13+
y = y - 1;
14+
}
15+
16+
assert(false);
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.\d+\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.assigns.\d+\] .* Check that x is assignable: SUCCESS$
8+
^\[main.assigns.\d+\] .* Check that y is assignable: SUCCESS$
9+
^\*\* 1 of \d+ failed
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Check whether loop invariant are synthesized when there is ASSERT FALSE.

src/goto-synthesizer/cegis_verifier.cpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,8 @@ optionalt<cext> cegis_verifiert::verify()
588588
// 3. construct the formatted counterexample from the violated property and
589589
// its trace.
590590

591+
const namespacet ns(goto_model.symbol_table);
592+
591593
// Store the original functions. We will restore them after the verification.
592594
for(const auto &fun_entry : goto_model.goto_functions.function_map)
593595
{
@@ -652,38 +654,48 @@ optionalt<cext> cegis_verifiert::verify()
652654
}
653655

654656
properties = checker->get_properties();
655-
bool target_violation_found = false;
656-
auto target_violation_info = properties.begin()->second;
657+
auto target_violation = properties.end();
657658

658659
// Find target violation---the violation we want to fix next.
659660
// A target violation is an assignable violation or the first violation that
660661
// is not assignable violation.
661-
for(const auto &property : properties)
662+
for(auto it_property = properties.begin(); it_property != properties.end();
663+
it_property++)
662664
{
663-
if(property.second.status != property_statust::FAIL)
665+
if(it_property->second.status != property_statust::FAIL)
664666
continue;
665667

666668
// assignable violation found
667-
if(property.second.description.find("assignable") != std::string::npos)
669+
if(it_property->second.description.find("assignable") != std::string::npos)
668670
{
669-
target_violation = property.first;
670-
target_violation_info = property.second;
671+
target_violation = it_property;
671672
break;
672673
}
673674

674675
// Store the violation that we want to fix with synthesized
675676
// assigns/invariant.
676-
if(!target_violation_found)
677+
// ignore ASSERT FALSE
678+
if(
679+
target_violation == properties.end() &&
680+
simplify_expr(it_property->second.pc->condition(), ns) != false_exprt())
677681
{
678-
target_violation = property.first;
679-
target_violation_info = property.second;
680-
target_violation_found = true;
682+
target_violation = it_property;
681683
}
682684
}
683685

686+
// All violations are
687+
// ASSERT FALSE
688+
if(target_violation == properties.end())
689+
{
690+
restore_functions();
691+
return optionalt<cext>();
692+
}
693+
694+
target_violation_id = target_violation->first;
695+
684696
// Decide the violation type from the description of violation
685697
cext::violation_typet violation_type =
686-
extract_violation_type(target_violation_info.description);
698+
extract_violation_type(target_violation->second.description);
687699

688700
// Compute the cause loop---the loop for which we synthesize loop contracts,
689701
// and the counterexample.
@@ -698,17 +710,17 @@ optionalt<cext> cegis_verifiert::verify()
698710
// although there can be multiple ones.
699711

700712
log.debug() << "Start to compute cause loop ids." << messaget::eom;
701-
log.debug() << "Violation description: " << target_violation_info.description
702-
<< messaget::eom;
713+
log.debug() << "Violation description: "
714+
<< target_violation->second.description << messaget::eom;
703715

704-
const auto &trace = checker->get_traces()[target_violation];
716+
const auto &trace = checker->get_traces()[target_violation->first];
705717
// Doing assigns-synthesis or invariant-synthesis
706718
if(violation_type == cext::violation_typet::cex_assignable)
707719
{
708720
cext result(violation_type);
709721
result.cause_loop_ids = get_cause_loop_id_for_assigns(trace);
710722
result.checked_pointer = static_cast<const exprt &>(
711-
target_violation_info.pc->condition().find(ID_checked_assigns));
723+
target_violation->second.pc->condition().find(ID_checked_assigns));
712724
restore_functions();
713725
return result;
714726
}
@@ -719,7 +731,7 @@ optionalt<cext> cegis_verifiert::verify()
719731
// Although there can be multiple cause loop ids. We only synthesize
720732
// loop invariants for the first cause loop.
721733
const std::list<loop_idt> cause_loop_ids =
722-
get_cause_loop_id(trace, target_violation_info.pc);
734+
get_cause_loop_id(trace, target_violation->second.pc);
723735

724736
if(cause_loop_ids.empty())
725737
{
@@ -743,7 +755,7 @@ optionalt<cext> cegis_verifiert::verify()
743755
violation_location = get_violation_location(
744756
cause_loop_ids.front(),
745757
goto_model.get_goto_function(cause_loop_ids.front().function_id),
746-
target_violation_info.pc->location_number);
758+
target_violation->second.pc->location_number);
747759
}
748760

749761
restore_functions();
@@ -755,7 +767,7 @@ optionalt<cext> cegis_verifiert::verify()
755767
goto_model.goto_functions
756768
.function_map[cause_loop_ids.front().function_id])
757769
->source_location());
758-
return_cex.violated_predicate = target_violation_info.pc->condition();
770+
return_cex.violated_predicate = target_violation->second.pc->condition();
759771
return_cex.cause_loop_ids = cause_loop_ids;
760772
return_cex.violation_location = violation_location;
761773
return_cex.violation_type = violation_type;
@@ -764,7 +776,7 @@ optionalt<cext> cegis_verifiert::verify()
764776
if(violation_type == cext::violation_typet::cex_null_pointer)
765777
{
766778
return_cex.checked_pointer = get_checked_pointer_from_null_pointer_check(
767-
target_violation_info.pc->condition());
779+
target_violation->second.pc->condition());
768780
}
769781

770782
return return_cex;

src/goto-synthesizer/cegis_verifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class cegis_verifiert
117117

118118
/// Result counterexample.
119119
propertiest properties;
120-
irep_idt target_violation;
120+
irep_idt target_violation_id;
121121

122122
protected:
123123
// Get the options same as using CBMC api without any flag, and

src/goto-synthesizer/enumerative_loop_contracts_synthesizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ invariant_mapt enumerative_loop_contracts_synthesizert::synthesize_all()
379379
new_invariant_clause = synthesize_strengthening_clause(
380380
terminal_symbols,
381381
return_cex->cause_loop_ids.front(),
382-
verifier.target_violation);
382+
verifier.target_violation_id);
383383
break;
384384

385385
case cext::violation_typet::cex_assignable:

0 commit comments

Comments
 (0)