Skip to content

Commit 424ab4f

Browse files
committed
--stop-on-fail now stops on failed path
When doing path exploration, one sometimes wants CBMC to halt symbolic execution as soon as it encounters a single bug, rather than continuing to explore the program for all bugs. This behaviour can now be enabled by passing the --stop-on-fail flag together with the --paths flag. Prior to this commit, the --stop-on-fail flag --- which was written with model-checking rather than path exploration in mind --- would explore all paths, but only print out a single failed property, which isn't terribly useful because it uses just as much time as printing out all properties. This commit makes this flag more useful when used in conjunction with --paths, while not changing its behaviour for model checking.
1 parent 545bff8 commit 424ab4f

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

src/cbmc/bmc.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,15 @@ int bmct::do_language_agnostic_bmc(
588588
if(driver_configure_bmc)
589589
driver_configure_bmc(bmc, symbol_table);
590590
tmp_result = bmc.run(model);
591+
592+
if(
593+
tmp_result == safety_checkert::resultt::UNSAFE &&
594+
opts.get_bool_option("stop-on-fail") && opts.is_set("paths"))
595+
{
596+
worklist->clear();
597+
return CPROVER_EXIT_VERIFICATION_UNSAFE;
598+
}
599+
591600
if(tmp_result != safety_checkert::resultt::PAUSED)
592601
final_result = tmp_result;
593602
}
@@ -637,6 +646,15 @@ int bmct::do_language_agnostic_bmc(
637646
if(driver_configure_bmc)
638647
driver_configure_bmc(pe, symbol_table);
639648
tmp_result = pe.run(model);
649+
650+
if(
651+
tmp_result == safety_checkert::resultt::UNSAFE &&
652+
opts.get_bool_option("stop-on-fail") && opts.is_set("paths"))
653+
{
654+
worklist->clear();
655+
return CPROVER_EXIT_VERIFICATION_UNSAFE;
656+
}
657+
640658
if(tmp_result != safety_checkert::resultt::PAUSED)
641659
final_result &= tmp_result;
642660
worklist->pop();

unit/path_strategies.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,45 @@ SCENARIO("path strategies")
224224
symex_eventt::result(symex_eventt::enumt::FAILURE),
225225
});
226226
}
227+
228+
GIVEN("program to check for stop-on-fail with path exploration")
229+
{
230+
std::function<void(optionst &)> halt_callback = [](optionst &opts) {
231+
opts.set_option("stop-on-fail", true);
232+
};
233+
std::function<void(optionst &)> no_halt_callback = [](optionst &opts) {};
234+
235+
c =
236+
"/* 1 */ int main() \n"
237+
"/* 2 */ { \n"
238+
"/* 3 */ int x, y; \n"
239+
"/* 4 */ if(x) \n"
240+
"/* 5 */ assert(0); \n"
241+
"/* 6 */ else \n"
242+
"/* 7 */ assert(0); \n"
243+
"/* 8 */ } \n";
244+
245+
GIVEN("no stopping on failure")
246+
{
247+
check_with_strategy(
248+
"lifo",
249+
no_halt_callback,
250+
c,
251+
{symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
252+
symex_eventt::result(symex_eventt::enumt::FAILURE),
253+
symex_eventt::resume(symex_eventt::enumt::NEXT, 5),
254+
symex_eventt::result(symex_eventt::enumt::FAILURE)});
255+
}
256+
GIVEN("stopping on failure")
257+
{
258+
check_with_strategy(
259+
"lifo",
260+
halt_callback,
261+
c,
262+
{symex_eventt::resume(symex_eventt::enumt::JUMP, 7),
263+
symex_eventt::result(symex_eventt::enumt::FAILURE)});
264+
}
265+
}
227266
}
228267

229268
// In theory, there should be no need to change the code below when adding new
@@ -335,6 +374,13 @@ void _check_with_strategy(
335374
safety_checkert::resultt result = bmc.run(gm);
336375
symex_eventt::validate_result(events, result);
337376

377+
if(
378+
result == safety_checkert::resultt::UNSAFE &&
379+
opts.get_bool_option("stop-on-fail") && opts.is_set("paths"))
380+
{
381+
worklist->clear();
382+
}
383+
338384
while(!worklist->empty())
339385
{
340386
cbmc_solverst solvers(opts, gm.get_symbol_table(), mh);
@@ -358,6 +404,13 @@ void _check_with_strategy(
358404

359405
symex_eventt::validate_result(events, result);
360406
worklist->pop();
407+
408+
if(
409+
result == safety_checkert::resultt::UNSAFE &&
410+
opts.get_bool_option("stop-on-fail"))
411+
{
412+
worklist->clear();
413+
}
361414
}
362415
REQUIRE(events.empty());
363416
}

0 commit comments

Comments
 (0)