Skip to content

Commit d069719

Browse files
authored
Merge pull request diffblue#1915 from karkhaz/kk-abstract-paths-worklist
Path exploration goodies
2 parents aac16d5 + 916eb1f commit d069719

22 files changed

+963
-93
lines changed

src/cbmc/bmc.cpp

+38-19
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ safety_checkert::resultt bmct::execute(
342342
const goto_functionst &goto_functions =
343343
goto_model.get_goto_functions();
344344

345+
if(symex.should_pause_symex)
346+
return safety_checkert::resultt::PAUSED;
347+
345348
// This provides the driver program the opportunity to do things like a
346349
// symbol-table or goto-functions dump instead of actually running the
347350
// checker, like show-vcc except driver-program specific.
@@ -595,17 +598,24 @@ void bmct::setup_unwind()
595598
/// \param callback_after_symex: optional callback to be run after symex.
596599
/// See class member `bmct::driver_callback_after_symex` for details.
597600
int bmct::do_language_agnostic_bmc(
601+
const path_strategy_choosert &path_strategy_chooser,
598602
const optionst &opts,
599603
abstract_goto_modelt &model,
600604
const ui_message_handlert::uit &ui,
601605
messaget &message,
602606
std::function<void(bmct &, const symbol_tablet &)> driver_configure_bmc,
603607
std::function<bool(void)> callback_after_symex)
604608
{
609+
safety_checkert::resultt final_result = safety_checkert::resultt::UNKNOWN;
610+
safety_checkert::resultt tmp_result = safety_checkert::resultt::UNKNOWN;
605611
const symbol_tablet &symbol_table = model.get_symbol_table();
606612
message_handlert &mh = message.get_message_handler();
607-
safety_checkert::resultt result;
608-
goto_symext::branch_worklistt worklist;
613+
std::unique_ptr<path_storaget> worklist;
614+
std::string strategy = opts.get_option("exploration-strategy");
615+
INVARIANT(
616+
path_strategy_chooser.is_valid_strategy(strategy),
617+
"Front-end passed us invalid path strategy '" + strategy + "'");
618+
worklist = path_strategy_chooser.get(strategy);
609619
try
610620
{
611621
{
@@ -614,21 +624,23 @@ int bmct::do_language_agnostic_bmc(
614624
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
615625
cbmc_solver = solvers.get_solver();
616626
prop_convt &pc = cbmc_solver->prop_conv();
617-
bmct bmc(opts, symbol_table, mh, pc, worklist, callback_after_symex);
627+
bmct bmc(opts, symbol_table, mh, pc, *worklist, callback_after_symex);
618628
bmc.set_ui(ui);
619629
if(driver_configure_bmc)
620630
driver_configure_bmc(bmc, symbol_table);
621-
result = bmc.run(model);
631+
tmp_result = bmc.run(model);
632+
if(tmp_result != safety_checkert::resultt::PAUSED)
633+
final_result = tmp_result;
622634
}
623635
INVARIANT(
624-
opts.get_bool_option("paths") || worklist.empty(),
636+
opts.get_bool_option("paths") || worklist->empty(),
625637
"the worklist should be empty after doing full-program "
626638
"model checking, but the worklist contains " +
627-
std::to_string(worklist.size()) + " unexplored branches.");
639+
std::to_string(worklist->size()) + " unexplored branches.");
628640

629641
// When model checking, the bmc.run() above will already have explored
630-
// the entire program, and result contains the verification result. The
631-
// worklist (containing paths that have not yet been explored) is thus
642+
// the entire program, and final_result contains the verification result.
643+
// The worklist (containing paths that have not yet been explored) is thus
632644
// empty, and we don't enter this loop.
633645
//
634646
// When doing path exploration, there will be some saved paths left to
@@ -641,31 +653,34 @@ int bmct::do_language_agnostic_bmc(
641653
// difference between the implementations of perform_symbolic_exection()
642654
// in bmct and path_explorert, for more information.
643655

644-
while(!worklist.empty())
656+
while(!worklist->empty())
645657
{
646-
message.status() << "___________________________\n"
647-
<< "Starting new path (" << worklist.size()
648-
<< " to go)\n"
649-
<< message.eom;
658+
if(tmp_result != safety_checkert::resultt::PAUSED)
659+
message.status() << "___________________________\n"
660+
<< "Starting new path (" << worklist->size()
661+
<< " to go)\n"
662+
<< message.eom;
650663
cbmc_solverst solvers(opts, symbol_table, message.get_message_handler());
651664
solvers.set_ui(ui);
652665
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
653666
cbmc_solver = solvers.get_solver();
654667
prop_convt &pc = cbmc_solver->prop_conv();
655-
goto_symext::branch_pointt &resume = worklist.front();
668+
path_storaget::patht &resume = worklist->peek();
656669
path_explorert pe(
657670
opts,
658671
symbol_table,
659672
mh,
660673
pc,
661674
resume.equation,
662675
resume.state,
663-
worklist,
676+
*worklist,
664677
callback_after_symex);
665678
if(driver_configure_bmc)
666679
driver_configure_bmc(pe, symbol_table);
667-
result &= pe.run(model);
668-
worklist.pop_front();
680+
tmp_result = pe.run(model);
681+
if(tmp_result != safety_checkert::resultt::PAUSED)
682+
final_result &= tmp_result;
683+
worklist->pop();
669684
}
670685
}
671686
catch(const char *error_msg)
@@ -684,14 +699,18 @@ int bmct::do_language_agnostic_bmc(
684699
throw std::current_exception();
685700
}
686701

687-
switch(result)
702+
switch(final_result)
688703
{
689704
case safety_checkert::resultt::SAFE:
690705
return CPROVER_EXIT_VERIFICATION_SAFE;
691706
case safety_checkert::resultt::UNSAFE:
692707
return CPROVER_EXIT_VERIFICATION_UNSAFE;
693708
case safety_checkert::resultt::ERROR:
694709
return CPROVER_EXIT_INTERNAL_ERROR;
710+
case safety_checkert::resultt::UNKNOWN:
711+
return CPROVER_EXIT_INTERNAL_ERROR;
712+
case safety_checkert::resultt::PAUSED:
713+
UNREACHABLE;
695714
}
696715
UNREACHABLE;
697716
}
@@ -701,7 +720,7 @@ void bmct::perform_symbolic_execution(
701720
{
702721
symex.symex_from_entry_point_of(get_goto_function, symex_symbol_table);
703722
INVARIANT(
704-
options.get_bool_option("paths") || branch_worklist.empty(),
723+
options.get_bool_option("paths") || path_storage.empty(),
705724
"Branch points were saved even though we should have been "
706725
"executing the entire program and merging paths");
707726
}

src/cbmc/bmc.h

+20-15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Author: Daniel Kroening, [email protected]
2323
#include <goto-programs/goto_trace.h>
2424

2525
#include <goto-symex/symex_target_equation.h>
26+
#include <goto-symex/path_storage.h>
27+
2628
#include <goto-programs/goto_model.h>
2729
#include <goto-programs/safety_checker.h>
2830
#include <goto-symex/memory_model.h>
@@ -49,32 +51,32 @@ class bmct:public safety_checkert
4951
/// constructor is `false` (unset), an instance of this class will
5052
/// symbolically execute the entire program, performing path merging
5153
/// to build a formula corresponding to all executions of the program
52-
/// up to the unwinding limit. In this case, the `branch_worklist`
54+
/// up to the unwinding limit. In this case, the `path_storage`
5355
/// member shall not be touched; this is enforced by the assertion in
5456
/// this class' implementation of bmct::perform_symbolic_execution().
5557
///
5658
/// - If the `--paths` flag is `true`, this `bmct` object will explore a
5759
/// single path through the codebase without doing any path merging.
5860
/// If some paths were not taken, the state at those branch points
59-
/// will be appended to `branch_worklist`. After the single path that
61+
/// will be appended to `path_storage`. After the single path that
6062
/// this `bmct` object executed has been model-checked, you can resume
6163
/// exploring further paths by popping an element from
62-
/// `branch_worklist` and using it to construct a path_explorert
64+
/// `path_storage` and using it to construct a path_explorert
6365
/// object.
6466
bmct(
6567
const optionst &_options,
6668
const symbol_tablet &outer_symbol_table,
6769
message_handlert &_message_handler,
6870
prop_convt &_prop_conv,
69-
goto_symext::branch_worklistt &_branch_worklist,
71+
path_storaget &_path_storage,
7072
std::function<bool(void)> callback_after_symex)
7173
: safety_checkert(ns, _message_handler),
7274
options(_options),
7375
outer_symbol_table(outer_symbol_table),
7476
ns(outer_symbol_table, symex_symbol_table),
7577
equation(),
76-
branch_worklist(_branch_worklist),
77-
symex(_message_handler, outer_symbol_table, equation, branch_worklist),
78+
path_storage(_path_storage),
79+
symex(_message_handler, outer_symbol_table, equation, path_storage),
7880
prop_conv(_prop_conv),
7981
ui(ui_message_handlert::uit::PLAIN),
8082
driver_callback_after_symex(callback_after_symex)
@@ -115,6 +117,7 @@ class bmct:public safety_checkert
115117
}
116118

117119
static int do_language_agnostic_bmc(
120+
const path_strategy_choosert &path_strategy_chooser,
118121
const optionst &opts,
119122
abstract_goto_modelt &goto_model,
120123
const ui_message_handlert::uit &ui,
@@ -128,7 +131,7 @@ class bmct:public safety_checkert
128131
///
129132
/// This constructor exists as a delegate for the path_explorert class.
130133
/// It differs from \ref bmct's public constructor in that it actually
131-
/// does something with the branch_worklistt argument, and also takes a
134+
/// does something with the path_storaget argument, and also takes a
132135
/// symex_target_equationt. See the documentation for path_explorert for
133136
/// details.
134137
bmct(
@@ -137,15 +140,15 @@ class bmct:public safety_checkert
137140
message_handlert &_message_handler,
138141
prop_convt &_prop_conv,
139142
symex_target_equationt &_equation,
140-
goto_symext::branch_worklistt &_branch_worklist,
143+
path_storaget &_path_storage,
141144
std::function<bool(void)> callback_after_symex)
142145
: safety_checkert(ns, _message_handler),
143146
options(_options),
144147
outer_symbol_table(outer_symbol_table),
145148
ns(outer_symbol_table),
146149
equation(_equation),
147-
branch_worklist(_branch_worklist),
148-
symex(_message_handler, outer_symbol_table, equation, branch_worklist),
150+
path_storage(_path_storage),
151+
symex(_message_handler, outer_symbol_table, equation, path_storage),
149152
prop_conv(_prop_conv),
150153
ui(ui_message_handlert::uit::PLAIN),
151154
driver_callback_after_symex(callback_after_symex)
@@ -166,7 +169,7 @@ class bmct:public safety_checkert
166169
symbol_tablet symex_symbol_table;
167170
namespacet ns;
168171
symex_target_equationt equation;
169-
goto_symext::branch_worklistt &branch_worklist;
172+
path_storaget &path_storage;
170173
symex_bmct symex;
171174
prop_convt &prop_conv;
172175
std::unique_ptr<memory_model_baset> memory_model;
@@ -257,15 +260,15 @@ class path_explorert : public bmct
257260
prop_convt &_prop_conv,
258261
symex_target_equationt &saved_equation,
259262
const goto_symex_statet &saved_state,
260-
goto_symext::branch_worklistt &branch_worklist,
263+
path_storaget &path_storage,
261264
std::function<bool(void)> callback_after_symex)
262265
: bmct(
263266
_options,
264267
outer_symbol_table,
265268
_message_handler,
266269
_prop_conv,
267270
saved_equation,
268-
branch_worklist,
271+
path_storage,
269272
callback_after_symex),
270273
saved_state(saved_state)
271274
{
@@ -292,15 +295,17 @@ class path_explorert : public bmct
292295
"(no-unwinding-assertions)" \
293296
"(no-pretty-names)" \
294297
"(partial-loops)" \
295-
"(paths)" \
298+
"(paths):" \
299+
"(show-symex-strategies)" \
296300
"(depth):" \
297301
"(unwind):" \
298302
"(unwindset):" \
299303
"(graphml-witness):" \
300304
"(unwindset):"
301305

302306
#define HELP_BMC \
303-
" --paths explore paths one at a time\n" \
307+
" --paths [strategy] explore paths one at a time\n" \
308+
" --show-symex-strategies list strategies for use with --paths\n" \
304309
" --program-only only show program expression\n" \
305310
" --show-loops show the loops in the program\n" \
306311
" --depth nr limit search depth\n" \

src/cbmc/cbmc_parse_options.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ cbmc_parse_optionst::cbmc_parse_optionst(int argc, const char **argv):
6868
parse_options_baset(CBMC_OPTIONS, argc, argv),
6969
xml_interfacet(cmdline),
7070
messaget(ui_message_handler),
71-
ui_message_handler(cmdline, "CBMC " CBMC_VERSION)
71+
ui_message_handler(cmdline, "CBMC " CBMC_VERSION),
72+
path_strategy_chooser()
7273
{
7374
}
7475

@@ -79,7 +80,8 @@ ::cbmc_parse_optionst::cbmc_parse_optionst(
7980
parse_options_baset(CBMC_OPTIONS+extra_options, argc, argv),
8081
xml_interfacet(cmdline),
8182
messaget(ui_message_handler),
82-
ui_message_handler(cmdline, "CBMC " CBMC_VERSION)
83+
ui_message_handler(cmdline, "CBMC " CBMC_VERSION),
84+
path_strategy_chooser()
8385
{
8486
}
8587

@@ -146,8 +148,13 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
146148
exit(CPROVER_EXIT_USAGE_ERROR);
147149
}
148150

149-
if(cmdline.isset("paths"))
150-
options.set_option("paths", true);
151+
if(cmdline.isset("show-symex-strategies"))
152+
{
153+
std::cout << path_strategy_chooser.show_strategies();
154+
exit(CPROVER_EXIT_SUCCESS);
155+
}
156+
157+
path_strategy_chooser.set_path_strategy_options(cmdline, options, *this);
151158

152159
if(cmdline.isset("program-only"))
153160
options.set_option("program-only", true);
@@ -531,7 +538,11 @@ int cbmc_parse_optionst::doit()
531538
return CPROVER_EXIT_SET_PROPERTIES_FAILED;
532539

533540
return bmct::do_language_agnostic_bmc(
534-
options, goto_model, ui_message_handler.get_ui(), *this);
541+
path_strategy_chooser,
542+
options,
543+
goto_model,
544+
ui_message_handler.get_ui(),
545+
*this);
535546
}
536547

537548
bool cbmc_parse_optionst::set_properties()

src/cbmc/cbmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class cbmc_parse_optionst:
110110
protected:
111111
goto_modelt goto_model;
112112
ui_message_handlert ui_message_handler;
113+
const path_strategy_choosert path_strategy_chooser;
113114

114115
void eval_verbosity();
115116
void register_languages();

src/cbmc/symex_bmc.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ symex_bmct::symex_bmct(
2222
message_handlert &mh,
2323
const symbol_tablet &outer_symbol_table,
2424
symex_target_equationt &_target,
25-
goto_symext::branch_worklistt &branch_worklist)
26-
: goto_symext(mh, outer_symbol_table, _target, branch_worklist),
25+
path_storaget &path_storage)
26+
: goto_symext(mh, outer_symbol_table, _target, path_storage),
2727
record_coverage(false),
2828
max_unwind(0),
2929
max_unwind_is_set(false),

src/cbmc/symex_bmc.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include <util/message.h>
1616
#include <util/threeval.h>
1717

18+
#include <goto-symex/path_storage.h>
1819
#include <goto-symex/goto_symex.h>
1920

2021
#include "symex_coverage.h"
@@ -26,7 +27,7 @@ class symex_bmct: public goto_symext
2627
message_handlert &mh,
2728
const symbol_tablet &outer_symbol_table,
2829
symex_target_equationt &_target,
29-
goto_symext::branch_worklistt &branch_worklist);
30+
path_storaget &path_storage);
3031

3132
// To show progress
3233
source_locationt last_source_location;

src/doxyfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
281281
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
282282
# the files are not read by doxygen.
283283

284-
EXTENSION_MAPPING =
284+
EXTENSION_MAPPING = h=c++
285285

286286
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
287287
# according to the Markdown format, which allows for more readable

src/goto-instrument/accelerate/scratch_program.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Matt Lewis
2323
#include <goto-programs/goto_functions.h>
2424

2525
#include <goto-symex/goto_symex.h>
26+
#include <goto-symex/path_storage.h>
2627
#include <goto-symex/symex_target_equation.h>
2728

2829
#include <solvers/smt2/smt2_dec.h>
@@ -41,8 +42,8 @@ class scratch_programt:public goto_programt
4142
symex_symbol_table(),
4243
ns(symbol_table, symex_symbol_table),
4344
equation(),
44-
branch_worklist(),
45-
symex(mh, symbol_table, equation, branch_worklist),
45+
path_storage(),
46+
symex(mh, symbol_table, equation, path_storage),
4647
satcheck(util_make_unique<satcheckt>()),
4748
satchecker(ns, *satcheck),
4849
z3(ns, "accelerate", "", "", smt2_dect::solvert::Z3),
@@ -78,7 +79,7 @@ class scratch_programt:public goto_programt
7879
symbol_tablet symex_symbol_table;
7980
namespacet ns;
8081
symex_target_equationt equation;
81-
goto_symext::branch_worklistt branch_worklist;
82+
path_fifot path_storage;
8283
goto_symext symex;
8384

8485
std::unique_ptr<propt> satcheck;

0 commit comments

Comments
 (0)