Skip to content

Commit a307396

Browse files
committed
Fix CAR creation for local static symbols
1 parent 3fca566 commit a307396

File tree

3 files changed

+45
-30
lines changed

3 files changed

+45
-30
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
static int x;
5+
6+
void foo() __CPROVER_assigns(x)
7+
{
8+
int *y = &x;
9+
10+
static int x;
11+
x++;
12+
13+
(*y)++;
14+
}
15+
16+
int main()
17+
{
18+
foo();
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo _ --pointer-primitive-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS$
7+
^\[foo.\d+\] line \d+ Check that foo\$\$1\$\$x is assignable: SUCCESS$
8+
^\[foo.\d+\] line \d+ Check that \*y is assignable: SUCCESS$
9+
^VERIFICATION SUCCESSFUL$
10+
--
11+
--
12+
Checks whether static local and global variables are correctly tracked
13+
in assigns clause verification.

src/goto-instrument/contracts/contracts.cpp

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -628,39 +628,17 @@ goto_functionst &code_contractst::get_goto_functions()
628628
}
629629

630630
void code_contractst::instrument_assign_statement(
631-
goto_programt::instructionst::iterator &instruction_iterator,
631+
goto_programt::instructionst::iterator &instruction_it,
632632
goto_programt &program,
633633
assigns_clauset &assigns_clause)
634634
{
635635
INVARIANT(
636-
instruction_iterator->is_assign(),
636+
instruction_it->is_assign(),
637637
"The first instruction of instrument_assign_statement should always be"
638638
" an assignment");
639639

640-
const exprt &lhs = instruction_iterator->assign_lhs();
641-
642-
// Local static variables are not declared locally, therefore, they are not
643-
// included in the local write set during declaration. We check here whether
644-
// lhs of the assignment is a local static variable and, if it is indeed
645-
// true, we add lhs to our local write set before checking the assignment.
646-
if(lhs.id() == ID_symbol)
647-
{
648-
auto lhs_sym = ns.lookup(lhs.get(ID_identifier));
649-
if(
650-
lhs_sym.is_static_lifetime &&
651-
lhs_sym.location.get_function() ==
652-
instruction_iterator->source_location.get_function())
653-
{
654-
// TODO: Fix this.
655-
// The CAR snapshot should be made only once at the beginning.
656-
const auto car = assigns_clause.add_to_write_set(lhs);
657-
auto snapshot_instructions = car->generate_snapshot_instructions();
658-
insert_before_swap_and_advance(
659-
program, instruction_iterator, snapshot_instructions);
660-
}
661-
}
662-
663-
add_containment_check(program, assigns_clause, instruction_iterator, lhs);
640+
add_containment_check(
641+
program, assigns_clause, instruction_it, instruction_it->assign_lhs());
664642
}
665643

666644
void code_contractst::instrument_call_statement(
@@ -798,11 +776,16 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
798776
function,
799777
symbol_table);
800778

801-
// Adds formal parameters to freely assignable set
802-
for(auto &parameter : to_code_type(target.type).parameters())
779+
// Adds formal parameters to write set
780+
for(const auto &param : to_code_type(target.type).parameters())
781+
assigns.add_to_write_set(ns.lookup(param.get_identifier()).symbol_expr());
782+
783+
// Adds local static declarations to write set
784+
for(const auto &sym_pair : symbol_table)
803785
{
804-
assigns.add_to_write_set(
805-
ns.lookup(parameter.get_identifier()).symbol_expr());
786+
const auto &sym = sym_pair.second;
787+
if(sym.is_static_lifetime && sym.location.get_function() == function)
788+
assigns.add_to_write_set(sym.symbol_expr());
806789
}
807790

808791
auto instruction_it = function_obj->second.body.instructions.begin();

0 commit comments

Comments
 (0)