Skip to content

Commit 2846e8c

Browse files
committed
Explicitly initialise non-static objects with non-deterministic values
1 parent ec56630 commit 2846e8c

File tree

10 files changed

+90
-45
lines changed

10 files changed

+90
-45
lines changed

regression/cbmc/constant_folding2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc/graphml_witness1/test.desc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@ main.c
5454
<data key="startline">21</data>
5555
</edge>
5656
<node id="[0-9\.]*"/>
57-
<edge source="[0-9\.]*" target="[0-9\.]*">
58-
<data key="originfile">main.c</data>
59-
<data key="startline">29</data>
60-
<data key="assumption.scope">main</data>
61-
</edge>
62-
<node id="[0-9\.]*"/>
6357
<edge source="[0-9\.]*" target="[0-9\.]*">
6458
<data key="originfile">main.c</data>
6559
<data key="startline">15</data>

regression/cbmc/struct10/main.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct test_struct
2+
{
3+
int a[2];
4+
int b;
5+
};
6+
7+
int main()
8+
{
9+
struct test_struct test;
10+
test.a[1] = 1;
11+
test.b = 1;
12+
__CPROVER_assert(test.a[1] == 0, "");
13+
}

regression/cbmc/struct10/test.desc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
main.c
3+
--trace
4+
test.a\[1ll?\]=1 \(00000000000000000000000000000001\)$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
10+
\(\?\)
11+
--
12+
Earlier versions of non-deterministic initialisation would cause trace output
13+
including
14+
15+
test.a[1l]={ .a={ 0, 1 }, .b=0 }.a[1l] (?)

src/goto-programs/graphml_witness.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,15 @@ static bool filter_out(
144144
const goto_tracet::stepst::const_iterator &prev_it,
145145
goto_tracet::stepst::const_iterator &it)
146146
{
147+
// use the goto program's assignment type as declarations may be
148+
// recorded as (non-deterministic) assignments in the trace
147149
if(it->hidden &&
148150
(!it->pc->is_assign() ||
149151
to_code_assign(it->pc->code).rhs().id()!=ID_side_effect ||
150152
to_code_assign(it->pc->code).rhs().get(ID_statement)!=ID_nondet))
151153
return true;
152154

153-
if(!it->is_assignment() && !it->is_goto() && !it->is_assert())
155+
if(!it->pc->is_assign() && !it->is_goto() && !it->is_assert())
154156
return true;
155157

156158
// we filter out steps with the same source location

src/goto-symex/goto_symex.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include "goto_symex.h"
1313

1414
#include <util/simplify_expr.h>
15+
#include <util/zero_initializer.h>
1516

1617
unsigned goto_symext::nondet_count=0;
1718
unsigned goto_symext::dynamic_counter=0;
@@ -34,6 +35,17 @@ void goto_symext::replace_nondet(exprt &expr)
3435
if(expr.id()==ID_side_effect &&
3536
expr.get(ID_statement)==ID_nondet)
3637
{
38+
exprt nondet = nondet_initializer(
39+
expr.type(), expr.source_location(), ns, log.get_message_handler());
40+
41+
// recursively replace nondet fields in structs or arrays
42+
if(nondet.id() != ID_side_effect)
43+
{
44+
replace_nondet(nondet);
45+
expr.swap(nondet);
46+
return;
47+
}
48+
3749
nondet_symbol_exprt new_expr = build_symex_nondet(expr.type());
3850
new_expr.add_source_location()=expr.source_location();
3951
expr.swap(new_expr);

src/goto-symex/goto_symex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ class goto_symext
271271
irep_idt guard_identifier;
272272

273273
// symex
274+
irep_idt init_l1;
275+
274276
virtual void symex_transition(
275277
statet &,
276278
goto_programt::const_targett to,

src/goto-symex/symex_assign.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,20 @@ void goto_symext::symex_assign_symbol(
204204
// have an L2 entry set up beforehand either, so exempt them from
205205
// this check (all other L1 objects should have seen a declaration)
206206
const symbolt *s;
207-
if(!ns.lookup(lhs.get_object_name(), s) &&
208-
!s->is_parameter &&
209-
!lhs.get_level_1().empty() &&
210-
state.level2.current_count(lhs.get_identifier())==0)
207+
if(
208+
init_l1 != lhs.get_identifier() && !ns.lookup(lhs.get_object_name(), s) &&
209+
!s->is_parameter && !lhs.get_level_1().empty() &&
210+
state.level2.current_count(lhs.get_identifier()) == 0)
211+
{
211212
return;
213+
}
214+
else if(init_l1 == lhs.get_identifier())
215+
{
216+
// the assignment about to happen is the initialisation, clear the
217+
// identifier to make sure future steps are not treated as initialisation
218+
// steps (and we thus cannot reach the early return above
219+
init_l1.clear();
220+
}
212221

213222
exprt ssa_rhs=rhs;
214223

src/goto-symex/symex_builtin_functions.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,17 @@ void goto_symext::symex_allocate(
185185
}
186186
else
187187
{
188-
exprt nondet = build_symex_nondet(object_type);
189-
code_assignt assignment(value_symbol.symbol_expr(), nondet);
190-
symex_assign(state, assignment);
188+
side_effect_expr_nondett init(object_type);
189+
replace_nondet(init);
190+
191+
guardt guard;
192+
symex_assign_symbol(
193+
state,
194+
ssa_exprt(value_symbol.symbol_expr()),
195+
nil_exprt(),
196+
init,
197+
guard,
198+
symex_targett::assignment_typet::HIDDEN);
191199
}
192200

193201
exprt rhs;

src/goto-symex/symex_decl.cpp

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/rename.h>
1717
#include <util/std_expr.h>
1818

19-
#include <pointer-analysis/add_failed_symbols.h>
20-
2119
#include <analyses/dirty.h>
2220

2321
void goto_symext::symex_decl(statet &state)
@@ -51,37 +49,23 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
5149
state.rename(ssa.type(), l1_identifier, ns);
5250
ssa.update_type();
5351

54-
// in case of pointers, put something into the value set
55-
if(ns.follow(expr.type()).id()==ID_pointer)
56-
{
57-
exprt failed=
58-
get_failed_symbol(expr, ns);
59-
60-
exprt rhs;
61-
62-
if(failed.is_not_nil())
63-
rhs=address_of_exprt(failed, to_pointer_type(expr.type()));
64-
else
65-
rhs=exprt(ID_invalid);
66-
67-
state.rename(rhs, ns, goto_symex_statet::L1);
68-
state.value_set.assign(ssa, rhs, ns, true, false);
69-
}
70-
71-
// prevent propagation
72-
state.propagation.remove(l1_identifier);
73-
7452
// L2 renaming
7553
// inlining may yield multiple declarations of the same identifier
7654
// within the same L1 context
7755
if(state.level2.current_names.find(l1_identifier)==
7856
state.level2.current_names.end())
7957
state.level2.current_names[l1_identifier]=std::make_pair(ssa, 0);
80-
state.level2.increase_counter(l1_identifier);
81-
const bool record_events=state.record_events;
82-
state.record_events=false;
83-
state.rename(ssa, ns);
84-
state.record_events=record_events;
58+
init_l1 = l1_identifier;
59+
60+
// optimisation: skip non-deterministic initialisation if the next instruction
61+
// will take care of initialisation (but ensure int x=x; is handled properly)
62+
goto_programt::const_targett next = std::next(state.source.pc);
63+
if(
64+
next->is_assign() && to_code_assign(next->code).lhs() == expr &&
65+
to_code_assign(next->code).rhs().is_constant())
66+
{
67+
return;
68+
}
8569

8670
// we hide the declaration of auxiliary variables
8771
// and if the statement itself is hidden
@@ -90,10 +74,16 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
9074
state.top().hidden_function ||
9175
state.source.pc->source_location.get_hide();
9276

93-
target.decl(
94-
state.guard.as_expr(),
77+
side_effect_expr_nondett init(ssa.type());
78+
replace_nondet(init);
79+
80+
guardt guard;
81+
symex_assign_symbol(
82+
state,
9583
ssa,
96-
state.source,
84+
nil_exprt(),
85+
init,
86+
guard,
9787
hidden?
9888
symex_targett::assignment_typet::HIDDEN:
9989
symex_targett::assignment_typet::STATE);

0 commit comments

Comments
 (0)