Skip to content

Commit c445f51

Browse files
committed
Explicitly initialise non-static objects with non-deterministic values
1 parent a3bb7b9 commit c445f51

File tree

7 files changed

+176
-54
lines changed

7 files changed

+176
-54
lines changed

regression/cbmc/graphml_witness1/test.desc

-6
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>

src/goto-programs/graphml_witness.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,15 @@ static bool filter_out(
173173
const goto_tracet::stepst::const_iterator &prev_it,
174174
goto_tracet::stepst::const_iterator &it)
175175
{
176+
// use the goto program's assignment type as declarations may be
177+
// recorded as (non-deterministic) assignments in the trace
176178
if(it->hidden &&
177-
(!it->is_assignment() ||
179+
(!it->pc->is_assign() ||
178180
to_code_assign(it->pc->code).rhs().id()!=ID_side_effect ||
179181
to_code_assign(it->pc->code).rhs().get(ID_statement)!=ID_nondet))
180182
return true;
181183

182-
if(!it->is_assignment() && !it->is_goto() && !it->is_assert())
184+
if(!it->pc->is_assign() && !it->is_goto() && !it->is_assert())
183185
return true;
184186

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

src/goto-symex/goto_symex.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9+
#include <util/message.h>
910
#include <util/simplify_expr.h>
1011

12+
#include <linking/zero_initializer.h>
13+
1114
#include "goto_symex.h"
1215

1316
unsigned goto_symext::nondet_count=0;
@@ -48,6 +51,21 @@ void goto_symext::replace_nondet(exprt &expr)
4851
if(expr.id()==ID_side_effect &&
4952
expr.get(ID_statement)==ID_nondet)
5053
{
54+
null_message_handlert null_message;
55+
exprt nondet=
56+
nondet_initializer(
57+
expr.type(),
58+
expr.source_location(),
59+
ns,
60+
null_message);
61+
62+
if(nondet.id()!=ID_side_effect)
63+
{
64+
replace_nondet(nondet);
65+
expr.swap(nondet);
66+
return;
67+
}
68+
5169
exprt new_expr(ID_nondet_symbol, expr.type());
5270
new_expr.set(ID_identifier, "symex::nondet"+std::to_string(nondet_count++));
5371
new_expr.add_source_location()=expr.source_location();

src/goto-symex/symex_builtin_functions.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ void goto_symext::symex_malloc(
173173

174174
new_symbol_table.add(value_symbol);
175175

176+
side_effect_expr_nondett init(object_type);
177+
replace_nondet(init);
178+
179+
guardt guard;
180+
symex_assign_symbol(
181+
state,
182+
ssa_exprt(value_symbol.symbol_expr()),
183+
nil_exprt(),
184+
init,
185+
guard,
186+
symex_targett::HIDDEN);
187+
176188
address_of_exprt rhs;
177189

178190
if(object_type.id()==ID_array)

src/goto-symex/symex_decl.cpp

+19-35
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/rename.h>
1212
#include <util/std_expr.h>
1313

14-
#include <pointer-analysis/add_failed_symbols.h>
15-
1614
#include <analyses/dirty.h>
1715

1816
#include "goto_symex.h"
@@ -72,42 +70,22 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
7270
state.rename(ssa.type(), l1_identifier, ns);
7371
ssa.update_type();
7472

75-
// in case of pointers, put something into the value set
76-
if(ns.follow(expr.type()).id()==ID_pointer)
77-
{
78-
exprt failed=
79-
get_failed_symbol(expr, ns);
80-
81-
exprt rhs;
82-
83-
if(failed.is_not_nil())
84-
{
85-
address_of_exprt address_of_expr;
86-
address_of_expr.object()=failed;
87-
address_of_expr.type()=expr.type();
88-
rhs=address_of_expr;
89-
}
90-
else
91-
rhs=exprt(ID_invalid);
92-
93-
state.rename(rhs, ns, goto_symex_statet::L1);
94-
state.value_set.assign(ssa, rhs, ns, true, false);
95-
}
96-
97-
// prevent propagation
98-
state.propagation.remove(l1_identifier);
99-
10073
// L2 renaming
10174
// inlining may yield multiple declarations of the same identifier
10275
// within the same L1 context
10376
if(state.level2.current_names.find(l1_identifier)==
10477
state.level2.current_names.end())
10578
state.level2.current_names[l1_identifier]=std::make_pair(ssa, 0);
106-
state.level2.increase_counter(l1_identifier);
107-
const bool record_events=state.record_events;
108-
state.record_events=false;
109-
state.rename(ssa, ns);
110-
state.record_events=record_events;
79+
80+
// skip non-deterministic initialisation if the next instruction
81+
// will take care of initialisation (but ensure int x=x; is handled
82+
// properly)
83+
goto_programt::const_targett next=state.source.pc;
84+
++next;
85+
if(next->is_assign() &&
86+
to_code_assign(next->code).lhs()==expr &&
87+
to_code_assign(next->code).rhs().is_constant())
88+
return;
11189

11290
// we hide the declaration of auxiliary variables
11391
// and if the statement itself is hidden
@@ -116,10 +94,16 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
11694
state.top().hidden_function ||
11795
state.source.pc->source_location.get_hide();
11896

119-
target.decl(
120-
state.guard.as_expr(),
97+
side_effect_expr_nondett init(ssa.type());
98+
replace_nondet(init);
99+
100+
guardt guard;
101+
symex_assign_symbol(
102+
state,
121103
ssa,
122-
state.source,
104+
nil_exprt(),
105+
init,
106+
guard,
123107
hidden?symex_targett::HIDDEN:symex_targett::STATE);
124108

125109
assert(state.dirty);

src/linking/zero_initializer.cpp

+112-11
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ Author: Daniel Kroening, [email protected]
1313
#include <util/arith_tools.h>
1414
#include <util/std_types.h>
1515
#include <util/std_expr.h>
16+
#include <util/std_code.h>
1617
#include <util/pointer_offset_size.h>
1718

1819
#include <ansi-c/c_types.h>
1920
#include <ansi-c/expr2c.h>
2021

2122
#include "zero_initializer.h"
2223

24+
template<bool nondet>
2325
class zero_initializert:public messaget
2426
{
2527
public:
@@ -68,7 +70,8 @@ Function: zero_initializert::zero_initializer_rec
6870
6971
\*******************************************************************/
7072

71-
exprt zero_initializert::zero_initializer_rec(
73+
template<bool nondet>
74+
exprt zero_initializert<nondet>::zero_initializer_rec(
7275
const typet &type,
7376
const source_locationt &source_location)
7477
{
@@ -85,31 +88,55 @@ exprt zero_initializert::zero_initializer_rec(
8588
type_id==ID_floatbv ||
8689
type_id==ID_fixedbv)
8790
{
88-
exprt result=from_integer(0, type);
91+
exprt result;
92+
if(nondet)
93+
result=side_effect_expr_nondett(type);
94+
else
95+
result=from_integer(0, type);
96+
8997
result.add_source_location()=source_location;
9098
return result;
9199
}
92100
else if(type_id==ID_rational ||
93101
type_id==ID_real)
94102
{
95-
constant_exprt result(ID_0, type);
103+
exprt result;
104+
if(nondet)
105+
result=side_effect_expr_nondett(type);
106+
else
107+
result=constant_exprt(ID_0, type);
108+
96109
result.add_source_location()=source_location;
97110
return result;
98111
}
99112
else if(type_id==ID_verilog_signedbv ||
100113
type_id==ID_verilog_unsignedbv)
101114
{
102-
std::size_t width=to_bitvector_type(type).get_width();
103-
std::string value(width, '0');
115+
exprt result;
116+
if(nondet)
117+
result=side_effect_expr_nondett(type);
118+
else
119+
{
120+
std::size_t width=to_bitvector_type(type).get_width();
121+
std::string value(width, '0');
122+
123+
result=constant_exprt(value, type);
124+
}
104125

105-
constant_exprt result(value, type);
106126
result.add_source_location()=source_location;
107127
return result;
108128
}
109129
else if(type_id==ID_complex)
110130
{
111-
exprt sub_zero=zero_initializer_rec(type.subtype(), source_location);
112-
complex_exprt result(sub_zero, sub_zero, to_complex_type(type));
131+
exprt result;
132+
if(nondet)
133+
result=side_effect_expr_nondett(type);
134+
else
135+
{
136+
exprt sub_zero=zero_initializer_rec(type.subtype(), source_location);
137+
result=complex_exprt(sub_zero, sub_zero, to_complex_type(type));
138+
}
139+
113140
result.add_source_location()=source_location;
114141
return result;
115142
}
@@ -148,6 +175,13 @@ exprt zero_initializert::zero_initializer_rec(
148175
}
149176
else if(to_integer(array_type.size(), array_size))
150177
{
178+
if(nondet)
179+
{
180+
exprt result=side_effect_expr_nondett(type);
181+
result.add_source_location()=source_location;
182+
return result;
183+
}
184+
151185
error().source_location=source_location;
152186
error() << "failed to zero-initialize array of non-fixed size `"
153187
<< to_string(array_type.size()) << "'" << eom;
@@ -178,6 +212,13 @@ exprt zero_initializert::zero_initializer_rec(
178212

179213
if(to_integer(vector_type.size(), vector_size))
180214
{
215+
if(nondet)
216+
{
217+
exprt result=side_effect_expr_nondett(type);
218+
result.add_source_location()=source_location;
219+
return result;
220+
}
221+
181222
error().source_location=source_location;
182223
error() << "failed to zero-initialize vector of non-fixed size `"
183224
<< to_string(vector_type.size()) << "'" << eom;
@@ -308,7 +349,14 @@ exprt zero_initializert::zero_initializer_rec(
308349
}
309350
else if(type_id==ID_string)
310351
{
311-
return constant_exprt(irep_idt(), type);
352+
exprt result;
353+
if(nondet)
354+
result=side_effect_expr_nondett(type);
355+
else
356+
result=constant_exprt(irep_idt(), type);
357+
358+
result.add_source_location()=source_location;
359+
return result;
312360
}
313361
else
314362
{
@@ -337,7 +385,29 @@ exprt zero_initializer(
337385
const namespacet &ns,
338386
message_handlert &message_handler)
339387
{
340-
zero_initializert z_i(ns, message_handler);
388+
zero_initializert<false> z_i(ns, message_handler);
389+
return z_i(type, source_location);
390+
}
391+
392+
/*******************************************************************\
393+
394+
Function: nondet_initializer
395+
396+
Inputs:
397+
398+
Outputs:
399+
400+
Purpose:
401+
402+
\*******************************************************************/
403+
404+
exprt nondet_initializer(
405+
const typet &type,
406+
const source_locationt &source_location,
407+
const namespacet &ns,
408+
message_handlert &message_handler)
409+
{
410+
zero_initializert<true> z_i(ns, message_handler);
341411
return z_i(type, source_location);
342412
}
343413

@@ -363,7 +433,38 @@ exprt zero_initializer(
363433

364434
try
365435
{
366-
zero_initializert z_i(ns, mh);
436+
zero_initializert<false> z_i(ns, mh);
437+
return z_i(type, source_location);
438+
}
439+
catch(int)
440+
{
441+
throw oss.str();
442+
}
443+
}
444+
445+
/*******************************************************************\
446+
447+
Function: nondet_initializer
448+
449+
Inputs:
450+
451+
Outputs:
452+
453+
Purpose:
454+
455+
\*******************************************************************/
456+
457+
exprt nondet_initializer(
458+
const typet &type,
459+
const source_locationt &source_location,
460+
const namespacet &ns)
461+
{
462+
std::ostringstream oss;
463+
stream_message_handlert mh(oss);
464+
465+
try
466+
{
467+
zero_initializert<true> z_i(ns, mh);
367468
return z_i(type, source_location);
368469
}
369470
catch(int)

src/linking/zero_initializer.h

+11
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,21 @@ exprt zero_initializer(
2121
const namespacet &,
2222
message_handlert &);
2323

24+
exprt nondet_initializer(
25+
const typet &,
26+
const source_locationt &,
27+
const namespacet &,
28+
message_handlert &);
29+
2430
// throws a char* in case of failure
2531
exprt zero_initializer(
2632
const typet &,
2733
const source_locationt &,
2834
const namespacet &);
2935

36+
exprt nondet_initializer(
37+
const typet &type,
38+
const source_locationt &source_location,
39+
const namespacet &ns);
40+
3041
#endif // CPROVER_LINKING_ZERO_INITIALIZER_H

0 commit comments

Comments
 (0)