forked from diffblue/cbmc
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[path explore 5/7] Support path-based exploratio2
This commit introduces the --paths flag to CBMC, which makes CBMC model-check each individual path of the program rather than merging paths and model-checking the entire program. The overall strategy involves allowing the "state" of symbolic execution---i.e., a pair of goto_symex_statet and symex_target_equationt ---to be saved during an execution, and for an execution to be resumed from a saved pair. By saving the state at every branch point and disabling path merging, symbolic execution only runs along one path but populates a worklist of saved states that should be executed later. At the top level, CBMC or JBMC loops while the worklist of saved states is non-empty, creating a new bmct object to resume executing each saved path. This commit includes the following supporting changes: - goto_symex_statet now owns a symbol table, separate from the one supporting the goto_program, which is used for dynamically created objects during symbolic execution. goto_symex was previously using a symbol table that was passed to it by reference for this purpose, but that symbol table is needed when resuming symbolic execution from a saved point and so ought properly to be part of the symbolic execution state. - goto_symex_statet now has a pointer to a symex_target_equationt, which can be updated with an equation from a previously-saved symbolic execution run. While equations are also conceptually part of the state of symbolic execution, they are heavily used after symbolic execution has completed (and the symex state has been deallocated) and so the equation is not owned by the state. An explicit copy constructor has been added to goto_symex_statet that initializes the equation member, so that symbolic execution can proceed either with an empty equation or with an equation that was earlier saved. - goto_symex_statet no longer has a pointer to a dirtyt, as this was hindering it from being copied.
- Loading branch information
Showing
24 changed files
with
615 additions
and
226 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ Author: Daniel Kroening, [email protected] | |
#include <langapi/mode.h> | ||
#include <langapi/language_util.h> | ||
|
||
#include <goto-programs/goto_model.h> | ||
#include <goto-programs/xml_goto_trace.h> | ||
#include <goto-programs/json_goto_trace.h> | ||
#include <goto-programs/graphml_witness.h> | ||
|
@@ -363,8 +364,7 @@ safety_checkert::resultt bmct::execute(const goto_functionst &goto_functions) | |
{ | ||
try | ||
{ | ||
// perform symbolic execution | ||
symex.symex_from_entry_point_of(goto_functions); | ||
perform_symbolic_execution(goto_functions); | ||
|
||
// add a partial ordering, if required | ||
if(equation.has_threads()) | ||
|
@@ -607,13 +607,69 @@ int bmct::do_language_agnostic_bmc( | |
messaget &message, | ||
std::function<void(bmct &, const goto_modelt &)> frontend_configure_bmc) | ||
{ | ||
cbmc_solverst solvers( | ||
opts, goto_model.symbol_table, message.get_message_handler()); | ||
solvers.set_ui(ui); | ||
std::unique_ptr<cbmc_solverst::solvert> solver; | ||
message_handlert &mh = message.get_message_handler(); | ||
safety_checkert::resultt result; | ||
goto_symext::branch_worklistt worklist; | ||
try | ||
{ | ||
solver = solvers.get_solver(); | ||
{ | ||
cbmc_solverst solvers( | ||
opts, goto_model.symbol_table, message.get_message_handler()); | ||
solvers.set_ui(ui); | ||
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver; | ||
cbmc_solver = solvers.get_solver(); | ||
prop_convt &pc = cbmc_solver->prop_conv(); | ||
bmct bmc(opts, goto_model.symbol_table, mh, pc, worklist); | ||
bmc.set_ui(ui); | ||
frontend_configure_bmc(bmc, goto_model); | ||
result = bmc.run(goto_model.goto_functions); | ||
} | ||
INVARIANT( | ||
opts.get_bool_option("paths") || worklist.empty(), | ||
"the worklist should be empty after doing full-program " | ||
"model checking, but the worklist contains " + | ||
std::to_string(worklist.size()) + " unexplored branches."); | ||
|
||
// When model checking, the bmc.run() above will already have explored | ||
// the entire program, and result contains the verification result. The | ||
// worklist (containing paths that have not yet been explored) is thus | ||
// empty, and we don't enter this loop. | ||
// | ||
// When doing path exploration, there will be some saved paths left to | ||
// explore in the worklist. We thus need to run the above code again, | ||
// once for each saved path in the worklist, to continue symbolically | ||
// execute the program. Note that the code in the loop is similar to | ||
// the code above except that we construct a path_explorert rather than | ||
// a bmct, which allows us to execute from a saved state rather than | ||
// from the entry point. See the path_explorert documentation, and the | ||
// difference between the implementations of perform_symbolic_exection() | ||
// in bmct and path_explorert, for more information. | ||
|
||
while(!worklist.empty()) | ||
{ | ||
message.status() << "___________________________\n" | ||
<< "Starting new path (" << worklist.size() | ||
<< " to go)\n" | ||
<< message.eom; | ||
cbmc_solverst solvers( | ||
opts, goto_model.symbol_table, message.get_message_handler()); | ||
solvers.set_ui(ui); | ||
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver; | ||
cbmc_solver = solvers.get_solver(); | ||
prop_convt &pc = cbmc_solver->prop_conv(); | ||
goto_symext::branch_pointt &resume = worklist.front(); | ||
path_explorert pe( | ||
opts, | ||
goto_model.symbol_table, | ||
mh, | ||
pc, | ||
resume.equation, | ||
resume.state, | ||
worklist); | ||
frontend_configure_bmc(pe, goto_model); | ||
result &= pe.run(goto_model.goto_functions); | ||
worklist.pop_front(); | ||
} | ||
} | ||
catch(const char *error_msg) | ||
{ | ||
|
@@ -631,35 +687,30 @@ int bmct::do_language_agnostic_bmc( | |
throw std::current_exception(); | ||
} | ||
|
||
bmct bmc( | ||
opts, | ||
goto_model.symbol_table, | ||
message.get_message_handler(), | ||
solver->prop_conv()); | ||
|
||
frontend_configure_bmc(bmc, goto_model); | ||
bmc.set_ui(ui); | ||
|
||
int result = CPROVER_EXIT_INTERNAL_ERROR; | ||
|
||
// do actual BMC | ||
switch(bmc.run(goto_model.goto_functions)) | ||
switch(result) | ||
{ | ||
case safety_checkert::resultt::SAFE: | ||
result = CPROVER_EXIT_VERIFICATION_SAFE; | ||
break; | ||
return CPROVER_EXIT_VERIFICATION_SAFE; | ||
case safety_checkert::resultt::UNSAFE: | ||
result = CPROVER_EXIT_VERIFICATION_UNSAFE; | ||
break; | ||
return CPROVER_EXIT_VERIFICATION_UNSAFE; | ||
case safety_checkert::resultt::ERROR: | ||
result = CPROVER_EXIT_INTERNAL_ERROR; | ||
break; | ||
return CPROVER_EXIT_INTERNAL_ERROR; | ||
} | ||
UNREACHABLE; | ||
} | ||
|
||
// let's log some more statistics | ||
message.debug() << "Memory consumption:" << messaget::endl; | ||
memory_info(message.debug()); | ||
message.debug() << eom; | ||
void bmct::perform_symbolic_execution(const goto_functionst &goto_functions) | ||
{ | ||
symex.symex_from_entry_point_of(goto_functions, symex_symbol_table); | ||
INVARIANT( | ||
options.get_bool_option("paths") || branch_worklist.empty(), | ||
"Branch points were saved even though we should have been " | ||
"executing the entire program and merging paths"); | ||
} | ||
|
||
return result; | ||
void path_explorert::perform_symbolic_execution( | ||
const goto_functionst &goto_functions) | ||
{ | ||
symex.resume_symex_from_saved_state( | ||
goto_functions, saved_state, &equation, symex_symbol_table); | ||
} |
Oops, something went wrong.