Skip to content

Commit e9cfb2c

Browse files
committed
Fix contract enforcement to work with (local and global) static variables
Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent c255a15 commit e9cfb2c

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <assert.h>
2+
3+
static int b = 0;
4+
static int c = 0;
5+
6+
int f() __CPROVER_assigns()
7+
{
8+
static int a = 0;
9+
a++;
10+
return a;
11+
}
12+
13+
int g(int *points_to_b, int *points_to_c)
14+
__CPROVER_assigns(b) // Error: it should also mention c
15+
{
16+
b = 1;
17+
c = 2;
18+
*points_to_b = 1;
19+
*points_to_c = 2;
20+
}
21+
22+
int main()
23+
{
24+
assert(f() == 1);
25+
assert(f() == 2);
26+
assert(b == 0);
27+
assert(c == 0);
28+
g(&b, &c);
29+
assert(b == 1);
30+
assert(c == 2);
31+
32+
return 0;
33+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[f.\d+\] line \d+ Check that a is assignable: SUCCESS$
7+
^\[g.\d+\] line \d+ Check that b is assignable: SUCCESS$
8+
^\[g.\d+\] line \d+ Check that c is assignable: FAILURE$
9+
^\[g.\d+\] line \d+ Check that \*points\_to\_b is assignable: SUCCESS$
10+
^\[g.\d+\] line \d+ Check that \*points\_to\_c is assignable: FAILURE$
11+
^VERIFICATION FAILED$
12+
--
13+
--
14+
Checks whether contract enforcement works with (local and global) static variables.
15+
Local static variables should be part of the local write set.
16+
Global static variables should be included in the global write set,
17+
otherwise any assignment to it is invalid.

src/goto-instrument/contracts/contracts.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,20 @@ void code_contractst::instrument_assign_statement(
678678

679679
const exprt &lhs = instruction_iterator->assign_lhs();
680680

681+
// Local static variables are not declared locally, therefore, they are not
682+
// included in the local write set during declaration. We check here whether
683+
// lhs of the assignment is a local static variable and, if it is indeed
684+
// true, we add lhs to our local write set before checking the assignment.
685+
if(lhs.id() == ID_symbol)
686+
{
687+
auto lhs_sym = ns.lookup(lhs.get(ID_identifier));
688+
if(
689+
lhs_sym.is_static_lifetime &&
690+
lhs_sym.location.get_function() ==
691+
instruction_iterator->source_location.get_function())
692+
assigns_clause.add_local_write_set(lhs);
693+
}
694+
681695
goto_programt alias_assertion;
682696
alias_assertion.add(goto_programt::make_assertion(
683697
assigns_clause.generate_containment_check(lhs),

0 commit comments

Comments
 (0)