Skip to content

Commit 93e217b

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 6ce34dc commit 93e217b

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-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: 49 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
@@ -334,6 +373,11 @@ void _check_with_strategy(
334373
safety_checkert::resultt result = bmc.run(gm);
335374
symex_eventt::validate_result(events, result);
336375

376+
if(
377+
result == safety_checkert::resultt::UNSAFE &&
378+
opts.get_bool_option("stop-on-fail") && opts.is_set("paths"))
379+
worklist->clear();
380+
337381
while(!worklist->empty())
338382
{
339383
cbmc_solverst solvers(opts, gm.get_symbol_table(), mh);
@@ -357,6 +401,11 @@ void _check_with_strategy(
357401

358402
symex_eventt::validate_result(events, result);
359403
worklist->pop();
404+
405+
if(
406+
result == safety_checkert::resultt::UNSAFE &&
407+
opts.get_bool_option("stop-on-fail"))
408+
worklist->clear();
360409
}
361410
REQUIRE(events.empty());
362411
}

0 commit comments

Comments
 (0)