Skip to content

Commit 3ab8371

Browse files
authored
Merge pull request #3237 from karkhaz/kk-thrifty-model-checking
Only safety-check paths when new VCCs get added
2 parents 641a557 + 5099467 commit 3ab8371

File tree

7 files changed

+112
-57
lines changed

7 files changed

+112
-57
lines changed

src/cbmc/bmc.cpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,14 @@ bmct::run_decision_procedure(prop_convt &prop_conv)
153153

154154
void bmct::report_success()
155155
{
156-
result() << bold << "VERIFICATION SUCCESSFUL" << reset << eom;
156+
report_success(*this, ui_message_handler);
157+
}
157158

158-
switch(ui_message_handler.get_ui())
159+
void bmct::report_success(messaget &log, ui_message_handlert &handler)
160+
{
161+
log.result() << log.bold << "VERIFICATION SUCCESSFUL" << log.reset << log.eom;
162+
163+
switch(handler.get_ui())
159164
{
160165
case ui_message_handlert::uit::PLAIN:
161166
break;
@@ -164,25 +169,30 @@ void bmct::report_success()
164169
{
165170
xmlt xml("cprover-status");
166171
xml.data="SUCCESS";
167-
result() << xml;
172+
log.result() << xml;
168173
}
169174
break;
170175

171176
case ui_message_handlert::uit::JSON_UI:
172177
{
173178
json_objectt json_result;
174179
json_result["cProverStatus"]=json_stringt("success");
175-
result() << json_result;
180+
log.result() << json_result;
176181
}
177182
break;
178183
}
179184
}
180185

181186
void bmct::report_failure()
182187
{
183-
result() << bold << "VERIFICATION FAILED" << reset << eom;
188+
report_failure(*this, ui_message_handler);
189+
}
184190

185-
switch(ui_message_handler.get_ui())
191+
void bmct::report_failure(messaget &log, ui_message_handlert &handler)
192+
{
193+
log.result() << log.bold << "VERIFICATION FAILED" << log.reset << log.eom;
194+
195+
switch(handler.get_ui())
186196
{
187197
case ui_message_handlert::uit::PLAIN:
188198
break;
@@ -191,15 +201,15 @@ void bmct::report_failure()
191201
{
192202
xmlt xml("cprover-status");
193203
xml.data="FAILURE";
194-
result() << xml;
204+
log.result() << xml;
195205
}
196206
break;
197207

198208
case ui_message_handlert::uit::JSON_UI:
199209
{
200210
json_objectt json_result;
201211
json_result["cProverStatus"]=json_stringt("failure");
202-
result() << json_result;
212+
log.result() << json_result;
203213
}
204214
break;
205215
}
@@ -260,9 +270,6 @@ safety_checkert::resultt bmct::execute(
260270
const goto_functionst &goto_functions =
261271
goto_model.get_goto_functions();
262272

263-
if(symex.should_pause_symex)
264-
return safety_checkert::resultt::PAUSED;
265-
266273
// This provides the driver program the opportunity to do things like a
267274
// symbol-table or goto-functions dump instead of actually running the
268275
// checker, like show-vcc except driver-program specific.
@@ -272,9 +279,14 @@ safety_checkert::resultt bmct::execute(
272279
if(driver_callback_after_symex && driver_callback_after_symex())
273280
return safety_checkert::resultt::SAFE; // to indicate non-error
274281

275-
// add a partial ordering, if required
276282
if(equation.has_threads())
277283
{
284+
// When doing path exploration in a concurrent setting, we should avoid
285+
// model-checking the program until we reach the end of a path.
286+
if(symex.should_pause_symex)
287+
return safety_checkert::resultt::PAUSED;
288+
289+
// add a partial ordering, if required
278290
memory_model->set_message_handler(get_message_handler());
279291
(*memory_model)(equation);
280292
}
@@ -318,6 +330,8 @@ safety_checkert::resultt bmct::execute(
318330
!options.get_bool_option("program-only") &&
319331
symex.get_remaining_vccs() == 0)
320332
{
333+
if(options.is_set("paths"))
334+
return safety_checkert::resultt::PAUSED;
321335
report_success();
322336
output_graphml(resultt::SAFE);
323337
return safety_checkert::resultt::SAFE;
@@ -329,7 +343,10 @@ safety_checkert::resultt bmct::execute(
329343
return safety_checkert::resultt::SAFE;
330344
}
331345

332-
return decide(goto_functions, prop_conv);
346+
if(!options.is_set("paths") || symex.path_segment_vccs > 0)
347+
return decide(goto_functions, prop_conv);
348+
349+
return safety_checkert::resultt::PAUSED;
333350
}
334351

335352
catch(const std::string &error_str)
@@ -396,6 +413,10 @@ void bmct::slice()
396413
statistics() << "Generated " << symex.get_total_vccs() << " VCC(s), "
397414
<< symex.get_remaining_vccs()
398415
<< " remaining after simplification" << eom;
416+
417+
if(options.is_set("paths"))
418+
statistics() << "Generated " << symex.path_segment_vccs
419+
<< " new VCC(s) along current path segment" << eom;
399420
}
400421

401422
safety_checkert::resultt bmct::run(
@@ -484,8 +505,8 @@ int bmct::do_language_agnostic_bmc(
484505
std::function<void(bmct &, const symbol_tablet &)> driver_configure_bmc,
485506
std::function<bool(void)> callback_after_symex)
486507
{
487-
safety_checkert::resultt final_result = safety_checkert::resultt::UNKNOWN;
488-
safety_checkert::resultt tmp_result = safety_checkert::resultt::UNKNOWN;
508+
safety_checkert::resultt final_result = safety_checkert::resultt::SAFE;
509+
safety_checkert::resultt tmp_result = safety_checkert::resultt::SAFE;
489510
const symbol_tablet &symbol_table = model.get_symbol_table();
490511
messaget message(ui);
491512
std::unique_ptr<path_storaget> worklist;
@@ -544,11 +565,6 @@ int bmct::do_language_agnostic_bmc(
544565

545566
while(!worklist->empty())
546567
{
547-
if(tmp_result != safety_checkert::resultt::PAUSED)
548-
message.status() << "___________________________\n"
549-
<< "Starting new path (" << worklist->size()
550-
<< " to go)\n"
551-
<< message.eom;
552568
cbmc_solverst solvers(
553569
opts,
554570
symbol_table,
@@ -603,13 +619,15 @@ int bmct::do_language_agnostic_bmc(
603619
switch(final_result)
604620
{
605621
case safety_checkert::resultt::SAFE:
622+
if(opts.is_set("paths"))
623+
report_success(message, ui);
606624
return CPROVER_EXIT_VERIFICATION_SAFE;
607625
case safety_checkert::resultt::UNSAFE:
626+
if(opts.is_set("paths"))
627+
report_failure(message, ui);
608628
return CPROVER_EXIT_VERIFICATION_UNSAFE;
609629
case safety_checkert::resultt::ERROR:
610630
return CPROVER_EXIT_INTERNAL_ERROR;
611-
case safety_checkert::resultt::UNKNOWN:
612-
return CPROVER_EXIT_INTERNAL_ERROR;
613631
case safety_checkert::resultt::PAUSED:
614632
UNREACHABLE;
615633
}

src/cbmc/bmc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ class bmct:public safety_checkert
208208
virtual void report_success();
209209
virtual void report_failure();
210210

211+
static void report_success(messaget &, ui_message_handlert &);
212+
static void report_failure(messaget &, ui_message_handlert &);
213+
211214
virtual void error_trace();
212215
void output_graphml(resultt result);
213216

src/goto-programs/safety_checker.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ class safety_checkert:public messaget
4242
/// doing path exploration; the symex state has been saved, and symex should
4343
/// be resumed by the caller.
4444
PAUSED,
45-
/// We haven't yet assigned a safety check result to this object. A value of
46-
/// UNKNOWN can be used to initialize a resultt object, and that object may
47-
/// then safely be used with the |= and &= operators.
48-
UNKNOWN
4945
};
5046

5147
// check whether all assertions in goto_functions are safe
@@ -76,9 +72,6 @@ operator&=(safety_checkert::resultt &a, safety_checkert::resultt const &b)
7672
b != safety_checkert::resultt::PAUSED);
7773
switch(a)
7874
{
79-
case safety_checkert::resultt::UNKNOWN:
80-
a = b;
81-
return a;
8275
case safety_checkert::resultt::ERROR:
8376
return a;
8477
case safety_checkert::resultt::SAFE:
@@ -107,9 +100,6 @@ operator|=(safety_checkert::resultt &a, safety_checkert::resultt const &b)
107100
b != safety_checkert::resultt::PAUSED);
108101
switch(a)
109102
{
110-
case safety_checkert::resultt::UNKNOWN:
111-
a = b;
112-
return a;
113103
case safety_checkert::resultt::SAFE:
114104
return a;
115105
case safety_checkert::resultt::ERROR:

src/goto-symex/goto_symex.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class goto_symext
7070
log(mh),
7171
guard_identifier("goto_symex::\\guard"),
7272
path_storage(path_storage),
73+
path_segment_vccs(0),
7374
_total_vccs(std::numeric_limits<unsigned>::max()),
7475
_remaining_vccs(std::numeric_limits<unsigned>::max())
7576
{
@@ -464,6 +465,18 @@ class goto_symext
464465

465466
path_storaget &path_storage;
466467

468+
public:
469+
/// \brief Number of VCCs generated during the run of this goto_symext object
470+
///
471+
/// This member is always initialized to `0` upon construction of this object.
472+
/// It therefore differs from goto_symex_statet::total_vccs, which persists
473+
/// across the creation of several goto_symext objects. When CBMC is run in
474+
/// path-exploration mode, the meaning of this member is "the number of VCCs
475+
/// generated between the last branch point and the current instruction,"
476+
/// while goto_symex_statet::total_vccs records the total number of VCCs
477+
/// generated along the entire path from the beginning of the program.
478+
std::size_t path_segment_vccs;
479+
467480
protected:
468481
/// @{\name Statistics
469482
///

src/goto-symex/symex_main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ void goto_symext::vcc(
5252
statet &state)
5353
{
5454
state.total_vccs++;
55+
path_segment_vccs++;
5556

5657
exprt expr=vcc_expr;
5758

0 commit comments

Comments
 (0)