From 90a041da9c70ea06cbe03859e8ab97a39aa698f1 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 18 Feb 2019 21:59:19 +0000 Subject: [PATCH 1/3] Move bmct and all_properties to jbmc/ These aren't used by CBMC anymore, but only for the symex-driven lazy-loading mode of JBMC. --- jbmc/src/jbmc/Makefile | 6 +++--- {src/cbmc => jbmc/src/jbmc}/all_properties.cpp | 0 {src/cbmc => jbmc/src/jbmc}/all_properties_class.h | 0 {src/cbmc => jbmc/src/jbmc}/bmc.cpp | 0 {src/cbmc => jbmc/src/jbmc}/bmc.h | 0 jbmc/src/jbmc/jbmc_parse_options.cpp | 2 +- jbmc/src/jbmc/module_dependencies.txt | 3 ++- src/cbmc/Makefile | 4 +--- src/cbmc/cbmc_parse_options.h | 1 - unit/Makefile | 4 +--- 10 files changed, 8 insertions(+), 12 deletions(-) rename {src/cbmc => jbmc/src/jbmc}/all_properties.cpp (100%) rename {src/cbmc => jbmc/src/jbmc}/all_properties_class.h (100%) rename {src/cbmc => jbmc/src/jbmc}/bmc.cpp (100%) rename {src/cbmc => jbmc/src/jbmc}/bmc.h (100%) diff --git a/jbmc/src/jbmc/Makefile b/jbmc/src/jbmc/Makefile index 1efad8a920..ec96389eef 100644 --- a/jbmc/src/jbmc/Makefile +++ b/jbmc/src/jbmc/Makefile @@ -1,4 +1,6 @@ -SRC = jbmc_main.cpp \ +SRC = all_properties.cpp \ + bmc.cpp \ + jbmc_main.cpp \ jbmc_parse_options.cpp \ # Empty last line @@ -39,8 +41,6 @@ OBJ += ../$(CPROVER_DIR)/src/ansi-c/ansi-c$(LIBEXT) \ ../$(CPROVER_DIR)/src/util/util$(LIBEXT) \ ../miniz/miniz$(OBJEXT) \ ../$(CPROVER_DIR)/src/json/json$(LIBEXT) \ - ../$(CPROVER_DIR)/src/cbmc/all_properties$(OBJEXT) \ - ../$(CPROVER_DIR)/src/cbmc/bmc$(OBJEXT) \ # Empty last line INCLUDES= -I .. -I ../$(CPROVER_DIR)/src diff --git a/src/cbmc/all_properties.cpp b/jbmc/src/jbmc/all_properties.cpp similarity index 100% rename from src/cbmc/all_properties.cpp rename to jbmc/src/jbmc/all_properties.cpp diff --git a/src/cbmc/all_properties_class.h b/jbmc/src/jbmc/all_properties_class.h similarity index 100% rename from src/cbmc/all_properties_class.h rename to jbmc/src/jbmc/all_properties_class.h diff --git a/src/cbmc/bmc.cpp b/jbmc/src/jbmc/bmc.cpp similarity index 100% rename from src/cbmc/bmc.cpp rename to jbmc/src/jbmc/bmc.cpp diff --git a/src/cbmc/bmc.h b/jbmc/src/jbmc/bmc.h similarity index 100% rename from src/cbmc/bmc.h rename to jbmc/src/jbmc/bmc.h diff --git a/jbmc/src/jbmc/jbmc_parse_options.cpp b/jbmc/src/jbmc/jbmc_parse_options.cpp index be67484fc4..b0bc9e2e8e 100644 --- a/jbmc/src/jbmc/jbmc_parse_options.cpp +++ b/jbmc/src/jbmc/jbmc_parse_options.cpp @@ -61,7 +61,7 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include // will go away +#include "bmc.h" // will go away #include #include diff --git a/jbmc/src/jbmc/module_dependencies.txt b/jbmc/src/jbmc/module_dependencies.txt index e878b9c20f..d9411b8728 100644 --- a/jbmc/src/jbmc/module_dependencies.txt +++ b/jbmc/src/jbmc/module_dependencies.txt @@ -1,6 +1,5 @@ analyses ansi-c # should go away -cbmc # bmc.h - will go away goto-checker goto-instrument goto-programs @@ -11,5 +10,7 @@ langapi # should go away linking pointer-analysis solvers/refinement +solvers/prop +solvers/sat solvers/strings util diff --git a/src/cbmc/Makefile b/src/cbmc/Makefile index b9f7201d2d..e2a15dfd0e 100644 --- a/src/cbmc/Makefile +++ b/src/cbmc/Makefile @@ -1,6 +1,4 @@ -SRC = all_properties.cpp \ - bmc.cpp \ - c_test_input_generator.cpp \ +SRC = c_test_input_generator.cpp \ cbmc_languages.cpp \ cbmc_main.cpp \ cbmc_parse_options.cpp \ diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index f3d6349991..49b7a5cc82 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -31,7 +31,6 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include "bmc.h" #include "xml_interface.h" class goto_functionst; diff --git a/unit/Makefile b/unit/Makefile index c93aa6fc93..2d7bbc5bbe 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -98,9 +98,7 @@ testing-utils-clean: $(MAKE) $(MAKEARGS) -C testing-utils clean # We need to link bmc.o to the unit test, so here's everything it depends on... -BMC_DEPS =../src/cbmc/all_properties$(OBJEXT) \ - ../src/cbmc/bmc$(OBJEXT) \ - ../src/cbmc/c_test_input_generator$(OBJEXT) \ +BMC_DEPS =../src/cbmc/c_test_input_generator$(OBJEXT) \ ../src/cbmc/cbmc_languages$(OBJEXT) \ ../src/cbmc/cbmc_parse_options$(OBJEXT) \ ../src/cbmc/xml_interface$(OBJEXT) \ From c94d0afbd065145797c527308560c4358ce5552c Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Mon, 18 Feb 2019 22:38:15 +0000 Subject: [PATCH 2/3] Clang-format --- jbmc/src/jbmc/all_properties.cpp | 277 ++++++++++++++------------- jbmc/src/jbmc/all_properties_class.h | 41 ++-- jbmc/src/jbmc/bmc.cpp | 38 ++-- jbmc/src/jbmc/bmc.h | 22 +-- 4 files changed, 191 insertions(+), 187 deletions(-) diff --git a/jbmc/src/jbmc/all_properties.cpp b/jbmc/src/jbmc/all_properties.cpp index 44d5eab13f..89273d31d3 100644 --- a/jbmc/src/jbmc/all_properties.cpp +++ b/jbmc/src/jbmc/all_properties.cpp @@ -17,32 +17,32 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include +#include #include #include -#include -#include #include +#include +#include void bmc_all_propertiest::goal_covered(const cover_goalst::goalt &) { for(auto &g : goal_map) { // failed already? - if(g.second.status==goalt::statust::FAILURE) + if(g.second.status == goalt::statust::FAILURE) continue; // check whether failed for(auto &c : g.second.instances) { - literalt cond=c->cond_literal; + literalt cond = c->cond_literal; if(solver.l_get(cond).is_false()) { - g.second.status=goalt::statust::FAILURE; + g.second.status = goalt::statust::FAILURE; build_goto_trace(bmc.equation, c, solver, bmc.ns, g.second.goto_trace); break; } @@ -54,7 +54,7 @@ safety_checkert::resultt bmc_all_propertiest::operator()() { status() << "Passing problem to " << solver.decision_procedure_text() << eom; - auto solver_start=std::chrono::steady_clock::now(); + auto solver_start = std::chrono::steady_clock::now(); convert_symex_target_equation( bmc.equation, bmc.prop_conv, get_message_handler()); @@ -65,13 +65,13 @@ safety_checkert::resultt bmc_all_propertiest::operator()() forall_goto_functions(f_it, goto_functions) forall_goto_program_instructions(i_it, f_it->second.body) if(i_it->is_assert()) - goal_map[i_it->source_location.get_property_id()]=goalt(*i_it); + goal_map[i_it->source_location.get_property_id()] = goalt(*i_it); // get the conditions for these goals from formula // collect all 'instances' of the properties - for(symex_target_equationt::SSA_stepst::iterator - it=bmc.equation.SSA_steps.begin(); - it!=bmc.equation.SSA_steps.end(); + for(symex_target_equationt::SSA_stepst::iterator it = + bmc.equation.SSA_steps.begin(); + it != bmc.equation.SSA_steps.end(); it++) { if(it->is_assert()) @@ -101,29 +101,29 @@ safety_checkert::resultt bmc_all_propertiest::operator()() { // Our goal is to falsify a property, i.e., we will // add the negation of the property as goal. - literalt p=!solver.convert(g.second.as_expr()); + literalt p = !solver.convert(g.second.as_expr()); cover_goals.add(p); } status() << "Running " << solver.decision_procedure_text() << eom; - bool error=false; + bool error = false; const decision_proceduret::resultt result = cover_goals(get_message_handler()); - if(result==decision_proceduret::resultt::D_ERROR) + if(result == decision_proceduret::resultt::D_ERROR) { - error=true; + error = true; for(auto &g : goal_map) - if(g.second.status==goalt::statust::UNKNOWN) - g.second.status=goalt::statust::ERROR; + if(g.second.status == goalt::statust::UNKNOWN) + g.second.status = goalt::statust::ERROR; } else { for(auto &g : goal_map) - if(g.second.status==goalt::statust::UNKNOWN) - g.second.status=goalt::statust::SUCCESS; + if(g.second.status == goalt::statust::UNKNOWN) + g.second.status = goalt::statust::SUCCESS; } { @@ -141,14 +141,15 @@ safety_checkert::resultt bmc_all_propertiest::operator()() if(error) return safety_checkert::resultt::ERROR; - bool safe=(cover_goals.number_covered()==0); + bool safe = (cover_goals.number_covered() == 0); if(safe) report_success(bmc.ui_message_handler); // legacy, might go away else report_failure(bmc.ui_message_handler); // legacy, might go away - return safe?safety_checkert::resultt::SAFE:safety_checkert::resultt::UNSAFE; + return safe ? safety_checkert::resultt::SAFE + : safety_checkert::resultt::UNSAFE; } void bmc_all_propertiest::report(const cover_goalst &cover_goals) @@ -156,141 +157,141 @@ void bmc_all_propertiest::report(const cover_goalst &cover_goals) switch(bmc.ui_message_handler.get_ui()) { case ui_message_handlert::uit::PLAIN: - { - result() << "\n** Results:" << eom; + { + result() << "\n** Results:" << eom; - // collect goals in a vector - std::vector goals; + // collect goals in a vector + std::vector goals; - for(auto g_it = goal_map.begin(); g_it != goal_map.end(); g_it++) - goals.push_back(g_it); + for(auto g_it = goal_map.begin(); g_it != goal_map.end(); g_it++) + goals.push_back(g_it); - // now determine an ordering for those goals: - // 1. alphabetical ordering of file name - // 2. numerical ordering of line number - // 3. alphabetical ordering of goal ID - std::sort( - goals.begin(), - goals.end(), - [](goal_mapt::const_iterator git1, goal_mapt::const_iterator git2) { - const auto &g1 = git1->second.source_location; - const auto &g2 = git2->second.source_location; - if(g1.get_file() != g2.get_file()) - return id2string(g1.get_file()) < id2string(g2.get_file()); - else if(!g1.get_line().empty() && !g2.get_line().empty()) - return std::stoul(id2string(g1.get_line())) < - std::stoul(id2string(g2.get_line())); - else - return id2string(git1->first) < id2string(git2->first); - }); - - // now show in the order we have determined - - irep_idt previous_function; - irep_idt current_file; - for(const auto &g : goals) - { - const auto &l = g->second.source_location; - - if(l.get_function() != previous_function) - { - if(!previous_function.empty()) - result() << '\n'; - previous_function = l.get_function(); - if(!previous_function.empty()) - { - current_file = l.get_file(); - if(!current_file.empty()) - result() << current_file << ' '; - if(!l.get_function().empty()) - result() << "function " << l.get_function(); - result() << eom; - } - } - - result() << faint << '[' << g->first << "] " << reset; - - if(l.get_file() != current_file) - result() << "file " << l.get_file() << ' '; - - if(!l.get_line().empty()) - result() << "line " << l.get_line() << ' '; - - result() << g->second.description << ": "; - - if(g->second.status == goalt::statust::SUCCESS) - result() << green; + // now determine an ordering for those goals: + // 1. alphabetical ordering of file name + // 2. numerical ordering of line number + // 3. alphabetical ordering of goal ID + std::sort( + goals.begin(), + goals.end(), + [](goal_mapt::const_iterator git1, goal_mapt::const_iterator git2) { + const auto &g1 = git1->second.source_location; + const auto &g2 = git2->second.source_location; + if(g1.get_file() != g2.get_file()) + return id2string(g1.get_file()) < id2string(g2.get_file()); + else if(!g1.get_line().empty() && !g2.get_line().empty()) + return std::stoul(id2string(g1.get_line())) < + std::stoul(id2string(g2.get_line())); else - result() << red; + return id2string(git1->first) < id2string(git2->first); + }); - result() << g->second.status_string() << reset << eom; - } + // now show in the order we have determined - if(bmc.options.get_bool_option("trace")) + irep_idt previous_function; + irep_idt current_file; + for(const auto &g : goals) + { + const auto &l = g->second.source_location; + + if(l.get_function() != previous_function) { - for(const auto &g : goal_map) - if(g.second.status==goalt::statust::FAILURE) - { - result() << "\n" << "Trace for " << g.first << ":" << "\n"; - show_goto_trace( - result(), bmc.ns, g.second.goto_trace, bmc.trace_options()); - result() << eom; - } + if(!previous_function.empty()) + result() << '\n'; + previous_function = l.get_function(); + if(!previous_function.empty()) + { + current_file = l.get_file(); + if(!current_file.empty()) + result() << current_file << ' '; + if(!l.get_function().empty()) + result() << "function " << l.get_function(); + result() << eom; + } } - status() << "\n** " << cover_goals.number_covered() - << " of " << cover_goals.size() << " failed (" - << cover_goals.iterations() << " iteration" - << (cover_goals.iterations()==1?"":"s") - << ")" << eom; + result() << faint << '[' << g->first << "] " << reset; + + if(l.get_file() != current_file) + result() << "file " << l.get_file() << ' '; + + if(!l.get_line().empty()) + result() << "line " << l.get_line() << ' '; + + result() << g->second.description << ": "; + + if(g->second.status == goalt::statust::SUCCESS) + result() << green; + else + result() << red; + + result() << g->second.status_string() << reset << eom; } - break; + + if(bmc.options.get_bool_option("trace")) + { + for(const auto &g : goal_map) + if(g.second.status == goalt::statust::FAILURE) + { + result() << "\n" + << "Trace for " << g.first << ":" + << "\n"; + show_goto_trace( + result(), bmc.ns, g.second.goto_trace, bmc.trace_options()); + result() << eom; + } + } + + status() << "\n** " << cover_goals.number_covered() << " of " + << cover_goals.size() << " failed (" << cover_goals.iterations() + << " iteration" << (cover_goals.iterations() == 1 ? "" : "s") + << ")" << eom; + } + break; case ui_message_handlert::uit::XML_UI: + { + for(const auto &g : goal_map) { - for(const auto &g : goal_map) - { - xmlt xml_result( - "result", - {{"property", id2string(g.first)}, - {"status", g.second.status_string()}}, - {}); + xmlt xml_result( + "result", + {{"property", id2string(g.first)}, + {"status", g.second.status_string()}}, + {}); - if(g.second.status==goalt::statust::FAILURE) - convert(bmc.ns, g.second.goto_trace, xml_result.new_element()); + if(g.second.status == goalt::statust::FAILURE) + convert(bmc.ns, g.second.goto_trace, xml_result.new_element()); - result() << xml_result; - } - break; - } - - case ui_message_handlert::uit::JSON_UI: - { - if(result().tellp() > 0) - result() << eom; // force end of previous message - json_stream_objectt &json_result = - bmc.ui_message_handler.get_json_stream().push_back_stream_object(); - json_stream_arrayt &result_array = - json_result.push_back_stream_array("result"); - - for(const auto &g : goal_map) - { - json_stream_objectt &result = result_array.push_back_stream_object(); - result["property"] = json_stringt(g.first); - result["description"] = json_stringt(g.second.description); - result["status"]=json_stringt(g.second.status_string()); - - if(g.second.status==goalt::statust::FAILURE) - { - json_stream_arrayt &json_trace = - result.push_back_stream_array("trace"); - convert( - bmc.ns, g.second.goto_trace, json_trace, bmc.trace_options()); - } - } + result() << xml_result; } break; } + + case ui_message_handlert::uit::JSON_UI: + { + if(result().tellp() > 0) + result() << eom; // force end of previous message + json_stream_objectt &json_result = + bmc.ui_message_handler.get_json_stream().push_back_stream_object(); + json_stream_arrayt &result_array = + json_result.push_back_stream_array("result"); + + for(const auto &g : goal_map) + { + json_stream_objectt &result = result_array.push_back_stream_object(); + result["property"] = json_stringt(g.first); + result["description"] = json_stringt(g.second.description); + result["status"] = json_stringt(g.second.status_string()); + + if(g.second.status == goalt::statust::FAILURE) + { + json_stream_arrayt &json_trace = result.push_back_stream_array("trace"); + convert( + bmc.ns, g.second.goto_trace, json_trace, bmc.trace_options()); + } + } + } + break; + } } safety_checkert::resultt diff --git a/jbmc/src/jbmc/all_properties_class.h b/jbmc/src/jbmc/all_properties_class.h index 293babda09..a5fc881ada 100644 --- a/jbmc/src/jbmc/all_properties_class.h +++ b/jbmc/src/jbmc/all_properties_class.h @@ -17,16 +17,14 @@ Author: Daniel Kroening, kroening@kroening.com #include "bmc.h" -class bmc_all_propertiest: - public cover_goalst::observert, - public messaget +class bmc_all_propertiest : public cover_goalst::observert, public messaget { public: bmc_all_propertiest( const goto_functionst &_goto_functions, prop_convt &_solver, - bmct &_bmc): - goto_functions(_goto_functions), solver(_solver), bmc(_bmc) + bmct &_bmc) + : goto_functions(_goto_functions), solver(_solver), bmc(_bmc) { } @@ -44,17 +42,27 @@ public: source_locationt source_location; // if failed, we compute a goto_trace for the first failing instance - enum statust { UNKNOWN, FAILURE, SUCCESS, ERROR } status; + enum statust + { + UNKNOWN, + FAILURE, + SUCCESS, + ERROR + } status; goto_tracet goto_trace; std::string status_string() const { switch(status) { - case UNKNOWN: return "UNKNOWN"; - case FAILURE: return "FAILURE"; - case SUCCESS: return "SUCCESS"; - case ERROR: return "ERROR"; + case UNKNOWN: + return "UNKNOWN"; + case FAILURE: + return "FAILURE"; + case SUCCESS: + return "SUCCESS"; + case ERROR: + return "ERROR"; } // make some poor compilers happy @@ -62,15 +70,14 @@ public: return ""; } - explicit goalt( - const goto_programt::instructiont &instruction): - status(statust::UNKNOWN) + explicit goalt(const goto_programt::instructiont &instruction) + : status(statust::UNKNOWN) { source_location = instruction.source_location; - description=id2string(instruction.source_location.get_comment()); + description = id2string(instruction.source_location.get_comment()); } - goalt():status(statust::UNKNOWN) + goalt() : status(statust::UNKNOWN) { } @@ -93,7 +100,9 @@ protected: bmct &bmc; virtual void report(const cover_goalst &cover_goals); - virtual void do_before_solving() {} + virtual void do_before_solving() + { + } }; #endif // CPROVER_CBMC_ALL_PROPERTIES_CLASS_H diff --git a/jbmc/src/jbmc/bmc.cpp b/jbmc/src/jbmc/bmc.cpp index 44caf9e528..e9b590a8ff 100644 --- a/jbmc/src/jbmc/bmc.cpp +++ b/jbmc/src/jbmc/bmc.cpp @@ -42,8 +42,8 @@ void bmct::freeze_program_variables() decision_proceduret::resultt bmct::run_decision_procedure() { - status() << "Passing problem to " - << prop_conv.decision_procedure_text() << eom; + status() << "Passing problem to " << prop_conv.decision_procedure_text() + << eom; auto solver_start = std::chrono::steady_clock::now(); @@ -54,7 +54,7 @@ decision_proceduret::resultt bmct::run_decision_procedure() status() << "Running " << prop_conv.decision_procedure_text() << eom; - decision_proceduret::resultt dec_result=prop_conv.dec_solve(); + decision_proceduret::resultt dec_result = prop_conv.dec_solve(); { auto solver_stop = std::chrono::steady_clock::now(); @@ -67,14 +67,13 @@ decision_proceduret::resultt bmct::run_decision_procedure() return dec_result; } -safety_checkert::resultt bmct::execute( - abstract_goto_modelt &goto_model) +safety_checkert::resultt bmct::execute(abstract_goto_modelt &goto_model) { try { - auto get_goto_function = [&goto_model](const irep_idt &id) -> - const goto_functionst::goto_functiont & - { + auto get_goto_function = + [&goto_model]( + const irep_idt &id) -> const goto_functionst::goto_functiont & { return goto_model.get_goto_function(id); }; @@ -84,8 +83,7 @@ safety_checkert::resultt bmct::execute( // iterators pointing into it, must not be stored by this function or its // callees, as goto_model.get_goto_function (as used by symex) // will have side-effects on it. - const goto_functionst &goto_functions = - goto_model.get_goto_functions(); + const goto_functionst &goto_functions = goto_model.get_goto_functions(); // This provides the driver program the opportunity to do things like a // symbol-table or goto-functions dump instead of actually running the @@ -108,16 +106,15 @@ safety_checkert::resultt bmct::execute( (*memory_model)(equation); } - statistics() << "size of program expression: " - << equation.SSA_steps.size() + statistics() << "size of program expression: " << equation.SSA_steps.size() << " steps" << eom; slice(symex, equation, ns, options, ui_message_handler); // coverage report - std::string cov_out=options.get_option("symex-coverage-report"); - if(!cov_out.empty() && - symex.output_coverage_report(goto_functions, cov_out)) + std::string cov_out = options.get_option("symex-coverage-report"); + if( + !cov_out.empty() && symex.output_coverage_report(goto_functions, cov_out)) { error() << "Failed to write symex coverage report" << eom; return safety_checkert::resultt::ERROR; @@ -156,7 +153,7 @@ safety_checkert::resultt bmct::execute( catch(const std::string &error_str) { messaget message(get_message_handler()); - message.error().source_location=symex.last_source_location; + message.error().source_location = symex.last_source_location; message.error() << error_str << messaget::eom; return safety_checkert::resultt::ERROR; @@ -165,7 +162,7 @@ safety_checkert::resultt bmct::execute( catch(const char *error_str) { messaget message(get_message_handler()); - message.error().source_location=symex.last_source_location; + message.error().source_location = symex.last_source_location; message.error() << error_str << messaget::eom; return safety_checkert::resultt::ERROR; @@ -178,9 +175,7 @@ safety_checkert::resultt bmct::execute( } } - -safety_checkert::resultt bmct::run( - abstract_goto_modelt &goto_model) +safety_checkert::resultt bmct::run(abstract_goto_modelt &goto_model) { memory_model = get_memory_model(options, ns); setup_symex(symex, ns, options, ui_message_handler); @@ -222,8 +217,7 @@ safety_checkert::resultt bmct::stop_on_fail() return resultt::UNSAFE; default: - if(options.get_bool_option("dimacs") || - options.get_option("outfile")!="") + if(options.get_bool_option("dimacs") || options.get_option("outfile") != "") return resultt::SAFE; error() << "decision procedure failed" << eom; diff --git a/jbmc/src/jbmc/bmc.h b/jbmc/src/jbmc/bmc.h index b5bc58a642..3543103cda 100644 --- a/jbmc/src/jbmc/bmc.h +++ b/jbmc/src/jbmc/bmc.h @@ -15,23 +15,22 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include -#include #include #include -#include #include +#include #include #include #include - class cbmc_solverst; /// \brief Bounded model checking or path exploration for goto-programs @@ -39,7 +38,7 @@ class cbmc_solverst; /// Higher-level architectural information on symbolic execution is /// documented in the \ref symex-overview /// "Symbolic execution module page". -class bmct:public safety_checkert +class bmct : public safety_checkert { public: /// \brief Constructor for path exploration with freshly-initialized state @@ -100,11 +99,12 @@ public: resultt run(abstract_goto_modelt &); void setup(); safety_checkert::resultt execute(abstract_goto_modelt &); - virtual ~bmct() { } + virtual ~bmct() + { + } // the safety_checkert interface - virtual resultt operator()( - const goto_functionst &goto_functions) + virtual resultt operator()(const goto_functionst &goto_functions) { return run(goto_functions); } @@ -114,8 +114,8 @@ public: symex.add_loop_unwind_handler(handler); } - void add_unwind_recursion_handler( - symex_bmct::recursion_unwind_handlert handler) + void + add_unwind_recursion_handler(symex_bmct::recursion_unwind_handlert handler) { symex.add_recursion_unwind_handler(handler); } @@ -207,8 +207,8 @@ private: /// invoke the symbolic executor in a class-specific way. This /// implementation invokes goto_symext::operator() to perform /// full-program model-checking from the entry point of the program. - virtual void perform_symbolic_execution( - goto_symext::get_goto_functiont get_goto_function); + virtual void + perform_symbolic_execution(goto_symext::get_goto_functiont get_goto_function); /// Optional callback, to be run after symex but before handing the resulting /// equation to the solver. If it returns true then we will skip the solver From 14109a48ba16c6d482bd6dfbf35e4d57f1e51bac Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Thu, 7 Mar 2019 17:36:36 +0000 Subject: [PATCH 3/3] Fix path explorer unit test Cannot use deprecated bmct anymore. --- unit/path_strategies.cpp | 233 +++++++++++++++++++++++---------------- unit/path_strategies.h | 5 +- 2 files changed, 142 insertions(+), 96 deletions(-) diff --git a/unit/path_strategies.cpp b/unit/path_strategies.cpp index 451be55eb6..6061077a61 100644 --- a/unit/path_strategies.cpp +++ b/unit/path_strategies.cpp @@ -16,10 +16,11 @@ Author: Kareem Khazem , 2018 #include -#include #include -#include +#include +#include +#include #include @@ -42,8 +43,8 @@ Author: Kareem Khazem , 2018 // `goto` instruction. // // Whenever symbolic execution reaches the end of a path, you should expect a -// result. Results are either SUCCESS, meaning that verification of that path -// succeeded, or FAILURE, meaning that there was an assertion failure on that +// result. Results are either DONE, meaning that verification of that path +// succeeded, or FOUND_FAIL, meaning that there was an assertion failure on that // path. // // To figure out what the events should be, run CBMC on the test program with @@ -80,14 +81,18 @@ SCENARIO("path strategies") "lifo", opts_callback, c, - {symex_eventt::resume(symex_eventt::enumt::JUMP, 7), + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + symex_eventt::resume(symex_eventt::enumt::JUMP, 7), symex_eventt::resume(symex_eventt::enumt::NEXT, 5), symex_eventt::result(symex_eventt::enumt::SUCCESS)}); check_with_strategy( "fifo", opts_callback, c, - {symex_eventt::resume(symex_eventt::enumt::NEXT, 5), + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + symex_eventt::resume(symex_eventt::enumt::NEXT, 5), symex_eventt::resume(symex_eventt::enumt::JUMP, 7), symex_eventt::result(symex_eventt::enumt::SUCCESS)}); } @@ -120,7 +125,9 @@ SCENARIO("path strategies") "lifo", opts_callback, c, - {// Outer else, inner else + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + // Outer else, inner else symex_eventt::resume(symex_eventt::enumt::JUMP, 13), symex_eventt::resume(symex_eventt::enumt::JUMP, 16), // Outer else, inner if @@ -136,7 +143,9 @@ SCENARIO("path strategies") "fifo", opts_callback, c, - {// Expand outer if, but don't continue depth-first + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + // Expand outer if, but don't continue depth-first symex_eventt::resume(symex_eventt::enumt::NEXT, 6), // Jump to outer else, but again don't continue depth-first symex_eventt::resume(symex_eventt::enumt::JUMP, 13), @@ -175,6 +184,9 @@ SCENARIO("path strategies") opts_callback, c, { + // Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + // The path where x != 1 and we have nothing to check: symex_eventt::resume(symex_eventt::enumt::JUMP, 11), @@ -204,6 +216,9 @@ SCENARIO("path strategies") opts_callback, c, { + // Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + // First the path where we enter the if-block at line 4 then on hitting // the branch at line 6 consider skipping straight to the end, but find // nothing there to investigate: @@ -257,7 +272,9 @@ SCENARIO("path strategies") "lifo", no_halt_callback, c, - {symex_eventt::resume(symex_eventt::enumt::JUMP, 7), + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + symex_eventt::resume(symex_eventt::enumt::JUMP, 7), symex_eventt::result(symex_eventt::enumt::FAILURE), symex_eventt::resume(symex_eventt::enumt::NEXT, 5), symex_eventt::result(symex_eventt::enumt::FAILURE), @@ -270,7 +287,9 @@ SCENARIO("path strategies") "lifo", halt_callback, c, - {symex_eventt::resume(symex_eventt::enumt::JUMP, 7), + {// Entry state is line 0 + symex_eventt::resume(symex_eventt::enumt::NEXT, 0), + symex_eventt::resume(symex_eventt::enumt::JUMP, 7), symex_eventt::result(symex_eventt::enumt::FAILURE), // Overall result symex_eventt::result(symex_eventt::enumt::FAILURE)}); @@ -283,24 +302,24 @@ SCENARIO("path strategies") void symex_eventt::validate_result( listt &events, - const safety_checkert::resultt result, + const incremental_goto_checkert::resultt::progresst result, std::size_t &counter) { INFO( "Expecting result to be '" - << (result == safety_checkert::resultt::SAFE ? "success" : "failure") + << (result == incremental_goto_checkert::resultt::progresst::DONE + ? "success" + : "failure") << "' (item at index [" << counter << "] in expected results list"); ++counter; - REQUIRE(result != safety_checkert::resultt::ERROR); - - if(result == safety_checkert::resultt::SAFE) + if(result == incremental_goto_checkert::resultt::progresst::DONE) { REQUIRE(!events.empty()); REQUIRE(events.front().first == symex_eventt::enumt::SUCCESS); events.pop_front(); } - else if(result == safety_checkert::resultt::UNSAFE) + else { REQUIRE(!events.empty()); REQUIRE(events.front().first == symex_eventt::enumt::FAILURE); @@ -315,17 +334,11 @@ void symex_eventt::validate_resume( { REQUIRE(!events.empty()); - int dst = std::stoi(state.saved_target->source_location.get_line().c_str()); + int dst = 0; + if(!state.saved_target->source_location.get_line().empty()) + dst = std::stoi(state.saved_target->source_location.get_line().c_str()); - if(state.has_saved_jump_target) - { - INFO( - "Expecting resume to be 'jump' to line " - << dst << " (item at index [" << counter - << "] in expected resumes list)"); - REQUIRE(events.front().first == symex_eventt::enumt::JUMP); - } - else if(state.has_saved_next_instruction) + if(state.has_saved_next_instruction) { INFO( "Expecting resume to be 'next' to line " @@ -333,6 +346,14 @@ void symex_eventt::validate_resume( << "] in expected resumes list)"); REQUIRE(events.front().first == symex_eventt::enumt::NEXT); } + else if(state.has_saved_jump_target) + { + INFO( + "Expecting resume to be 'jump' to line " + << dst << " (item at index [" << counter + << "] in expected resumes list)"); + REQUIRE(events.front().first == symex_eventt::enumt::JUMP); + } else REQUIRE(false); @@ -342,11 +363,8 @@ void symex_eventt::validate_resume( events.pop_front(); } -// This is a simplified version of bmct::do_language_agnostic_bmc, without all -// the edge cases to deal with java programs, bytecode loaded on demand, etc. We -// need to replicate some of this stuff because the worklist is a local variable -// of do_language_agnostic_bmc, and we need to check the worklist every time -// symex returns. +// This is a simplified copy of single_path_symex_checkert +// because we have to check the worklist every time goto-symex returns. void _check_with_strategy( const std::string &strategy, const std::string &program, @@ -366,95 +384,122 @@ void _check_with_strategy( config.main = "main"; config.set(cmdline); - optionst opts; - cbmc_parse_optionst::set_default_options(opts); - opts.set_option("paths", true); - opts.set_option("exploration-strategy", strategy); - - opts_callback(opts); - - ui_message_handlert mh(cmdline, "path-explore"); - mh.set_verbosity(0); - messaget log(mh); - + optionst options; + cbmc_parse_optionst::set_default_options(options); + options.set_option("paths", true); + options.set_option("exploration-strategy", strategy); REQUIRE(is_valid_path_strategy(strategy)); + opts_callback(options); + + ui_message_handlert ui_message_handler(cmdline, "path-explore"); + ui_message_handler.set_verbosity(0); + messaget log(ui_message_handler); + + goto_modelt goto_model; + int ret; + ret = cbmc_parse_optionst::get_goto_program( + goto_model, options, cmdline, log, ui_message_handler); + REQUIRE(ret == -1); + + symbol_tablet symex_symbol_table; + namespacet ns(goto_model.get_symbol_table(), symex_symbol_table); + propertiest properties(initialize_properties(goto_model)); std::unique_ptr worklist = get_path_strategy(strategy); guard_managert guard_manager; - goto_modelt gm; - int ret; - ret = cbmc_parse_optionst::get_goto_program(gm, opts, cmdline, log, mh); - REQUIRE(ret == -1); + { + // Put initial state into the work list + symex_target_equationt equation(ui_message_handler); + symex_bmct symex( + ui_message_handler, + goto_model.get_symbol_table(), + equation, + options, + *worklist, + guard_manager); + setup_symex(symex, ns, options, ui_message_handler); - namespacet ns(gm.get_symbol_table()); - solver_factoryt solver_factory(opts, ns, mh, false); - std::unique_ptr cbmc_solver = - solver_factory.get_solver(); - prop_convt &initial_pc = cbmc_solver->prop_conv(); - std::function callback = []() { return false; }; + symex.initialize_path_storage_from_entry_point_of( + goto_symext::get_goto_function(goto_model), symex_symbol_table); + } - safety_checkert::resultt overall_result = safety_checkert::resultt::SAFE; std::size_t expected_results_cnt = 0; - - bmct bmc( - opts, - gm.get_symbol_table(), - mh, - initial_pc, - *worklist, - callback, - guard_manager); - safety_checkert::resultt tmp_result = bmc.run(gm); - - if(tmp_result != safety_checkert::resultt::PAUSED) - { - symex_eventt::validate_result(events, tmp_result, expected_results_cnt); - overall_result &= tmp_result; - } - - if( - overall_result == safety_checkert::resultt::UNSAFE && - opts.get_bool_option("stop-on-fail") && opts.is_set("paths")) - { - worklist->clear(); - } - while(!worklist->empty()) { - cbmc_solver = solver_factory.get_solver(); - prop_convt &pc = cbmc_solver->prop_conv(); path_storaget::patht &resume = worklist->peek(); symex_eventt::validate_resume(events, resume.state, expected_results_cnt); - path_explorert pe( - opts, - gm.get_symbol_table(), - mh, - pc, + symex_bmct symex( + ui_message_handler, + goto_model.get_symbol_table(), resume.equation, - resume.state, + options, *worklist, - guard_manager, - callback); - tmp_result = pe.run(gm); + guard_manager); + setup_symex(symex, ns, options, ui_message_handler); - if(tmp_result != safety_checkert::resultt::PAUSED) + symex.resume_symex_from_saved_state( + goto_symext::get_goto_function(goto_model), + resume.state, + &resume.equation, + symex_symbol_table); + postprocess_equation( + symex, resume.equation, options, ns, ui_message_handler); + + incremental_goto_checkert::resultt result( + incremental_goto_checkert::resultt::progresst::DONE); + + if(symex.get_remaining_vccs() > 0) { - symex_eventt::validate_result(events, tmp_result, expected_results_cnt); - overall_result &= tmp_result; + update_properties_status_from_symex_target_equation( + properties, result.updated_properties, resume.equation); + + goto_symex_property_decidert property_decider( + options, ui_message_handler, resume.equation, ns); + + const auto solver_runtime = prepare_property_decider( + properties, resume.equation, property_decider, ui_message_handler); + + run_property_decider( + result, + properties, + property_decider, + ui_message_handler, + solver_runtime, + false); + + symex_eventt::validate_result( + events, result.progress, expected_results_cnt); } + worklist->pop(); if( - overall_result == safety_checkert::resultt::UNSAFE && - opts.get_bool_option("stop-on-fail")) + result.progress == + incremental_goto_checkert::resultt::progresst::FOUND_FAIL && + options.get_bool_option("stop-on-fail")) { worklist->clear(); } + + if(worklist->empty()) + { + update_status_of_not_checked_properties( + properties, result.updated_properties); + + update_status_of_unknown_properties( + properties, result.updated_properties); + } } - symex_eventt::validate_result(events, overall_result, expected_results_cnt); + const resultt overall_result = determine_result(properties); + symex_eventt::validate_result( + events, + overall_result == resultt::FAIL + ? incremental_goto_checkert::resultt::progresst::FOUND_FAIL + : incremental_goto_checkert::resultt::progresst::DONE, + expected_results_cnt); INFO("The expected results list contains " << events.size() << " items"); REQUIRE(events.empty()); diff --git a/unit/path_strategies.h b/unit/path_strategies.h index c953789619..118bc2f730 100644 --- a/unit/path_strategies.h +++ b/unit/path_strategies.h @@ -6,7 +6,8 @@ #define CPROVER_PATH_STRATEGIES_H #include -#include + +#include #include @@ -38,7 +39,7 @@ public: static void validate_result( listt &events, - const safety_checkert::resultt result, + const incremental_goto_checkert::resultt::progresst result, std::size_t &); static void