Skip to content

Commit 595e91e

Browse files
Fix: Do not nondet functions and fix scoping issue
In goto-harness: - we used is_static && is_lvalue to determine something was global. Turns out that this also applies to extern functions for some reason, so we ended up accidentally creating nondet assignments to those. We now check type.id() != ID_code as well. - we declared pointers to local variables. In if blocks. Which went out of scope before using them. This meant we had a bunch of dangling references. We solve this by creating global variables for our pointer-pointees instead of local ones. Co-authored-by: Fotis Koutoulakis <[email protected]> Co-authored-by: Hannes Steffenhagen <[email protected]>
1 parent 55eec59 commit 595e91e

File tree

7 files changed

+101
-4
lines changed

7 files changed

+101
-4
lines changed

regression/goto-harness/chain.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ if [ -e "${name}-mod.gb" ] ; then
2424
fi
2525

2626
$goto_harness "${name}.gb" "${name}-mod.gb" --harness-function-name $entry_point ${args}
27-
$cbmc --function $entry_point "${name}-mod.gb"
27+
$cbmc --function $entry_point "${name}-mod.gb" --unwind 20 --unwinding-assertions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
3+
#define NULL 0
4+
5+
typedef struct list
6+
{
7+
int datum;
8+
struct list *next;
9+
} list_nodet;
10+
11+
void test_function(list_nodet *node)
12+
{
13+
int i = 0;
14+
list_nodet *list_walker = node;
15+
while(list_walker)
16+
{
17+
list_walker->datum = ++i;
18+
list_walker = list_walker->next;
19+
}
20+
list_walker = node;
21+
i = 0;
22+
while(list_walker)
23+
{
24+
assert(list_walker->datum == ++i);
25+
list_walker = list_walker->next;
26+
}
27+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--harness-type call-function --max-nondet-tree-depth 4 --min-null-tree-depth 1 --function test_function
4+
\[test_function.unwind.\d+\] line \d+ unwinding assertion loop 0: SUCCESS
5+
\[test_function.unwind.\d+\] line \d+ unwinding assertion loop 1: SUCCESS
6+
\[test_function.assertion.\d+\] line \d+ assertion list_walker->datum == \+\+i: SUCCESS
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
VERIFICATION SUCCESSFUL
10+
--
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
3+
#define NULL 0
4+
5+
typedef struct list
6+
{
7+
int datum;
8+
struct list *next;
9+
} list_nodet;
10+
11+
list_nodet *global_list;
12+
void test_function(void)
13+
{
14+
int i = 0;
15+
list_nodet *list_walker = global_list;
16+
while(list_walker)
17+
{
18+
list_walker->datum = ++i;
19+
list_walker = list_walker->next;
20+
}
21+
list_walker = global_list;
22+
i = 0;
23+
while(list_walker)
24+
{
25+
assert(list_walker->datum == ++i);
26+
list_walker = list_walker->next;
27+
}
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--harness-type call-function --max-nondet-tree-depth 4 --min-null-tree-depth 1 --function test_function --nondet-globals
4+
\[test_function.unwind.\d+\] line \d+ unwinding assertion loop 0: SUCCESS
5+
\[test_function.unwind.\d+\] line \d+ unwinding assertion loop 1: SUCCESS
6+
\[test_function.assertion.\d+\] line \d+ assertion list_walker->datum == \+\+i: SUCCESS
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
VERIFICATION SUCCESSFUL
10+
--

src/goto-harness/function_call_harness_generator.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,16 +180,29 @@ void function_call_harness_generatort::implt::generate_nondet_globals(
180180
{
181181
if(nondet_globals)
182182
{
183+
// generating initialisation code may introduce new globals
184+
// i.e. modify the symbol table.
185+
// Modifying the symbol table while iterating over it is not
186+
// a good idea, therefore we just collect the names of globals
187+
// we need to initialise first and then generate the
188+
// initialisation code for all of them.
189+
auto global_names = std::vector<irep_idt>{};
183190
for(const auto &symbol_table_entry : *symbol_table)
184191
{
185192
const auto &symbol = symbol_table_entry.second;
186193
if(
187194
symbol.is_static_lifetime && symbol.is_lvalue &&
195+
symbol.type.id() != ID_code &&
188196
!has_prefix(id2string(symbol.name), CPROVER_PREFIX))
189197
{
190-
generate_initialisation_code_for(function_body, symbol.symbol_expr());
198+
global_names.push_back(symbol.name);
191199
}
192200
}
201+
for(auto const &global_name : global_names)
202+
{
203+
generate_initialisation_code_for(
204+
function_body, symbol_table->lookup_ref(global_name).symbol_expr());
205+
}
193206
}
194207
}
195208

src/goto-harness/recursive_initialization.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,17 @@ void recursive_initializationt::initialize_pointer(
9393
goto_model.symbol_table};
9494
exprt choice =
9595
allocate_objects.allocate_automatic_local_object(bool_typet{}, "choice");
96-
auto pointee =
97-
allocate_objects.allocate_automatic_local_object(type.subtype(), "pointee");
96+
symbolt &pointee_symbol = get_fresh_aux_symbol(
97+
type.subtype(),
98+
"__goto_harness",
99+
"pointee",
100+
lhs.source_location(),
101+
initialization_config.mode,
102+
goto_model.symbol_table);
103+
pointee_symbol.is_static_lifetime = true;
104+
pointee_symbol.is_lvalue = true;
105+
106+
auto pointee = pointee_symbol.symbol_expr();
98107
allocate_objects.declare_created_symbols(body);
99108
body.add(code_assignt{lhs, null_pointer_exprt{type}});
100109
bool is_unknown_struct_tag =

0 commit comments

Comments
 (0)