Skip to content

Commit 7a897a5

Browse files
committed
Bugfix: store VCC counters per-path
Prior to this commit, total_vccs and remaining_vccs had been members of goto_symext, meaning that they would be reset to zero every time a path was resumed. This would make CBMC incorrectly report safety for the included test program when running in path exploration mode, even though the program is reported as unsafe when CBMC runs in model-checking mode. This commit moves those members to goto_symex_statet, with goto_symext retaining cached versions so that its clients can read their values after the state has been torn down.
1 parent 5e84ac2 commit 7a897a5

File tree

7 files changed

+79
-24
lines changed

7 files changed

+79
-24
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main()
2+
{
3+
__CPROVER_assert(0, "");
4+
int x;
5+
while(x)
6+
--x;
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--paths lifo --unwind 1 --pointer-check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring

src/cbmc/bmc.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,9 @@ safety_checkert::resultt bmct::execute(
314314
}
315315

316316
// any properties to check at all?
317-
if(!options.get_bool_option("program-only") &&
318-
symex.remaining_vccs==0)
317+
if(
318+
!options.get_bool_option("program-only") &&
319+
symex.get_remaining_vccs() == 0)
319320
{
320321
report_success();
321322
output_graphml(resultt::SAFE);
@@ -392,9 +393,8 @@ void bmct::slice()
392393
}
393394
}
394395
}
395-
statistics() << "Generated "
396-
<< symex.total_vccs<<" VCC(s), "
397-
<< symex.remaining_vccs
396+
statistics() << "Generated " << symex.get_total_vccs() << " VCC(s), "
397+
<< symex.get_remaining_vccs()
398398
<< " remaining after simplification" << eom;
399399
}
400400

src/goto-symex/goto_symex.h

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ class goto_symext
6060
doing_path_exploration(options.is_set("paths")),
6161
allow_pointer_unsoundness(
6262
options.get_bool_option("allow-pointer-unsoundness")),
63-
total_vccs(0),
64-
remaining_vccs(0),
6563
constant_propagation(true),
6664
self_loops_to_assumptions(true),
6765
language_mode(),
@@ -71,7 +69,9 @@ class goto_symext
7169
atomic_section_counter(0),
7270
log(mh),
7371
guard_identifier("goto_symex::\\guard"),
74-
path_storage(path_storage)
72+
path_storage(path_storage),
73+
_total_vccs(std::numeric_limits<unsigned>::max()),
74+
_remaining_vccs(std::numeric_limits<unsigned>::max())
7575
{
7676
}
7777

@@ -209,9 +209,6 @@ class goto_symext
209209
// these bypass the target maps
210210
virtual void symex_step_goto(statet &, bool taken);
211211

212-
// statistics
213-
unsigned total_vccs, remaining_vccs;
214-
215212
bool constant_propagation;
216213
bool self_loops_to_assumptions;
217214

@@ -466,6 +463,36 @@ class goto_symext
466463
void rewrite_quantifiers(exprt &, statet &);
467464

468465
path_storaget &path_storage;
466+
467+
protected:
468+
/// @{\name Statistics
469+
///
470+
/// The actual number of total and remaining VCCs should be assigned to
471+
/// the relevant members of goto_symex_statet. The members below are used to
472+
/// cache the values from goto_symex_statet after symex has ended, so that
473+
/// \ref bmct can read those values even after the state has been deallocated.
474+
475+
unsigned _total_vccs, _remaining_vccs;
476+
///@}
477+
478+
public:
479+
unsigned get_total_vccs()
480+
{
481+
INVARIANT(
482+
_total_vccs != std::numeric_limits<unsigned>::max(),
483+
"symex_threaded_step should have been executed at least once before "
484+
"attempting to read total_vccs");
485+
return _total_vccs;
486+
}
487+
488+
unsigned get_remaining_vccs()
489+
{
490+
INVARIANT(
491+
_remaining_vccs != std::numeric_limits<unsigned>::max(),
492+
"symex_threaded_step should have been executed at least once before "
493+
"attempting to read remaining_vccs");
494+
return _remaining_vccs;
495+
}
469496
};
470497

471498
#endif // CPROVER_GOTO_SYMEX_GOTO_SYMEX_H

src/goto-symex/goto_symex_state.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ goto_symex_statet::goto_symex_statet()
2727
: depth(0),
2828
symex_target(nullptr),
2929
atomic_section_id(0),
30+
total_vccs(0),
31+
remaining_vccs(0),
3032
record_events(true),
3133
dirty()
3234
{

src/goto-symex/goto_symex_state.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,19 @@ class goto_symex_statet final
211211
propagationt propagation;
212212
unsigned atomic_section_id;
213213
std::unordered_map<irep_idt, local_safe_pointerst> safe_pointers;
214-
215-
explicit goto_statet(const goto_symex_statet &s):
216-
depth(s.depth),
217-
level2_current_names(s.level2.current_names),
218-
value_set(s.value_set),
219-
guard(s.guard),
220-
source(s.source),
221-
propagation(s.propagation),
222-
atomic_section_id(s.atomic_section_id),
223-
safe_pointers(s.safe_pointers)
214+
unsigned total_vccs, remaining_vccs;
215+
216+
explicit goto_statet(const goto_symex_statet &s)
217+
: depth(s.depth),
218+
level2_current_names(s.level2.current_names),
219+
value_set(s.value_set),
220+
guard(s.guard),
221+
source(s.source),
222+
propagation(s.propagation),
223+
atomic_section_id(s.atomic_section_id),
224+
safe_pointers(s.safe_pointers),
225+
total_vccs(s.total_vccs),
226+
remaining_vccs(s.remaining_vccs)
224227
{
225228
}
226229

@@ -250,7 +253,9 @@ class goto_symex_statet final
250253
propagation(s.propagation),
251254
safe_pointers(s.safe_pointers),
252255
value_set(s.value_set),
253-
atomic_section_id(s.atomic_section_id)
256+
atomic_section_id(s.atomic_section_id),
257+
total_vccs(s.total_vccs),
258+
remaining_vccs(s.remaining_vccs)
254259
{
255260
level2.current_names = s.level2_current_names;
256261
}
@@ -346,6 +351,8 @@ class goto_symex_statet final
346351
read_in_atomic_sectiont read_in_atomic_section;
347352
written_in_atomic_sectiont written_in_atomic_section;
348353

354+
unsigned total_vccs, remaining_vccs;
355+
349356
class threadt
350357
{
351358
public:

src/goto-symex/symex_main.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void goto_symext::vcc(
5151
const std::string &msg,
5252
statet &state)
5353
{
54-
total_vccs++;
54+
state.total_vccs++;
5555

5656
exprt expr=vcc_expr;
5757

@@ -69,7 +69,7 @@ void goto_symext::vcc(
6969

7070
state.guard.guard_expr(expr);
7171

72-
remaining_vccs++;
72+
state.remaining_vccs++;
7373
target.assertion(state.guard.as_expr(), expr, msg, state.source);
7474
}
7575

@@ -149,6 +149,10 @@ void goto_symext::symex_threaded_step(
149149
statet &state, const get_goto_functiont &get_goto_function)
150150
{
151151
symex_step(get_goto_function, state);
152+
153+
_total_vccs = state.total_vccs;
154+
_remaining_vccs = state.remaining_vccs;
155+
152156
if(should_pause_symex)
153157
return;
154158

0 commit comments

Comments
 (0)