Skip to content

Commit a52eda8

Browse files
committed
Skip checking frame conditions for local variables
It avoids unnecessary assertions (improving performance) and it prevents cases where memory primitives are invoked with dead objects. Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent 61fd24d commit a52eda8

File tree

12 files changed

+50
-42
lines changed

12 files changed

+50
-42
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
void foo(int *xp) __CPROVER_assigns(*xp)
2+
{
3+
{
4+
int y;
5+
y = 2;
6+
}
7+
int z = 3;
8+
*xp = 1;
9+
}
10+
11+
int main()
12+
{
13+
int *xp = malloc(sizeof(*xp));
14+
foo(xp);
15+
return 0;
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Checks whether verification fails when enforcing a contract
10+
for functions, without assigns clauses, that modify an input.

regression/contracts/assigns_enforce_scoping_01/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ main.c
33
--enforce-all-contracts
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[f1.\d+\] line \d+ Check that f1\$\$1\$\$1\$\$b is assignable: SUCCESS$
76
^\[f1.\d+\] line \d+ Check that \*f1\$\$1\$\$1\$\$b is assignable: SUCCESS$
87
^\[f1.\d+\] line \d+ Check that \*b is assignable: FAILURE$
98
^VERIFICATION FAILED$

regression/contracts/assigns_type_checking_valid_cases/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ main.c
55
^SIGNAL=0$
66
^\[foo1.\d+\] line \d+ Check that a is assignable: SUCCESS$
77
^\[foo10.\d+\] line \d+ Check that buffer\-\>len is assignable: SUCCESS$
8+
^\[foo10.\d+\] line \d+ Check that buffer\-\>aux\.allocated is assignable: SUCCESS$
89
^\[foo2.\d+\] line \d+ Check that b is assignable: SUCCESS$
910
^\[foo3.\d+\] line \d+ Check that b is assignable: SUCCESS$
1011
^\[foo3.\d+\] line \d+ Check that y is assignable: SUCCESS$
@@ -27,7 +28,6 @@ main.c
2728
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)7\] is assignable: SUCCESS$
2829
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)8\] is assignable: SUCCESS$
2930
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)9\] is assignable: SUCCESS$
30-
^\[foo9.\d+\] line \d+ Check that new_array is assignable: SUCCESS$
3131
^\[foo9.\d+\] line \d+ Check that array is assignable: SUCCESS$
3232
^VERIFICATION SUCCESSFUL$
3333
--

regression/contracts/function-calls-05/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
\[postcondition.\d+\] file main.c line \d+ Check ensures clause: SUCCESS
7-
\[foo.\d+\] line \d+ Check that sum is assignable: SUCCESS
87
\[main.assertion.\d+\] line \d+ assertion foo\(\&x, \&y\) \=\= 10: SUCCESS
98
^VERIFICATION SUCCESSFUL$
109
--

regression/contracts/history-pointer-enforce-10/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ main.c
77
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause\: SUCCESS$
88
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause\: SUCCESS$
99
^\[bar.\d+\] line \d+ Check that p\-\>y is assignable\: SUCCESS$
10-
^\[baz.\d+\] line \d+ Check that pp is assignable\: SUCCESS$
11-
^\[baz.\d+\] line \d+ Check that empty is assignable\: SUCCESS$
1210
^\[baz.\d+\] line \d+ Check that p is assignable\: SUCCESS$
1311
^\[baz.\d+\] line \d+ Check that p is assignable\: SUCCESS$
1412
^\[foo.\d+\] line \d+ Check that \*p\-\>y is assignable\: SUCCESS$

regression/contracts/quantifiers-exists-requires-enforce/test.desc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause: SUCCESS$
7-
^\[f1.\d+\] line \d+ Check that found\_four is assignable: SUCCESS$
8-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
9-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
10-
^\[f1.\d+\] line \d+ Check that found\_four is assignable: SUCCESS$
117
^VERIFICATION SUCCESSFUL$
128
--
139
^warning: ignoring

regression/contracts/quantifiers-forall-ensures-enforce/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause: SUCCESS$
7-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
8-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
97
^\[f1.\d+\] line \d+ Check that arr\[\(.*\)i\] is assignable: SUCCESS$
108
^VERIFICATION SUCCESSFUL$
119
--

regression/contracts/quantifiers-forall-requires-enforce/test.desc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause: SUCCESS$
7-
^\[f1.\d+\] line \d+ Check that is\_identity is assignable: SUCCESS$
8-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
9-
^\[f1.\d+\] line \d+ Check that i is assignable: SUCCESS$
10-
^\[f1.\d+\] line \d+ Check that is\_identity is assignable: SUCCESS$
117
^VERIFICATION SUCCESSFUL$
128
--
139
^warning: ignoring

regression/contracts/test_array_memory_enforce/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ main.c
77
\[foo.\d+\] line \d+ Check that \*x is assignable: SUCCESS
88
\[foo.\d+\] line \d+ Check that x\[\(.* int\)5\] is assignable: SUCCESS
99
\[foo.\d+\] line \d+ Check that x\[\(.* int\)9\] is assignable: SUCCESS
10-
\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS
1110
^VERIFICATION SUCCESSFUL$
1211
--
1312
--

src/goto-instrument/contracts/contracts.cpp

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ void code_contractst::instrument_assign_statement(
665665
goto_programt::instructionst::iterator &instruction_iterator,
666666
goto_programt &program,
667667
exprt &assigns,
668-
std::set<irep_idt> &freely_assignable_symbols,
668+
std::set<irep_idt> &local_assignable_symbols,
669669
assigns_clauset &assigns_clause)
670670
{
671671
INVARIANT(
@@ -675,21 +675,26 @@ void code_contractst::instrument_assign_statement(
675675

676676
const exprt &lhs = instruction_iterator->assign_lhs();
677677

678-
goto_programt alias_assertion;
679-
alias_assertion.add(goto_programt::make_assertion(
680-
assigns_clause.alias_expression(lhs),
681-
instruction_iterator->source_location));
682-
alias_assertion.instructions.back().source_location.set_comment(
683-
"Check that " + from_expr(ns, lhs.id(), lhs) + " is assignable");
684-
insert_before_swap_and_advance(
685-
program, instruction_iterator, alias_assertion);
678+
if(
679+
local_assignable_symbols.find(lhs.get(ID_identifier)) ==
680+
local_assignable_symbols.end())
681+
{
682+
goto_programt alias_assertion;
683+
alias_assertion.add(goto_programt::make_assertion(
684+
assigns_clause.alias_expression(lhs),
685+
instruction_iterator->source_location));
686+
alias_assertion.instructions.back().source_location.set_comment(
687+
"Check that " + from_expr(ns, lhs.id(), lhs) + " is assignable");
688+
insert_before_swap_and_advance(
689+
program, instruction_iterator, alias_assertion);
690+
}
686691
}
687692

688693
void code_contractst::instrument_call_statement(
689694
goto_programt::instructionst::iterator &instruction_iterator,
690695
goto_programt &program,
691696
exprt &assigns,
692-
std::set<irep_idt> &freely_assignable_symbols,
697+
std::set<irep_idt> &local_assignable_symbols,
693698
assigns_clauset &assigns_clause)
694699
{
695700
INVARIANT(
@@ -736,9 +741,9 @@ void code_contractst::instrument_call_statement(
736741

737742
if(
738743
call.lhs().is_not_nil() && call.lhs().id() == ID_symbol &&
739-
freely_assignable_symbols.find(
744+
local_assignable_symbols.find(
740745
to_symbol_expr(call.lhs()).get_identifier()) ==
741-
freely_assignable_symbols.end())
746+
local_assignable_symbols.end())
742747
{
743748
exprt alias_expr = assigns_clause.alias_expression(call.lhs());
744749

@@ -893,15 +898,7 @@ void code_contractst::check_frame_conditions(
893898
assigns_clauset assigns(assigns_expr, *this, target.name, log);
894899

895900
// Create a list of variables that are okay to assign.
896-
std::set<irep_idt> freely_assignable_symbols;
897-
// Add all parameters that are not pointers to the freely assignable set
898-
for(code_typet::parametert param : type.parameters())
899-
{
900-
if(param.type().id() != ID_pointer)
901-
{
902-
freely_assignable_symbols.insert(param.get_identifier());
903-
}
904-
}
901+
std::set<irep_idt> local_assignable_symbols;
905902

906903
// Create temporary variables to hold the assigns
907904
// clause targets before they can be modified.
@@ -917,7 +914,7 @@ void code_contractst::check_frame_conditions(
917914
{
918915
if(instruction_it->is_decl())
919916
{
920-
freely_assignable_symbols.insert(
917+
local_assignable_symbols.insert(
921918
instruction_it->get_decl().symbol().get_identifier());
922919

923920
assigns_clause_targett *new_target =
@@ -936,7 +933,7 @@ void code_contractst::check_frame_conditions(
936933
instruction_it,
937934
program,
938935
assigns_expr,
939-
freely_assignable_symbols,
936+
local_assignable_symbols,
940937
assigns);
941938
}
942939
else if(instruction_it->is_function_call())
@@ -945,7 +942,7 @@ void code_contractst::check_frame_conditions(
945942
instruction_it,
946943
program,
947944
assigns_expr,
948-
freely_assignable_symbols,
945+
local_assignable_symbols,
949946
assigns);
950947
}
951948
}

src/goto-instrument/contracts/contracts.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class code_contractst
164164
goto_programt::instructionst::iterator &instruction_it,
165165
goto_programt &program,
166166
exprt &assigns,
167-
std::set<irep_idt> &freely_assignable_symbols,
167+
std::set<irep_idt> &local_assignable_symbols,
168168
assigns_clauset &assigns_clause);
169169

170170
/// Inserts an assertion statement into program before the function call at
@@ -175,7 +175,7 @@ class code_contractst
175175
goto_programt::instructionst::iterator &ins_it,
176176
goto_programt &program,
177177
exprt &assigns,
178-
std::set<irep_idt> &freely_assignable_symbols,
178+
std::set<irep_idt> &local_assignable_symbols,
179179
assigns_clauset &assigns_clause);
180180

181181
/// Creates a boolean expression which is true when there exists an expression

0 commit comments

Comments
 (0)