From c53d630fed233c568e3a6476d5a11018eadaea26 Mon Sep 17 00:00:00 2001 From: Kareem Khazem Date: Mon, 6 Nov 2017 10:48:07 -0500 Subject: [PATCH 1/6] [path explore 2/7] Ignore jbmc binary --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea8be88725b..9693fb2faef 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,7 @@ src/goto-cc/goto-cc.exe src/goto-cc/goto-cl.exe src/goto-instrument/goto-instrument src/goto-instrument/goto-instrument.exe +src/jbmc/jbmc src/musketeer/musketeer src/musketeer/musketeer.exe src/symex/symex From d7a70e1baf07fdb0410f21e40416040d5c1db1a6 Mon Sep 17 00:00:00 2001 From: Kareem Khazem Date: Thu, 15 Feb 2018 08:46:00 +0000 Subject: [PATCH 2/6] [path explore 3/7] Logical ops for resultt The operators &= and |= can now be used between two safety_checkert::resultt objects. They return the "best" or "worst" of two results, and additionally assign that result to the LHS. The assignment operators are useful when repeatedly performing a safety check and wanting to return a single error code that either describes the best or worst outcome of all the safety checks combined. --- src/goto-programs/safety_checker.h | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/goto-programs/safety_checker.h b/src/goto-programs/safety_checker.h index bb1492d6f53..599669f4cce 100644 --- a/src/goto-programs/safety_checker.h +++ b/src/goto-programs/safety_checker.h @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com // this is just an interface -- it won't actually do any checking! +#include #include #include "goto_trace.h" @@ -45,4 +46,39 @@ class safety_checkert:public messaget const namespacet &ns; }; +/// \brief The worst of two results +inline safety_checkert::resultt & +operator&=(safety_checkert::resultt &a, safety_checkert::resultt const &b) +{ + switch(a) + { + case safety_checkert::resultt::ERROR: + return a; + case safety_checkert::resultt::SAFE: + a = b; + return a; + case safety_checkert::resultt::UNSAFE: + a = b == safety_checkert::resultt::ERROR ? b : a; + return a; + } + UNREACHABLE; +} + +/// \brief The best of two results +inline safety_checkert::resultt & +operator|=(safety_checkert::resultt &a, safety_checkert::resultt const &b) +{ + switch(a) + { + case safety_checkert::resultt::SAFE: + return a; + case safety_checkert::resultt::ERROR: + a = b; + return a; + case safety_checkert::resultt::UNSAFE: + a = b == safety_checkert::resultt::SAFE ? b : a; + return a; + } + UNREACHABLE; +} #endif // CPROVER_GOTO_PROGRAMS_SAFETY_CHECKER_H From c88a3ab5a0aa38328f45c9c1174e63b723518c59 Mon Sep 17 00:00:00 2001 From: Kareem Khazem Date: Wed, 29 Nov 2017 13:48:49 -0500 Subject: [PATCH 3/6] [path explore 4/7] Factor out common BMC code The CBMC and JBMC frontends included identical code for running BMC after the language-specific preprocessing. This commit moves that common code into a static method of bmct. Parse options and help text related to bounded model checking are defined in bmc.h. --- src/cbmc/bmc.cpp | 68 +++++++++++++++++++ src/cbmc/bmc.h | 50 ++++++++++++++ src/cbmc/cbmc_parse_options.cpp | 81 ++--------------------- src/cbmc/cbmc_parse_options.h | 13 ++-- src/jbmc/jbmc_parse_options.cpp | 114 +++++++------------------------- src/jbmc/jbmc_parse_options.h | 13 ++-- 6 files changed, 161 insertions(+), 178 deletions(-) diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index 9bc86d3eec6..4e5a1c9bba2 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -12,13 +12,16 @@ Author: Daniel Kroening, kroening@kroening.com #include "bmc.h" #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -37,6 +40,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include "cbmc_solvers.h" #include "counterexample_beautification.h" #include "fault_localization.h" @@ -595,3 +599,67 @@ void bmct::setup_unwind() if(options.get_option("unwind")!="") symex.set_unwind_limit(options.get_unsigned_int_option("unwind")); } + +int bmct::do_language_agnostic_bmc( + const optionst &opts, + const goto_modelt &goto_model, + const ui_message_handlert::uit &ui, + messaget &message, + std::function frontend_configure_bmc) +{ + cbmc_solverst solvers( + opts, goto_model.symbol_table, message.get_message_handler()); + solvers.set_ui(ui); + std::unique_ptr solver; + try + { + solver = solvers.get_solver(); + } + catch(const char *error_msg) + { + message.error() << error_msg << message.eom; + return CPROVER_EXIT_EXCEPTION; + } + catch(const std::string &error_msg) + { + message.error() << error_msg << message.eom; + return CPROVER_EXIT_EXCEPTION; + } + catch(...) + { + message.error() << "unable to get solver" << message.eom; + 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)) + { + case safety_checkert::resultt::SAFE: + result = CPROVER_EXIT_VERIFICATION_SAFE; + break; + case safety_checkert::resultt::UNSAFE: + result = CPROVER_EXIT_VERIFICATION_UNSAFE; + break; + case safety_checkert::resultt::ERROR: + result = CPROVER_EXIT_INTERNAL_ERROR; + break; + } + + // let's log some more statistics + message.debug() << "Memory consumption:" << messaget::endl; + memory_info(message.debug()); + message.debug() << eom; + + return result; +} diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index b3f9a7846e1..d46ae0812cc 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -28,6 +28,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include @@ -82,6 +83,25 @@ class bmct:public safety_checkert symex.add_recursion_unwind_handler(handler); } + /// \brief common BMC code, invoked from language-specific frontends + /// + /// Do bounded model-checking after all language-specific program + /// preprocessing has been completed by language-specific frontends. + /// Language-specific frontends may customize the \ref bmct objects + /// that are used for model-checking by supplying a function object to + /// the `frontend_configure_bmc` parameter of this function; the + /// function object will be called with every \ref bmct object that + /// is constructed by `do_language_agnostic_bmc`. + static int do_language_agnostic_bmc( + const optionst &opts, + const goto_modelt &goto_model, + const ui_message_handlert::uit &ui, + messaget &message, + std::function frontend_configure_bmc = + [](bmct &_bmc, const goto_modelt &) { // NOLINT (*) + // Empty default implementation + }); + protected: const optionst &options; symbol_tablet new_symbol_table; @@ -144,6 +164,36 @@ class bmct:public safety_checkert template