From db24bfa338422c92cdc18fe448179edc327c55d8 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 10 Jul 2024 17:39:08 +0800 Subject: [PATCH 001/126] update slhv encoding and refactor --- src/esbmc/bmc.cpp | 44 +- src/esbmc/bmc.h | 2 +- src/goto-symex/symex_target_equation.cpp | 264 ++--- src/goto-symex/symex_target_equation.h | 14 +- src/solvers/CMakeLists.txt | 1 + src/solvers/smt/smt_conv.cpp | 88 +- src/solvers/smt/smt_conv.h | 11 + src/solvers/solve.cpp | 11 +- src/solvers/solve.h | 6 +- src/solvers/solver_config.h.in | 4 + src/solvers/z3-slhv/CMakeLists.txt | 8 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 1304 ++++++++++++---------- src/solvers/z3-slhv/z3_slhv_conv.h | 67 +- 13 files changed, 1006 insertions(+), 818 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index ea6ac680..c5278d4f 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -40,6 +40,7 @@ #include #include #include +#include bmct::bmct(goto_functionst &funcs, optionst &opts, contextt &_context) : options(opts), context(_context), ns(context) @@ -144,8 +145,10 @@ void bmct::generate_smt_from_equation( log_status("generate smt from equation"); std::string logic; - if (!options.get_bool_option("int-encoding")) - { + if (options.get_bool_option("z3-slhv")) { + logic = "SLHV"; + } + else if (!options.get_bool_option("int-encoding")) { logic = "bit-vector"; logic += (!config.ansi_c.use_fixed_for_float) ? "/floating-point " : " "; logic += "arithmetic"; @@ -162,13 +165,13 @@ void bmct::generate_smt_from_equation( "Encoding to solver time: {}s", time2string(encode_stop - encode_start)); } -std::string bmct::generate_slhv_smt_from_equation(z3_slhv_convt& slhv_converter, symex_target_equationt &eq) { - log_status("generate slhv formula from equation"); - std::string result; - eq.convert2slhv(slhv_converter); - log_status("here"); - return result; -} +// std::string bmct::generate_slhv_smt_from_equation(z3_slhv_convt& slhv_converter, symex_target_equationt &eq) { +// log_status("generate slhv formula from equation"); +// std::string result; +// eq.convert2slhv(slhv_converter); +// log_status("here"); +// return result; +// } smt_convt::resultt bmct::run_decision_procedure(smt_convt &smt_conv, symex_target_equationt &eq) @@ -648,22 +651,27 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) return smt_convt::P_UNSATISFIABLE; } - if (!options.get_bool_option("smt-during-symex") && !options.get_bool_option("z3-slhv")) + if (!options.get_bool_option("smt-during-symex")) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); log_status("smt_convt created"); + if (options.get_bool_option("z3-slhv")) { + // show_vcc(*eq); + generate_smt_from_equation(*runtime_solver, *eq); + return smt_convt::P_SMTLIB; + } } - if (!options.get_bool_option("smt-during-symex") && options.get_bool_option("z3-slhv")) { + // if (!options.get_bool_option("smt-during-symex") && options.get_bool_option("z3-slhv")) { - log_status("enter branch dealing with slhv encoding"); - z3_slhv_convt* slhv_conv = new z3_slhv_convt(ns, options); - slhv_converter = std::unique_ptr(slhv_conv); - ; - std::string smt_str = generate_slhv_smt_from_equation(*slhv_converter, *eq); - return smt_convt::P_SMTLIB; - } + // log_status("enter branch dealing with slhv encoding"); + // z3_slhv_convt* slhv_conv = new z3_slhv_convt(ns, options); + // slhv_converter = std::unique_ptr(slhv_conv); + + // std::string smt_str = generate_slhv_smt_from_equation(*slhv_converter, *eq); + // return smt_convt::P_SMTLIB; + // } if ( options.get_bool_option("multi-property") && diff --git a/src/esbmc/bmc.h b/src/esbmc/bmc.h index fd6ece61..b6e50df0 100644 --- a/src/esbmc/bmc.h +++ b/src/esbmc/bmc.h @@ -73,7 +73,7 @@ class bmct void generate_smt_from_equation(smt_convt &smt_conv, symex_target_equationt &eq); - std::string generate_slhv_smt_from_equation(z3_slhv_convt& slhv_converter, symex_target_equationt &eq); + // std::string generate_slhv_smt_from_equation(z3_slhv_convt& slhv_converter, symex_target_equationt &eq); }; #endif diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index ae5897d3..8af8f8a2 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -132,13 +132,12 @@ void symex_target_equationt::renumber( debug_print_step(SSA_step); } - - void symex_target_equationt::convert(smt_convt &smt_conv) { smt_convt::ast_vec assertions; smt_astt assumpt_ast = smt_conv.convert_ast(gen_true_expr()); + log_status("============= begin converting ssa steps"); for (auto &SSA_step : SSA_steps) convert_internal_step(smt_conv, assumpt_ast, assertions, SSA_step); @@ -151,20 +150,20 @@ void symex_target_equationt::convert(smt_convt &smt_conv) } -void symex_target_equationt::convert2slhv(z3_slhv_convt& slhv_convt) { - smt_convt::ast_vec assertions; - smt_astt assumpt_ast = slhv_convt.convert_ast_slhv(gen_true_expr()); - for (auto &SSA_step : SSA_steps) - convert_internal_step_slhv(slhv_convt, assumpt_ast, assertions, SSA_step); +// void symex_target_equationt::convert2slhv(z3_slhv_convt& slhv_convt) { +// smt_convt::ast_vec assertions; +// smt_astt assumpt_ast = slhv_convt.convert_ast_slhv(gen_true_expr()); +// for (auto &SSA_step : SSA_steps) +// convert_internal_step_slhv(slhv_convt, assumpt_ast, assertions, SSA_step); - if (!assertions.empty()) - slhv_convt.assert_ast(slhv_convt.make_n_ary_or(assertions)); - log_status("final convert result ============= "); +// if (!assertions.empty()) +// slhv_convt.assert_ast(slhv_convt.make_n_ary_or(assertions)); +// log_status("final convert result ============= "); - slhv_convt.dump_smt(); - log_status("================================== "); +// slhv_convt.dump_smt(); +// log_status("================================== "); -} +// } void symex_target_equationt::convert_internal_step( smt_convt &smt_conv, @@ -179,12 +178,12 @@ void symex_target_equationt::convert_internal_step( if (step.ignore) { - std::ostringstream oss; - step.output(ns, oss); - log_status("{}", oss.str()); - log_status("convert internal step ignored ------ "); + // std::ostringstream oss; + // step.output(ns, oss); + // log_status("{}", oss.str()); + // log_status("convert internal step ignored ------ "); - log_status("-------------- over -----------------"); + // log_status("-------------- over -----------------"); step.cond_ast = true_val; step.guard_ast = false_val; return; @@ -192,12 +191,17 @@ void symex_target_equationt::convert_internal_step( if (ssa_trace) { - log_status("-------------- ssa trace -----------------"); - std::ostringstream oss; - step.output(ns, oss); - log_status("{}", oss.str()); - log_status("-------------- ssa trace end -----------------"); + // log_status("-------------- ssa trace -----------------"); + // std::ostringstream oss; + // step.output(ns, oss); + // log_status("{}", oss.str()); + // log_status("-------------- ssa trace end -----------------"); } + + log_status(" ============================== step ======================== "); + step.dump(); + log_status(" ============================== step ======================== "); + log_status("convert step guard ast: "); step.guard_ast = smt_conv.convert_ast(step.guard); step.guard_ast->dump(); @@ -271,112 +275,114 @@ void symex_target_equationt::convert_internal_step( } -void symex_target_equationt::convert_internal_step_slhv( - z3_slhv_convt& slhv_convt, - smt_astt& assumpt_ast, - smt_convt::ast_vec& assertions, - SSA_stept &step - ) { - - log_status("------ convert internal step slhv ------ "); - static unsigned output_count = 0; // Temporary hack; should become scoped. - smt_astt true_val = slhv_convt.convert_ast_slhv(gen_true_expr()); - smt_astt false_val = slhv_convt.convert_ast_slhv(gen_false_expr()); - - if (step.ignore) - { - std::ostringstream oss; - step.output(ns, oss); - log_status("{}", oss.str()); - log_status("convert internal step ignored ------ "); - - log_status("-------------- over -----------------"); - step.cond_ast = true_val; - step.guard_ast = false_val; - return; - } - - if (ssa_trace) - { - log_status("-------------- ssa trace -----------------"); - std::ostringstream oss; - step.output(ns, oss); - log_status("{}", oss.str()); - log_status("-------------- ssa trace end-----------------"); - } - log_status("------------- convert step guard ast: "); - step.guard_ast = slhv_convt.convert_ast_slhv(step.guard); - - if (step.is_assume() || step.is_assert()) - { - log_status("----- step is_assume || step is_assert"); - expr2tc tmp(step.cond); - step.cond_ast = slhv_convt.convert_ast_slhv(tmp); - if (ssa_smt_trace) - { - step.cond_ast->dump(); - } - } - else if (step.is_assignment()) - { - log_status(" ----- step is_assignment"); - smt_astt assign = slhv_convt.convert_assign_slhv(step.cond); - if (ssa_smt_trace) - { - assign->dump(); - } - - log_status("-------------- over -----------------"); - } - else if (step.is_output()) - { - log_status(" ----- step is_output"); - // for (std::list::const_iterator o_it = step.output_args.begin(); - // o_it != step.output_args.end(); - // o_it++) - // { - // const expr2tc &tmp = *o_it; - // if (is_constant_expr(tmp) || is_constant_string2t(tmp)) - // step.converted_output_args.push_back(tmp); - // else - // { - // expr2tc sym = - // symbol2tc(tmp->type, "symex::output::" + i2string(output_count++)); - // expr2tc eq = equality2tc(sym, tmp); - // smt_astt assign = smt_conv.convert_assign(eq); - // if (ssa_smt_trace) - // assign->dump(); - // step.converted_output_args.push_back(sym); - // } - // } - } - else if (step.is_renumber()) - { - log_status(" ----- step is_renumber"); - // smt_conv.renumber_symbol_address(step.guard, step.lhs, step.rhs); - } - else if (!step.is_skip()) - { - assert(0 && "Unexpected SSA step type in conversion"); - } - - if (step.is_assert()) - { - log_status(" ----- step is_assert"); - step.cond_ast = slhv_convt.imply_ast(assumpt_ast, step.cond_ast); - assertions.push_back(slhv_convt.invert_ast(step.cond_ast)); - slhv_convt.invert_ast(step.cond_ast)->dump(); - } - else if (step.is_assume()) - { - log_status(" ----- step is_assume"); - assumpt_ast = slhv_convt.mk_and(assumpt_ast, step.cond_ast); - step.cond_ast->dump(); - } - - log_status("-------------- over -----------------"); -} - +// void symex_target_equationt::convert_internal_step_slhv( +// z3_slhv_convt& slhv_convt, +// smt_astt& assumpt_ast, +// smt_convt::ast_vec& assertions, +// SSA_stept &step +// ) { + +// log_status("------ convert internal step slhv ------ "); +// static unsigned output_count = 0; // Temporary hack; should become scoped. +// smt_astt true_val = slhv_convt.convert_ast_slhv(gen_true_expr()); +// smt_astt false_val = slhv_convt.convert_ast_slhv(gen_false_expr()); + +// if (step.ignore) +// { +// // std::ostringstream oss; +// // step.output(ns, oss); +// // log_status("{}", oss.str()); +// // log_status("convert internal step ignored ------ "); + +// // log_status("-------------- over -----------------"); +// step.cond_ast = true_val; +// step.guard_ast = false_val; +// return; +// } + +// log_status(" ------------------ dump step ------------------- "); +// step.dump(); + +// if (ssa_trace) +// { +// log_status("-------------- ssa trace -----------------"); +// std::ostringstream oss; +// step.output(ns, oss); +// log_status("{}", oss.str()); +// log_status("-------------- ssa trace end-----------------"); +// } +// log_status("------------- convert step guard ast: "); +// step.guard_ast = slhv_convt.convert_ast_slhv(step.guard); + +// if (step.is_assume() || step.is_assert()) +// { +// log_status("----- step is_assume || step is_assert"); +// expr2tc tmp(step.cond); +// step.cond_ast = slhv_convt.convert_ast_slhv(tmp); +// if (ssa_smt_trace) +// { +// step.cond_ast->dump(); +// } +// } +// else if (step.is_assignment()) +// { +// log_status(" ----- step is_assignment"); +// smt_astt assign = slhv_convt.convert_assign_slhv(step.cond); +// if (ssa_smt_trace) +// { +// assign->dump(); +// } + +// log_status("-------------- assignment over -----------------"); +// } +// else if (step.is_output()) +// { +// log_status(" ----- step is_output"); +// // for (std::list::const_iterator o_it = step.output_args.begin(); +// // o_it != step.output_args.end(); +// // o_it++) +// // { +// // const expr2tc &tmp = *o_it; +// // if (is_constant_expr(tmp) || is_constant_string2t(tmp)) +// // step.converted_output_args.push_back(tmp); +// // else +// // { +// // expr2tc sym = +// // symbol2tc(tmp->type, "symex::output::" + i2string(output_count++)); +// // expr2tc eq = equality2tc(sym, tmp); +// // smt_astt assign = smt_conv.convert_assign(eq); +// // if (ssa_smt_trace) +// // assign->dump(); +// // step.converted_output_args.push_back(sym); +// // } +// // } +// } +// else if (step.is_renumber()) +// { +// log_status(" ----- step is_renumber"); +// // smt_conv.renumber_symbol_address(step.guard, step.lhs, step.rhs); +// } +// else if (!step.is_skip()) +// { +// assert(0 && "Unexpected SSA step type in conversion"); +// } + +// if (step.is_assert()) +// { +// log_status(" ----- step is_assert"); +// step.cond_ast = slhv_convt.imply_ast(assumpt_ast, step.cond_ast); +// assertions.push_back(slhv_convt.invert_ast(step.cond_ast)); +// slhv_convt.invert_ast(step.cond_ast)->dump(); +// } +// else if (step.is_assume()) +// { +// log_status(" ----- step is_assume"); +// assumpt_ast = slhv_convt.mk_and(assumpt_ast, step.cond_ast); +// step.cond_ast->dump(); +// } + +// log_status("-------------- over -----------------"); +// } void symex_target_equationt::output(std::ostream &out) const { diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index 09b4ab07..98724b2c 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -73,7 +73,7 @@ class symex_target_equationt : public symex_targett const sourcet &source) override; virtual void convert(smt_convt &smt_conv); - void convert2slhv(z3_slhv_convt& slhv_convt); + // void convert2slhv(z3_slhv_convt& slhv_convt); void convert_internal_step( smt_convt &smt_conv, @@ -81,12 +81,12 @@ class symex_target_equationt : public symex_targett smt_convt::ast_vec &assertions, SSA_stept &s); - void convert_internal_step_slhv( - z3_slhv_convt& slhv_convt, - smt_astt& assumpt_ast, - smt_convt::ast_vec& assertions, - SSA_stept &s - ); + // void convert_internal_step_slhv( + // z3_slhv_convt& slhv_convt, + // smt_astt& assumpt_ast, + // smt_convt::ast_vec& assertions, + // SSA_stept &s + // ); void reconstruct_symbolic_expression(expr2tc &expr, bool keep_local_variables) const override; diff --git a/src/solvers/CMakeLists.txt b/src/solvers/CMakeLists.txt index 56a2fead..179dd158 100644 --- a/src/solvers/CMakeLists.txt +++ b/src/solvers/CMakeLists.txt @@ -5,6 +5,7 @@ set (ESBMC_ENABLE_cvc4 0) set (ESBMC_ENABLE_mathsat 0) set (ESBMC_ENABLE_yices 0) set (ESBMC_ENABLE_bitwuzla 0) +set (ESBMC_ENABLE_z3_slhv 0) add_subdirectory(prop) add_subdirectory(smt) diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index e8059f59..e5dc3aab 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -142,6 +142,8 @@ void smt_convt::smt_post_init() { boolean_sort = mk_bool_sort(); + if (options.get_bool_option("z3-slhv")) { return; } + init_addr_space_array(); if (int_encoding) @@ -235,12 +237,14 @@ smt_astt smt_convt::convert_assign(const expr2tc &expr) smt_astt smt_convt::convert_ast(const expr2tc &expr) { - log_status("== convert ast "); + log_status("------------------------------- convert ast "); expr->dump(); - log_status("===="); + log_status("-------------------------------"); smt_cachet::const_iterator cache_result = smt_cache.find(expr); - if (cache_result != smt_cache.end()) + if (cache_result != smt_cache.end()) { + log_status("found!!!!!!!!"); return (cache_result->ast); + } /* Vectors! * @@ -252,7 +256,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) * for some reason we would like to run ESBMC without simplifications * then we need to apply it here. */ - if (is_vector_type(expr)) + if (!options.get_bool_option("z3-slhv") && is_vector_type(expr)) { if (is_neg2t(expr)) { @@ -317,6 +321,28 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) smt_astt a; switch (expr->expr_id) { + case expr2t::points_to_id: { + assert(args.size() == 2); + a = mk_pt(args[0], args[1]); + break; + } + case expr2t::uplus_id: { + assert(args.size() >= 2); + a = args[0]; + for (int i = 1; i < args.size(); i++) { + a = mk_uplus(a, args[i]); + } + break; + } + case expr2t::locadd_id: { + assert(args.size() == 2); + a = mk_locadd(args[0], args[1]); + break; + } + + case expr2t::constant_intheap_id: + case expr2t::constant_intloc_id: + case expr2t::pointer_with_region_id: case expr2t::constant_int_id: case expr2t::constant_fixedbv_id: case expr2t::constant_floatbv_id: @@ -1269,6 +1295,13 @@ smt_sortt smt_convt::convert_sort(const type2tc &type) smt_sortt result = nullptr; switch (type->type_id) { + case type2t::intheap_id: + result = mk_intheap_sort(); + break; + case type2t::intloc_id: + result = mk_intloc_sort(); + break; + case type2t::bool_id: result = boolean_sort; break; @@ -1391,7 +1424,20 @@ smt_astt smt_convt::convert_terminal(const expr2tc &expr) log_status("convert terminal: "); expr.get()->dump(); switch (expr->expr_id) - { + { + case expr2t::constant_intheap_id: { + return mk_emp(); + } + case expr2t::constant_intloc_id: { + return mk_nil(); + } + case expr2t::pointer_with_region_id: { + const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); + const symbol2t& nsym = to_symbol2t(pwr.loc_ptr); + std::string name = nsym.get_symbol_name(); + smt_sortt sort = convert_sort(nsym.type); + return mk_smt_symbol(name, sort); + } case expr2t::constant_int_id: { const constant_int2t &theint = to_constant_int2t(expr); @@ -3374,3 +3420,35 @@ smt_astt smt_convt::mk_isint(smt_astt a) (void)a; abort(); } + +smt_astt smt_convt::mk_emp() { abort(); } + +smt_astt smt_convt::mk_nil() { abort(); } + +smt_astt smt_convt::mk_pt(smt_astt a, smt_astt b) { + (void)a; + (void)b; + abort(); +} + +smt_astt smt_convt::mk_uplus(smt_astt a, smt_astt b) { + (void)a; + (void)b; + abort(); +} + +smt_astt smt_convt::mk_locadd(smt_astt a, smt_astt b) { + (void)a; + (void)b; + abort(); +} + +smt_sortt smt_convt::mk_intheap_sort() { + log_error("Chosen solver doesn't support intheap sorts"); + abort(); +} + +smt_sortt smt_convt::mk_intloc_sort() { + log_error("Chosen solver doesn't support inltoc sorts"); + abort(); +} \ No newline at end of file diff --git a/src/solvers/smt/smt_conv.h b/src/solvers/smt/smt_conv.h index e38c0281..fd6301aa 100644 --- a/src/solvers/smt/smt_conv.h +++ b/src/solvers/smt/smt_conv.h @@ -335,6 +335,17 @@ class smt_convt virtual smt_astt mk_int2real(smt_astt a); virtual smt_astt mk_isint(smt_astt a); + // SLHV mk_operators + virtual smt_astt mk_emp(); + virtual smt_astt mk_nil(); + virtual smt_astt mk_pt(smt_astt a, smt_astt b); + virtual smt_astt mk_uplus(smt_astt a, smt_astt b); + virtual smt_astt mk_locadd(smt_astt a, smt_astt b); + + // SLHV mk_sort + virtual smt_sortt mk_intheap_sort(); + virtual smt_sortt mk_intloc_sort(); + /** Create an integer or SBV/UBV sort */ smt_sortt mk_int_bv_sort(std::size_t width) { diff --git a/src/solvers/solve.cpp b/src/solvers/solve.cpp index 41a07746..50978646 100644 --- a/src/solvers/solve.cpp +++ b/src/solvers/solve.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +// #include #include @@ -17,6 +17,7 @@ solver_creator create_new_cvc_solver; solver_creator create_new_mathsat_solver; solver_creator create_new_yices_solver; solver_creator create_new_bitwuzla_solver; +solver_creator create_new_z3_slhv_solver; static const std::unordered_map esbmc_solvers = { #ifdef SMTLIB @@ -41,7 +42,10 @@ static const std::unordered_map esbmc_solvers = { {"yices", create_new_yices_solver}, #endif #ifdef BITWUZLA - {"bitwuzla", create_new_bitwuzla_solver} + {"bitwuzla", create_new_bitwuzla_solver}, +#endif +#ifdef Z3_SLHV + {"z3-slhv", create_new_z3_slhv_solver}, #endif }; @@ -55,7 +59,8 @@ static const std::string all_solvers[] = { "cvc", "mathsat", "yices", - "bitwuzla"}; + "bitwuzla", + "z3-slhv"}; static std::string pick_default_solver() { diff --git a/src/solvers/solve.h b/src/solvers/solve.h index 1dde9273..b22a16e1 100644 --- a/src/solvers/solve.h +++ b/src/solvers/solve.h @@ -15,9 +15,9 @@ typedef smt_convt *(solver_creator)( fp_convt **fp_api); // slhv added -typedef smt_convt *(slhv_solver_creator)( - const optionst &options, - const namespacet &ns); +// typedef smt_convt *(slhv_solver_creator)( +// const optionst &options, +// const namespacet &ns); smt_convt *create_solver( std::string solver_name, diff --git a/src/solvers/solver_config.h.in b/src/solvers/solver_config.h.in index 802f8b11..b67368a1 100644 --- a/src/solvers/solver_config.h.in +++ b/src/solvers/solver_config.h.in @@ -29,3 +29,7 @@ #if @ESBMC_ENABLE_smtlib@ #define SMTLIB #endif + +#if @ESBMC_ENABLE_z3_slhv@ +#define Z3_SLHV +#endif diff --git a/src/solvers/z3-slhv/CMakeLists.txt b/src/solvers/z3-slhv/CMakeLists.txt index abc3d755..278dd413 100644 --- a/src/solvers/z3-slhv/CMakeLists.txt +++ b/src/solvers/z3-slhv/CMakeLists.txt @@ -12,7 +12,10 @@ else() endif() endif() -if(ENABLE_Z3) +if(ENABLE_Z3_SLHV) + if(NOT DEFINED Z3_DIR) + message(FATAL_ERROR "Could not find library, please check Z3_DIR") + endif() find_library(Z3_LIB z3 libz3 HINTS ${Z3_DIR} $ENV{HOME}/z3 PATH_SUFFIXES lib bin) find_path(Z3_INCLUDE_DIRS z3.h HINTS ${Z3_DIR} $ENV{HOME}/z3 PATH_SUFFIXES include) @@ -42,7 +45,6 @@ if(ENABLE_Z3) message(FATAL_ERROR "Expected version ${Z3_MIN_VERSION} or greater") endif() - add_library(solverz3slhv z3_slhv_conv.cpp) target_include_directories(solverz3slhv PRIVATE ${Z3_INCLUDE_DIRS} @@ -57,4 +59,6 @@ if(ENABLE_Z3) # Add to solver link target_link_libraries(solvers INTERFACE solverz3slhv) + set(ESBMC_ENABLE_z3_slhv 1 PARENT_SCOPE) + set(ESBMC_AVAILABLE_SOLVERS "${ESBMC_AVAILABLE_SOLVERS} z3-slhv" PARENT_SCOPE) endif() diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index e5b846e4..9c670a49 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -6,6 +6,42 @@ #define new_ast new_solver_ast +smt_convt *create_new_z3_slhv_solver( + const optionst &options, + const namespacet &ns, + tuple_iface **tuple_api, + array_iface **array_api, + fp_convt **fp_api) +{ + std::string z3_file = options.get_option("z3-debug-dump-file"); + if (options.get_bool_option("z3-debug")) + { + // Generate Z3 API file + Z3_open_log(z3_file.empty() ? "z3.log" : z3_file.c_str()); + + // Add Type checker + z3::config().set("stats", "true"); + + // Add typecheck + z3::config().set("type_check", "true"); + z3::config().set("well_sorted_check", "true"); + + // SMT2 Compliant + z3::config().set("smtlib2_compliant", "true"); + } + + if ( + options.get_bool_option("--smt-formula-only") || + options.get_bool_option("--smt-formula-too")) + z3::config().set("smtlib2_compliant", "true"); + + z3_slhv_convt *conv = new z3_slhv_convt(ns, options); + *tuple_api = static_cast(conv); + *array_api = static_cast(conv); + *fp_api = static_cast(conv); + log_status("z3_slhv solver created"); + return conv; +} smt_astt z3_slhv_smt_ast::update(smt_convt *ctx, smt_astt value, @@ -24,22 +60,21 @@ void z3_slhv_smt_ast::dump() const { log_status("{}\n sort is {}", print_str, a.get_sort().to_string()); } - -z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : smt_convt(_ns, _options) { +z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here + int_encoding = true; log_status("z3_slhv_convt created"); } -z3_slhv_convt::~z3_slhv_convt() { - delete_all_asts(); -} -void z3_slhv_convt::push_ctx() { +z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } -} +// void z3_slhv_convt::push_ctx() { -void z3_slhv_convt::pop_ctx() { +// } -} +// void z3_slhv_convt::pop_ctx() { + +// } void z3_slhv_convt::assert_ast(smt_astt a) { this->assertions.push_back(a); @@ -53,110 +88,134 @@ const std::string z3_slhv_convt::solver_text() { return "Z3-slhv"; } -smt_astt z3_slhv_convt::mk_smt_int(const BigInt &theint) { - smt_sortt s = mk_int_sort(); - if (theint.is_negative()) - return new_ast(z3_ctx.int_val(theint.to_int64()), s); - - return new_ast(z3_ctx.int_val(theint.to_uint64()), s); -} - -smt_astt z3_slhv_convt::mk_smt_real(const std::string &str) { - log_error("SLHV does not support real yet"); - abort(); - return nullptr; -} - -smt_astt z3_slhv_convt::mk_smt_bv(const BigInt &theint, smt_sortt s) { - log_error("SLHV does not support bv"); - abort(); - return nullptr; -} -smt_astt z3_slhv_convt::mk_smt_bool(bool val){ - return new_ast(z3_ctx.bool_val(val), mk_bool_sort()); -} -smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s){ - switch (s->id) - { - case SMT_SORT_BOOL: { - - break; - } - case SMT_SORT_INT: { - - break; - } - case SMT_SORT_INTHEAP: { - z3::expr hvar_expr = this->z3_ctx.hvar_const(name.c_str()); - return new_ast( - hvar_expr, - s - ); - break; - } - case SMT_SORT_INTLOC: { - break; - } - default: - log_status("unsupported sort in symbol making"); - break; - } -} -smt_astt z3_slhv_convt::mk_extract(smt_astt a, unsigned int high, unsigned int low){ - log_error("SLHV does not support bv"); - abort(); +// smt_astt z3_slhv_convt::mk_smt_int(const BigInt &theint) { +// smt_sortt s = mk_int_sort(); +// if (theint.is_negative()) +// return new_ast(z3_ctx.int_val(theint.to_int64()), s); + +// return new_ast(z3_ctx.int_val(theint.to_uint64()), s); +// } + +// smt_astt z3_slhv_convt::mk_smt_real(const std::string &str) { +// log_error("SLHV does not support real yet"); +// abort(); +// return nullptr; +// } + +// smt_astt z3_slhv_convt::mk_smt_bv(const BigInt &theint, smt_sortt s) { +// log_error("SLHV does not support bv"); +// abort(); +// return nullptr; +// } +// smt_astt z3_slhv_convt::mk_smt_bool(bool val){ +// return new_ast(z3_ctx.bool_val(val), mk_bool_sort()); +// } + +// smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s){ +// switch (s->id) +// { +// case SMT_SORT_BOOL: { +// z3::expr bexpr = this->z3_ctx.bool_const(name.c_str()); +// return new_ast(bexpr, s); +// } +// case SMT_SORT_INT: { +// z3::expr ivar = this->z3_ctx.int_const(name.c_str()); +// return new_ast(ivar, s); +// } +// case SMT_SORT_INTHEAP: { +// z3::expr hvar_expr = this->z3_ctx.hvar_const(name.c_str()); +// return new_ast(hvar_expr, s); +// } +// case SMT_SORT_INTLOC: { +// z3::expr lvar_expr = this->z3_ctx.locvar_const(name.c_str()); +// return new_ast(lvar_expr, s); +// } +// default: +// log_status("unsupported sort in symbol making"); +// break; +// } +// } +// smt_astt z3_slhv_convt::mk_extract(smt_astt a, unsigned int high, unsigned int low){ +// log_error("SLHV does not support bv"); +// abort(); -} -smt_astt z3_slhv_convt::mk_sign_ext(smt_astt a, unsigned int topwidth){ +// } +// smt_astt z3_slhv_convt::mk_sign_ext(smt_astt a, unsigned int topwidth){ - log_error("SLHV does not support bv"); - abort(); -} -smt_astt z3_slhv_convt::mk_zero_ext(smt_astt a, unsigned int topwidth){ +// log_error("SLHV does not support bv"); +// abort(); +// } +// smt_astt z3_slhv_convt::mk_zero_ext(smt_astt a, unsigned int topwidth){ - log_error("SLHV does not support bv"); - abort(); -} -smt_astt z3_slhv_convt::mk_concat(smt_astt a, smt_astt b){ - log_error("SLHV does not support bv"); - abort(); -} -// logical connections -smt_astt z3_slhv_convt::mk_ite(smt_astt cond, smt_astt t, smt_astt f){ +// log_error("SLHV does not support bv"); +// abort(); +// } +// smt_astt z3_slhv_convt::mk_concat(smt_astt a, smt_astt b){ +// log_error("SLHV does not support bv"); +// abort(); +// } +// // logical connections +// smt_astt z3_slhv_convt::mk_ite(smt_astt cond, smt_astt t, smt_astt f){ -} +// } + +// smt_astt z3_slhv_convt::mk_or(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_and(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_implies(smt_astt a, smt_astt b) { +// z3::expr premise = to_solver_smt_ast(a)->a; +// z3::expr conclusion = to_solver_smt_ast(b)->a; +// z3::expr impl = z3::implies(premise, conclusion); +// return new_ast(impl, boolean_sort); +// } +// smt_astt z3_slhv_convt::mk_not(smt_astt a) { +// z3::expr noteq = !to_solver_smt_ast(a)->a; +// return new_ast(noteq, boolean_sort); +// } +// // numeral assertions +// smt_astt z3_slhv_convt::mk_lt(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_le(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_gt(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_ge(smt_astt a, smt_astt b) {} +// smt_astt z3_slhv_convt::mk_eq(smt_astt a, smt_astt b) { +// assert(a->sort->id == b->sort->id); +// z3::expr lhs = to_solver_smt_ast(a)->a; +// z3::expr rhs = to_solver_smt_ast(b)->a; +// z3::expr z3eq = (lhs == rhs); +// return new_ast(z3eq, boolean_sort); +// } +// smt_astt z3_slhv_convt::mk_neq(smt_astt a, smt_astt b) {} +// // numeral terms +// smt_astt z3_slhv_convt::mk_add(smt_astt a, smt_astt b) { + +// } -smt_astt z3_slhv_convt::mk_or(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_and(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_implies(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_not(smt_astt a) {} -// numeral assertions -smt_astt z3_slhv_convt::mk_lt(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_le(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_gt(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_ge(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_eq(smt_astt a, smt_astt b) { - assert(a->sort->id == b->sort->id); - z3::expr lhs = to_solver_smt_ast(a)->a; - z3::expr rhs = to_solver_smt_ast(b)->a; - z3::expr z3eq = (lhs == rhs); - return new_ast(z3eq, boolean_sort); +// heap terms +smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { + z3::expr pt = z3::points_to( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ); + return new_ast(pt, this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_neq(smt_astt a, smt_astt b) {} -// numeral terms -smt_astt z3_slhv_convt::mk_add(smt_astt a, smt_astt b) { - +smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b){ + z3::expr h = z3::uplus( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ); + return new_ast(h, this->mk_intheap_sort()); } -// heap terms -smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) {} -smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b){} smt_astt z3_slhv_convt::mk_emp() { z3::expr emp = z3_ctx.emp_const(); return new_ast(emp, this->mk_intheap_sort()); } // loc terms -smt_astt z3_slhv_convt::mk_locadd(smt_astt loc, smt_astt i){} -smt_astt z3_slhv_convt::mk_nil(){} +smt_astt z3_slhv_convt::mk_locadd(smt_astt loc, smt_astt i) { + +} +smt_astt z3_slhv_convt::mk_nil() { + z3::expr nil = z3_ctx.nil_const(); + return new_ast(nil, this->mk_intloc_sort()); +} bool z3_slhv_convt::get_bool(smt_astt a){ log_error("Can't get boolean value yet, solver not plugged."); @@ -166,510 +225,563 @@ BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed){ log_error("SLHV does not support bv"); abort(); } -smt_sortt z3_slhv_convt::mk_bool_sort() { - return new solver_smt_sort(SMT_SORT_BOOL, z3_ctx.bool_sort()); -} -smt_sortt z3_slhv_convt::mk_int_sort() { - return new solver_smt_sort(SMT_SORT_INT, z3_ctx.int_sort()); -} +// smt_sortt z3_slhv_convt::mk_bool_sort() { +// return new solver_smt_sort(SMT_SORT_BOOL, z3_ctx.bool_sort()); +// } -smt_sortt z3_slhv_convt::mk_intloc_sort() { - return new solver_smt_sort(SMT_SORT_INTLOC, z3_ctx.intloc_sort()); -} +// smt_sortt z3_slhv_convt::mk_int_sort() { +// return new solver_smt_sort(SMT_SORT_INT, z3_ctx.int_sort()); +// } smt_sortt z3_slhv_convt::mk_intheap_sort() { return new solver_smt_sort(SMT_SORT_INTHEAP, z3_ctx.intheap_sort()); } +smt_sortt z3_slhv_convt::mk_intloc_sort() { + return new solver_smt_sort(SMT_SORT_INTLOC, z3_ctx.intloc_sort()); +} -smt_astt z3_slhv_convt::convert_ast_slhv(const expr2tc &expr) { - log_status("== convert ast slhv"); - expr->dump(); - log_status("===="); - smt_cachet::const_iterator cache_result = smt_cache.find(expr); - if (cache_result != smt_cache.end()) - return (cache_result->ast); - - if (is_vector_type(expr)) { - log_status("WARNING!!!: does not support convert ast slhv vector type"); - } - - std::vector args; - args.reserve(expr->get_num_sub_exprs()); - - switch(expr->expr_id) { - - case expr2t::with_id: - case expr2t::constant_array_id: - case expr2t::constant_vector_id: - case expr2t::constant_array_of_id: - case expr2t::index_id: - case expr2t::address_of_id: - case expr2t::ieee_add_id: - case expr2t::ieee_sub_id: - case expr2t::ieee_mul_id: - case expr2t::ieee_div_id: - case expr2t::ieee_fma_id: - case expr2t::ieee_sqrt_id: - case expr2t::pointer_offset_id: - case expr2t::pointer_object_id: - case expr2t::pointer_capability_id: - break; // Don't convert their operands - - default: - { - // Convert all the arguments and store them in 'args'. - unsigned int i = 0; - expr->foreach_operand( - [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast_slhv(e); }); - } - } - - smt_astt a; - switch (expr->expr_id) - { - case expr2t::constant_fixedbv_id: - case expr2t::constant_floatbv_id: - case expr2t::constant_string_id: - - { - log_status("WARNING!!!: not supported expr id"); - std::cout << expr->expr_id << std::endl; - break; - } - case expr2t::constant_int_id: - { - const constant_int2t &theint = to_constant_int2t(expr); - a = mk_smt_int(theint.value); - break; - } - case expr2t::constant_bool_id: - { - const constant_bool2t &thebool = to_constant_bool2t(expr); - a = mk_smt_bool(thebool.value); - break; - } - case expr2t::symbol_id: - { - const symbol2t &sym = to_symbol2t(expr); - std::string name = sym.get_symbol_name(); - smt_sortt sort = convert_sort_slhv(sym.type); - std::cout << "symbol name: " << name << std::endl; - std::cout << "symbol thename: " << sym.thename << std::endl; - std::cout << "sort name: " << sort->id << std::endl; - a = mk_smt_symbol(name, sort); - break; - } - case expr2t::constant_vector_id: - { - log_status("WARNING!!!: not supported constant vector id convert ast"); - std::cout << expr->expr_id << std::endl; - break; - } +smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) { + assert(is_intloc_type(type)); + return mk_intloc_sort(); +} - case expr2t::constant_array_id: - { - log_status("WARNING: constant array id encountered"); - break; - } - case expr2t::constant_array_of_id: - { - const array_type2t &arr = to_array_type(expr->type); - const constant_array_of2t &aof_expr = to_constant_array_of2t(expr); - const expr2tc& init = aof_expr.initializer; - std::cout << "array of argument type id: " << init->type->type_id << std::endl; - if(is_constant_number(init)) { - a = this->mk_emp(); - } else { - log_status("WARNING: initializer of array of not supported"); - } - - break; - } - case expr2t::add_id: - { - const add2t &add = to_add2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(add.side_1) || - is_pointer_type(add.side_2)) - { - log_status("TODO: ptr adding not impled yet"); - } - else - { - a = mk_add(args[0], args[1]); - } - } - case expr2t::sub_id: - { - const sub2t &sub = to_sub2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || - is_pointer_type(sub.side_2)) - { - log_status("TODO: ptr sub not impled yet"); - } - else - { - a = mk_sub(args[0], args[1]); - } - break; - } - case expr2t::mul_id: - { - log_status("WARNING: mul_id not supported"); - break; - } - case expr2t::div_id: - { - log_status("WARNING: div_id not supported"); - break; - } - case expr2t::ieee_add_id: - case expr2t::ieee_sub_id: - case expr2t::ieee_mul_id: - case expr2t::ieee_div_id: - case expr2t::ieee_fma_id: - case expr2t::ieee_sqrt_id: - { +// smt_astt z3_slhv_convt::convert_ast_slhv(const expr2tc &expr) { +// log_status("== convert ast slhv"); +// expr->dump(); +// log_status("===="); +// smt_cachet::const_iterator cache_result = smt_cache.find(expr); +// if (cache_result != smt_cache.end()) { +// log_status("found -------------------::"); +// expr->dump(); +// return (cache_result->ast); +// } + +// if (is_vector_type(expr)) { +// log_status("WARNING!!!: does not support convert ast slhv vector type"); +// } + +// std::vector args; +// args.reserve(expr->get_num_sub_exprs()); + +// switch(expr->expr_id) { + +// case expr2t::with_id: +// case expr2t::constant_array_id: +// case expr2t::constant_vector_id: +// case expr2t::constant_array_of_id: +// case expr2t::index_id: +// case expr2t::address_of_id: +// case expr2t::ieee_add_id: +// case expr2t::ieee_sub_id: +// case expr2t::ieee_mul_id: +// case expr2t::ieee_div_id: +// case expr2t::ieee_fma_id: +// case expr2t::ieee_sqrt_id: +// case expr2t::pointer_offset_id: +// case expr2t::pointer_object_id: +// case expr2t::pointer_capability_id: +// break; // Don't convert their operands + +// default: +// { +// // Convert all the arguments and store them in 'args'. +// unsigned int i = 0; +// expr->foreach_operand( +// [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast_slhv(e); }); +// } +// } + +// log_status(" ------------- covert args ends ------------- "); +// expr->dump(); + +// smt_astt a; +// switch (expr->expr_id) +// { + +// case expr2t::constant_intheap_id: { +// const constant_intheap2t& intheap = to_constant_intheap2t(expr); +// log_status("{}", intheap.is_emp); +// expr->dump(); +// if (intheap.is_emp) { +// a = mk_emp(); +// } else { + +// } +// break; +// } +// case expr2t::constant_intloc_id: { +// const constant_intloc2t& intloc = to_constant_intloc2t(expr); +// if (intloc.value.is_zero()) { +// a = mk_nil(); +// } else { + +// } +// break; +// } +// case expr2t::points_to_id: { +// assert(args.size() == 2); +// a = mk_pt(args[0], args[1]); +// break; +// } +// case expr2t::uplus_id: { +// assert(args.size() >= 2); +// a = args[0]; +// for (int i = 1; i < args.size(); i++) { +// a = mk_uplus(a, args[i]); +// } +// break; +// } +// case expr2t::locadd_id: { +// assert(args.size() == 2); +// a = mk_locadd(args[0], args[1]); +// break; +// } +// case expr2t::constant_fixedbv_id: +// case expr2t::constant_floatbv_id: +// case expr2t::constant_string_id: +// { +// log_status("WARNING!!!: not supported expr id"); +// std::cout << expr->expr_id << std::endl; +// break; +// } +// case expr2t::constant_int_id: +// { +// const constant_int2t &theint = to_constant_int2t(expr); +// a = mk_smt_int(theint.value); +// break; +// } +// case expr2t::constant_bool_id: +// { +// const constant_bool2t &thebool = to_constant_bool2t(expr); +// a = mk_smt_bool(thebool.value); +// break; +// } +// case expr2t::symbol_id: +// { +// const symbol2t &sym = to_symbol2t(expr); +// std::string name = sym.get_symbol_name(); +// smt_sortt sort = convert_sort_slhv(sym.type); +// std::cout << "symbol name: " << name << std::endl; +// std::cout << "symbol thename: " << sym.thename << std::endl; +// std::cout << "sort name: " << sort->id << std::endl; +// a = mk_smt_symbol(name, sort); +// break; +// } +// case expr2t::constant_vector_id: +// { +// log_status("WARNING!!!: not supported constant vector id convert ast"); +// std::cout << expr->expr_id << std::endl; +// break; +// } + +// case expr2t::constant_array_id: +// { +// log_status("WARNING: constant array id encountered"); +// break; +// } +// case expr2t::constant_array_of_id: +// { +// const array_type2t &arr = to_array_type(expr->type); +// const constant_array_of2t &aof_expr = to_constant_array_of2t(expr); +// const expr2tc& init = aof_expr.initializer; +// std::cout << "array of argument type id: " << init->type->type_id << std::endl; +// if(is_constant_number(init)) { +// a = this->mk_emp(); +// } else { +// log_status("WARNING: initializer of array of not supported"); +// } + +// break; +// } +// case expr2t::add_id: +// { +// const add2t &add = to_add2t(expr); +// if ( +// is_pointer_type(expr->type) || is_pointer_type(add.side_1) || +// is_pointer_type(add.side_2)) +// { +// log_status("TODO: ptr adding not impled yet"); +// } +// else +// { +// a = mk_add(args[0], args[1]); +// } +// } +// case expr2t::sub_id: +// { +// const sub2t &sub = to_sub2t(expr); +// if ( +// is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || +// is_pointer_type(sub.side_2)) +// { +// log_status("TODO: ptr sub not impled yet"); +// } +// else +// { +// a = mk_sub(args[0], args[1]); +// } +// break; +// } +// case expr2t::mul_id: +// { +// log_status("WARNING: mul_id not supported"); +// break; +// } +// case expr2t::div_id: +// { +// log_status("WARNING: div_id not supported"); +// break; +// } +// case expr2t::ieee_add_id: +// case expr2t::ieee_sub_id: +// case expr2t::ieee_mul_id: +// case expr2t::ieee_div_id: +// case expr2t::ieee_fma_id: +// case expr2t::ieee_sqrt_id: +// { - log_status("WARNING: ieee expr2t not supported"); - break; - } - case expr2t::modulus_id: - { - log_status("WARNING: modulus_id not supported"); - break; - } - case expr2t::index_id: - { - log_status("TODO: index id not impled yet"); - break; - } - case expr2t::with_id: - { - const with2t &with = to_with2t(expr); - log_status("TODO: with id not impled yet"); - // We reach here if we're with'ing a struct, not an array. Or a bool. - if (is_struct_type(expr) || is_pointer_type(expr)) - { - log_status("expr struct/ptr type"); - } - else if (is_union_type(expr)) - { - log_status("expr union type"); - } - else - { - log_status("expr other type"); - } - break; - } - case expr2t::member_id: - { - log_status("TODO: member_id not impled yet"); - break; - } - case expr2t::same_object_id: - { - log_status("TODO: same_object_id not impled yet"); - break; - } - case expr2t::pointer_offset_id: - { - log_status("TODO: pointer_offset_id not impled yet"); - break; - } - case expr2t::pointer_object_id: - { - log_status("TODO: pointer_object_id not impled yet"); - break; - } - case expr2t::pointer_capability_id: - { - log_status("TODO: pointer_capability_id not impled yet"); - break; - } - case expr2t::typecast_id: - { - log_status("TODO: typecast_id not impled yet"); - break; - } - case expr2t::nearbyint_id: - { - log_status("WARNING: nearbyint_id not supported"); - break; - } - case expr2t::if_id: - { - // Only attempt to handle struct.s - const if2t &if_ref = to_if2t(expr); - args[0] = convert_ast(if_ref.cond); - args[1] = convert_ast(if_ref.true_value); - args[2] = convert_ast(if_ref.false_value); - a = args[1]->ite(this, args[0], args[2]); - break; - } - case expr2t::isnan_id: - { - log_status("WARNING: isnan_id not supported"); - break; - } - case expr2t::isinf_id: - { - log_status("WARNING: isinf_id not supported"); - break; - } - case expr2t::isnormal_id: - { - log_status("WARNING: isnormal_id not supported"); - break; - } - case expr2t::isfinite_id: - { - log_status("WARNING: isfinite_id not supported"); - break; - } - case expr2t::signbit_id: - { - log_status("WARNING: signbit_id not supported"); - break; - } - case expr2t::popcount_id: - { - log_status("WARNING: popcount_id not supported"); - break; - } - case expr2t::bswap_id: - { - log_status("WARNING: bswap_id not supported"); - break; - } - case expr2t::overflow_id: - { - log_status("WARNING: overflow_id not supported"); - break; - } - case expr2t::overflow_cast_id: - { - log_status("WARNING: overflow_cast_id not supported"); - break; - } - case expr2t::overflow_neg_id: - { - log_status("WARNING: overflow_neg_id not supported"); - break; - } - case expr2t::byte_extract_id: - { - log_status("WARNING: byte_extract_id not supported"); - break; - } - case expr2t::byte_update_id: - { - log_status("WARNING: byte_update_id not supported"); - break; - } - case expr2t::address_of_id: - { - log_status("WARNING: address_of_id not supported"); - break; - } - case expr2t::equality_id: - { - a = args[0]->eq(this, args[1]); - break; - } - case expr2t::notequal_id: - { - auto neq = to_notequal2t(expr); - a = args[0]->eq(this, args[1]); - a = mk_not(a); - break; - } - case expr2t::shl_id: - { - log_status("WARNING: shl_id not supported"); - break; - } - case expr2t::ashr_id: - { - log_status("WARNING: ashr_id not supported"); - break; - } - case expr2t::lshr_id: - { - log_status("WARNING: lshr_id not supported"); - break; - } - case expr2t::abs_id: - { - log_status("WARNING: abs_id not supported"); - break; - } - case expr2t::lessthan_id: - { - log_status("TODO: lessthan_id not impled yet"); - break; - } - case expr2t::lessthanequal_id: - { - log_status("TODO: lessthanequal_id not impled yet"); - break; - } - case expr2t::greaterthan_id: - { - log_status("TODO: greaterthan_id not impled yet"); - break; - } - case expr2t::greaterthanequal_id: - { +// log_status("WARNING: ieee expr2t not supported"); +// break; +// } +// case expr2t::modulus_id: +// { +// log_status("WARNING: modulus_id not supported"); +// break; +// } +// case expr2t::index_id: +// { +// log_status("TODO: index id not impled yet"); +// break; +// } +// case expr2t::with_id: +// { +// const with2t &with = to_with2t(expr); +// log_status("TODO: with id not impled yet"); +// // We reach here if we're with'ing a struct, not an array. Or a bool. +// if (is_struct_type(expr) || is_pointer_type(expr)) +// { +// log_status("expr struct/ptr type"); +// } +// else if (is_union_type(expr)) +// { +// log_status("expr union type"); +// } +// else +// { +// log_status("expr other type"); +// } +// break; +// } +// case expr2t::member_id: +// { +// log_status("TODO: member_id not impled yet"); +// break; +// } +// case expr2t::same_object_id: +// { +// log_status("TODO: same_object_id not impled yet"); +// break; +// } +// case expr2t::pointer_offset_id: +// { +// log_status("TODO: pointer_offset_id not impled yet"); +// break; +// } +// case expr2t::pointer_object_id: +// { +// log_status("TODO: pointer_object_id not impled yet"); +// break; +// } +// case expr2t::pointer_capability_id: +// { +// log_status("TODO: pointer_capability_id not impled yet"); +// break; +// } +// case expr2t::typecast_id: +// { +// log_status("TODO: typecast_id not impled yet"); +// break; +// } +// case expr2t::nearbyint_id: +// { +// log_status("WARNING: nearbyint_id not supported"); +// break; +// } +// case expr2t::if_id: +// { +// // Only attempt to handle struct.s +// const if2t &if_ref = to_if2t(expr); +// args[0] = convert_ast(if_ref.cond); +// args[1] = convert_ast(if_ref.true_value); +// args[2] = convert_ast(if_ref.false_value); +// a = args[1]->ite(this, args[0], args[2]); +// break; +// } +// case expr2t::isnan_id: +// { +// log_status("WARNING: isnan_id not supported"); +// break; +// } +// case expr2t::isinf_id: +// { +// log_status("WARNING: isinf_id not supported"); +// break; +// } +// case expr2t::isnormal_id: +// { +// log_status("WARNING: isnormal_id not supported"); +// break; +// } +// case expr2t::isfinite_id: +// { +// log_status("WARNING: isfinite_id not supported"); +// break; +// } +// case expr2t::signbit_id: +// { +// log_status("WARNING: signbit_id not supported"); +// break; +// } +// case expr2t::popcount_id: +// { +// log_status("WARNING: popcount_id not supported"); +// break; +// } +// case expr2t::bswap_id: +// { +// log_status("WARNING: bswap_id not supported"); +// break; +// } +// case expr2t::overflow_id: +// { +// log_status("WARNING: overflow_id not supported"); +// break; +// } +// case expr2t::overflow_cast_id: +// { +// log_status("WARNING: overflow_cast_id not supported"); +// break; +// } +// case expr2t::overflow_neg_id: +// { +// log_status("WARNING: overflow_neg_id not supported"); +// break; +// } +// case expr2t::byte_extract_id: +// { +// log_status("WARNING: byte_extract_id not supported"); +// break; +// } +// case expr2t::byte_update_id: +// { +// log_status("WARNING: byte_update_id not supported"); +// break; +// } +// case expr2t::address_of_id: +// { +// log_status("WARNING: address_of_id not supported"); +// break; +// } +// case expr2t::equality_id: +// { +// a = args[0]->eq(this, args[1]); +// break; +// } +// case expr2t::notequal_id: +// { +// auto neq = to_notequal2t(expr); +// a = args[0]->eq(this, args[1]); +// a = mk_not(a); +// break; +// } +// case expr2t::shl_id: +// { +// log_status("WARNING: shl_id not supported"); +// break; +// } +// case expr2t::ashr_id: +// { +// log_status("WARNING: ashr_id not supported"); +// break; +// } +// case expr2t::lshr_id: +// { +// log_status("WARNING: lshr_id not supported"); +// break; +// } +// case expr2t::abs_id: +// { +// log_status("WARNING: abs_id not supported"); +// break; +// } +// case expr2t::lessthan_id: +// { +// log_status("TODO: lessthan_id not impled yet"); +// break; +// } +// case expr2t::lessthanequal_id: +// { +// log_status("TODO: lessthanequal_id not impled yet"); +// break; +// } +// case expr2t::greaterthan_id: +// { +// log_status("TODO: greaterthan_id not impled yet"); +// break; +// } +// case expr2t::greaterthanequal_id: +// { - log_status("TODO: greaterthanequal_id not impled yet"); - break; - } - case expr2t::concat_id: - { - log_status("WARNING: concat_id not supported"); - break; - } - case expr2t::implies_id: - { - a = mk_implies(args[0], args[1]); - break; - } - case expr2t::bitand_id: - case expr2t::bitor_id: - case expr2t::bitxor_id: - case expr2t::bitnand_id: - case expr2t::bitnor_id: - case expr2t::bitnxor_id: - case expr2t::bitnot_id: - { - log_status("WARNING: bit operations not supported"); - break; - } - case expr2t::not_id: - { - assert(is_bool_type(expr)); - a = mk_not(args[0]); - break; - } - case expr2t::neg_id: - { - const neg2t &neg = to_neg2t(expr); - a = mk_neg(args[0]); - break; - } - case expr2t::and_id: - { - a = mk_and(args[0], args[1]); - break; - } - case expr2t::or_id: - { - a = mk_or(args[0], args[1]); - break; - } - case expr2t::xor_id: - { - a = mk_xor(args[0], args[1]); - break; - } - case expr2t::bitcast_id: - { - log_status("WARNING: bitcast_id not supported"); - break; - } - case expr2t::extract_id: - { - log_status("WARNING: extract_id not supported"); - break; - } - case expr2t::code_comma_id: - { - log_status("WARNING: code_comma_id not supported"); - break; - } - default: - log_error("Couldn't convert expression in unrecognised format\n{}", *expr); - abort(); - } - - struct smt_cache_entryt entry = {expr, a, ctx_level}; - smt_cache.insert(entry); - - log_status("==== converted reuslt: "); - a->dump(); - log_status("===="); - return a; - - -} - - -smt_sortt z3_slhv_convt::convert_sort_slhv(const type2tc &type) { - std::cout << "convert sort slhv, type name: " << type->type_id << std::endl; - smt_sort_cachet::const_iterator it = sort_cache.find(type); - if (it != sort_cache.end()) - { - return it->second; - } - - smt_sortt result = nullptr; - switch (type->type_id) - { - case type2t::bool_id: - result = boolean_sort; - break; - - case type2t::struct_id: - { - log_status("INFO: convert struct_id sort"); +// log_status("TODO: greaterthanequal_id not impled yet"); +// break; +// } +// case expr2t::concat_id: +// { +// log_status("WARNING: concat_id not supported"); +// break; +// } +// case expr2t::implies_id: +// { +// a = mk_implies(args[0], args[1]); +// break; +// } +// case expr2t::bitand_id: +// case expr2t::bitor_id: +// case expr2t::bitxor_id: +// case expr2t::bitnand_id: +// case expr2t::bitnor_id: +// case expr2t::bitnxor_id: +// case expr2t::bitnot_id: +// { +// log_status("WARNING: bit operations not supported"); +// break; +// } +// case expr2t::not_id: +// { +// assert(is_bool_type(expr)); +// a = mk_not(args[0]); +// break; +// } +// case expr2t::neg_id: +// { +// const neg2t &neg = to_neg2t(expr); +// a = mk_neg(args[0]); +// break; +// } +// case expr2t::and_id: +// { +// a = mk_and(args[0], args[1]); +// break; +// } +// case expr2t::or_id: +// { +// a = mk_or(args[0], args[1]); +// break; +// } +// case expr2t::xor_id: +// { +// a = mk_xor(args[0], args[1]); +// break; +// } +// case expr2t::bitcast_id: +// { +// log_status("WARNING: bitcast_id not supported"); +// break; +// } +// case expr2t::extract_id: +// { +// log_status("WARNING: extract_id not supported"); +// break; +// } +// case expr2t::code_comma_id: +// { +// log_status("WARNING: code_comma_id not supported"); +// break; +// } +// default: +// log_error("Couldn't convert expression in unrecognised format\n{}", *expr); +// abort(); +// } + +// struct smt_cache_entryt entry = {expr, a, ctx_level}; +// smt_cache.insert(entry); + +// log_status("==== converted reuslt: "); +// a->dump(); +// log_status("===="); +// return a; +// } + +// smt_sortt z3_slhv_convt::convert_sort_slhv(const type2tc &type) { +// std::cout << "convert sort slhv, type name: " << type->type_id << std::endl; +// smt_sort_cachet::const_iterator it = sort_cache.find(type); +// if (it != sort_cache.end()) +// { +// return it->second; +// } + +// smt_sortt result = nullptr; +// switch (type->type_id) +// { +// case type2t::bool_id: +// result = boolean_sort; +// break; + +// case type2t::struct_id: +// { +// log_status("INFO: convert struct_id sort"); - break; - } - case type2t::code_id: - case type2t::pointer_id: - log_status("TODO: convert code pointer id sort"); - break; - - - - case type2t::array_id: - { - log_status("INFO: convert array id type to intheap sort"); - result = this->mk_intheap_sort(); - - break; - } - - default: - log_error( - "Unexpected type ID {} reached SMT conversion", get_type_id(type)); - abort(); - } - - sort_cache.insert(smt_sort_cachet::value_type(type, result)); - return result; -} - -smt_astt z3_slhv_convt::convert_assign_slhv(const expr2tc &expr) { - - const equality2t &eq = to_equality2t(expr); - smt_astt side1 = convert_ast_slhv(eq.side_1); // LHS - smt_astt side2 = convert_ast_slhv(eq.side_2); // RHS - side2->assign(this, side1); - - smt_cache_entryt e = {eq.side_1, side2, ctx_level}; - smt_cache.insert(e); - return side2; -} - - - - -void z3_slhv_convt::dump_smt(){ - std::cout << "TODO: add smt dump here" << std::endl; -} \ No newline at end of file +// break; +// } +// case type2t::code_id: +// case type2t::pointer_id: +// log_status("TODO: convert code pointer id sort"); +// result = this->mk_intloc_sort(); +// break; + + +// case type2t::intheap_id: +// case type2t::array_id: +// { +// log_status("INFO: convert array id type to intheap sort"); +// result = this->mk_intheap_sort(); + +// break; +// } +// case type2t::signedbv_id: +// { +// result = this->mk_int_sort(); +// break; +// } + +// default: +// log_error( +// "Unexpected type ID {} reached SMT conversion", get_type_id(type)); +// abort(); +// } + +// sort_cache.insert(smt_sort_cachet::value_type(type, result)); +// return result; +// } + +// smt_astt z3_slhv_convt::convert_assign_slhv(const expr2tc &expr) { +// const equality2t &eq = to_equality2t(expr); +// smt_astt side1 = convert_ast_slhv(eq.side_1); // LHS +// smt_astt side2 = convert_ast_slhv(eq.side_2); // RHS +// side2->assign(this, side1); + +// smt_cache_entryt e = {eq.side_1, side2, ctx_level}; +// smt_cache.insert(e); +// return side2; +// } + + +// void z3_slhv_convt::print_smt_formulae(std::ostream &dest) { +// log_status("TODO: slhv print smt"); +// } + +// void z3_slhv_convt::dump_smt() { +// log_status("TODO: slhv dump smt"); +// } \ No newline at end of file diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 904edfc3..9f237ffa 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -3,10 +3,10 @@ // this file does not follow the translation procedure in the -#include +// #include +#include #include - class z3_slhv_smt_ast : public solver_smt_ast { public: @@ -24,10 +24,7 @@ class z3_slhv_smt_ast : public solver_smt_ast void dump() const override; }; -/* Be sure to not make smt_convt a *virtual* base class: our dtor ~z3_convt() - * erases all smt_asts early. */ - -class z3_slhv_convt : public smt_convt { +class z3_slhv_convt : public z3_convt { public: z3_slhv_convt(const namespacet &ns, const optionst &options); ~z3_slhv_convt() override; @@ -35,70 +32,32 @@ class z3_slhv_convt : public smt_convt { // interface for translation // TODO slhv: move to the api later, currently we use the smt-lib2 string translation // interfaces of smt_convt need implementation - void push_ctx() override; - void pop_ctx() override; void assert_ast(smt_astt a) override; resultt dec_solve() override; const std::string solver_text() override; - // terminal making - smt_astt mk_smt_int(const BigInt &theint) override; - smt_astt mk_smt_real(const std::string &str) override; - smt_astt mk_smt_bv(const BigInt &theint, smt_sortt s) override; - smt_astt mk_smt_bool(bool val) override; - smt_astt mk_smt_symbol(const std::string &name, smt_sortt s) override; - smt_astt mk_extract(smt_astt a, unsigned int high, unsigned int low) override; - smt_astt mk_sign_ext(smt_astt a, unsigned int topwidth) override; - smt_astt mk_zero_ext(smt_astt a, unsigned int topwidth) override; - smt_astt mk_concat(smt_astt a, smt_astt b) override; - // logical connection making - smt_astt mk_ite(smt_astt cond, smt_astt t, smt_astt f) override; - smt_astt mk_or(smt_astt a, smt_astt b) override; - smt_astt mk_and(smt_astt a, smt_astt b) override; - smt_astt mk_implies(smt_astt a, smt_astt b) override; - smt_astt mk_not(smt_astt a) override; - - // numeral assertions - smt_astt mk_lt(smt_astt a, smt_astt b) override; - smt_astt mk_le(smt_astt a, smt_astt b) override; - smt_astt mk_gt(smt_astt a, smt_astt b) override; - smt_astt mk_ge(smt_astt a, smt_astt b) override; - smt_astt mk_eq(smt_astt a, smt_astt b) override; - smt_astt mk_neq(smt_astt a, smt_astt b) override; - // numeral terms - smt_astt mk_add(smt_astt a, smt_astt b) override; - // heap terms - smt_astt mk_pt(smt_astt a, smt_astt b); - smt_astt mk_uplus(smt_astt a, smt_astt b); - smt_astt mk_emp(); + smt_astt mk_pt(smt_astt a, smt_astt b) override; + smt_astt mk_uplus(smt_astt a, smt_astt b) override; + smt_astt mk_emp() override; // loc terms - smt_astt mk_locadd(smt_astt loc, smt_astt i); - smt_astt mk_nil(); + smt_astt mk_locadd(smt_astt loc, smt_astt i) override; + smt_astt mk_nil() override; // value obtaining from solver, not supported here bool get_bool(smt_astt a) override; BigInt get_bv(smt_astt a, bool is_signed) override; - void dump_smt() override; // sort making - smt_sortt mk_bool_sort() override; - smt_sortt mk_int_sort() override; - smt_sortt mk_intloc_sort(); - smt_sortt mk_intheap_sort(); - - - // ast converting - smt_astt convert_ast_slhv(const expr2tc &expr); - smt_sortt convert_sort_slhv(const type2tc &type); - smt_astt convert_assign_slhv(const expr2tc &expr); - + smt_sortt mk_intheap_sort() override; + smt_sortt mk_intloc_sort() override; + smt_sortt mk_struct_sort(const type2tc &type) override; - std::vector assertions; - z3::context z3_ctx; +private: + std::vector assertions; }; #endif \ No newline at end of file From 617aec227bad99109938c570c717db4fdd10155d Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 11 Jul 2024 17:27:32 +0800 Subject: [PATCH 002/126] heap update encoding --- src/esbmc/bmc.cpp | 2 +- src/solvers/smt/smt_casts.cpp | 2 +- src/solvers/smt/smt_conv.cpp | 43 ++++++++++++++++++++++++++-- src/solvers/z3-slhv/z3_slhv_conv.cpp | 43 ++++++++++++++-------------- src/solvers/z3-slhv/z3_slhv_conv.h | 32 ++++++++++----------- 5 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index c5278d4f..29455ac8 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -657,7 +657,7 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) std::unique_ptr(create_solver("", ns, options)); log_status("smt_convt created"); if (options.get_bool_option("z3-slhv")) { - // show_vcc(*eq); + show_vcc(*eq); generate_smt_from_equation(*runtime_solver, *eq); return smt_convt::P_SMTLIB; } diff --git a/src/solvers/smt/smt_casts.cpp b/src/solvers/smt/smt_casts.cpp index 05c54985..6e82338d 100644 --- a/src/solvers/smt/smt_casts.cpp +++ b/src/solvers/smt/smt_casts.cpp @@ -403,7 +403,7 @@ smt_astt smt_convt::convert_typecast_to_ptr(const typecast2t &cast) { // First, sanity check -- typecast from one kind of a pointer to another kind // is a simple operation. Check for that first. - if (is_pointer_type(cast.from)) + if (is_pointer_type(cast.from) || is_intloc_type(cast.from)) return convert_ast(cast.from); // Unpleasentness; we don't know what pointer this integer is going to diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index e5dc3aab..5149eb5a 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -232,6 +232,11 @@ smt_astt smt_convt::convert_assign(const expr2tc &expr) smt_cache_entryt e = {eq.side_1, side2, ctx_level}; smt_cache.insert(e); + log_status(" ----------------- assignment result ----------------- "); + side1->dump(); + side2->dump(); + log_status(" ----------------- assignment result ----------------- "); + return side2; } @@ -315,6 +320,12 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) unsigned int i = 0; expr->foreach_operand( [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); + log_status(" -------------- convert args finished ------------ "); + for (int i = 0; i < expr->get_num_sub_exprs(); i++) { + args[i]->dump(); + } + log_status(" -------------- convert args finished ------------ "); + } } @@ -339,6 +350,29 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) a = mk_locadd(args[0], args[1]); break; } + case expr2t::heap_update_id: { + log_status("heap update"); + const heap_update2t& heap_upd = to_heap_update2t(expr); + smt_astt h = args[0]; + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap")); + smt_astt adr = args[1]; + smt_astt val = args[2]; + smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val")); + // old heap state + smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(adr, v1), h1)); + assert_ast(o_state); + // new heap state + a = mk_uplus(mk_pt(adr, val), h1); + break; + } + case expr2t::heap_load_id: { + log_status("TODO: heap load"); + abort(); + } + case expr2t::heap_contains_id: { + log_status("TODO: heap contains"); + abort(); + } case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: @@ -721,9 +755,12 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) } case expr2t::same_object_id: { + const same_object2t& so = to_same_object2t(expr); // Two projects, then comparison. - args[0] = args[0]->project(this, 0); - args[1] = args[1]->project(this, 0); + if (this->solver_text() != "Z3-slhv") { + args[0] = args[0]->project(this, 0); + args[1] = args[1]->project(this, 0); + } a = mk_eq(args[0], args[1]); break; } @@ -748,7 +785,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) ptr = &to_typecast2t(*ptr).from; args[0] = convert_ast(*ptr); - a = args[0]->project(this, 0); + a = this->solver_text() == "Z3-slhv" ? args[0] : args[0]->project(this, 0); break; } case expr2t::pointer_capability_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 9c670a49..39b5cf45 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -3,8 +3,7 @@ #include #include - -#define new_ast new_solver_ast +#define new_ast new_solver_ast smt_convt *create_new_z3_slhv_solver( const optionst &options, @@ -43,22 +42,22 @@ smt_convt *create_new_z3_slhv_solver( return conv; } -smt_astt z3_slhv_smt_ast::update(smt_convt *ctx, - smt_astt value, - unsigned int idx, - expr2tc idx_expr) - const { - log_status("slhv_smt does not support update"); - return nullptr; - } -smt_astt z3_slhv_smt_ast::project(smt_convt *ctx, unsigned int elem)const { - log_status("slhv_smt does not support project"); - return nullptr; -} -void z3_slhv_smt_ast::dump() const { - std::string print_str = a.to_string(); - log_status("{}\n sort is {}", print_str, a.get_sort().to_string()); -} +// smt_astt z3_slhv_smt_ast::update(smt_convt *ctx, +// smt_astt value, +// unsigned int idx, +// expr2tc idx_expr) +// const { +// log_status("slhv_smt does not support update"); +// return nullptr; +// } +// smt_astt z3_slhv_smt_ast::project(smt_convt *ctx, unsigned int elem) const { +// log_status("slhv_smt does not support project"); +// return nullptr; +// } +// void z3_slhv_smt_ast::dump() const { +// std::string print_str = a.to_string(); +// log_status("{}\n sort is {}", print_str, a.get_sort().to_string()); +// } z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here @@ -192,15 +191,15 @@ const std::string z3_slhv_convt::solver_text() { // heap terms smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { z3::expr pt = z3::points_to( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a ); return new_ast(pt, this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b){ z3::expr h = z3::uplus( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a ); return new_ast(h, this->mk_intheap_sort()); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 9f237ffa..a64bad17 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -7,22 +7,22 @@ #include #include -class z3_slhv_smt_ast : public solver_smt_ast -{ -public: - using solver_smt_ast::solver_smt_ast; - ~z3_slhv_smt_ast() override = default; - - smt_astt update(smt_convt *ctx, - smt_astt value, - unsigned int idx, - expr2tc idx_expr) - const override; - - smt_astt project(smt_convt *ctx, unsigned int elem) const override; - - void dump() const override; -}; +// class z3_slhv_smt_ast : public solver_smt_ast +// { +// public: +// using solver_smt_ast::solver_smt_ast; +// ~z3_slhv_smt_ast() override = default; + +// smt_astt update(smt_convt *ctx, +// smt_astt value, +// unsigned int idx, +// expr2tc idx_expr) +// const override; + +// smt_astt project(smt_convt *ctx, unsigned int elem) const override; + +// void dump() const override; +// }; class z3_slhv_convt : public z3_convt { public: From e4c7df964d76495f0cc8c11f4717c7dba1cea771 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 12 Jul 2024 14:21:54 +0800 Subject: [PATCH 003/126] finish encoding(pending for locadd) --- src/solvers/smt/smt_conv.cpp | 100 ++++------------------ src/solvers/smt/smt_conv.h | 29 ++++--- src/solvers/z3-slhv/z3_slhv_conv.cpp | 123 +++++++++++++++++++++++---- src/solvers/z3-slhv/z3_slhv_conv.h | 24 +++--- 4 files changed, 153 insertions(+), 123 deletions(-) diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 5149eb5a..03275acf 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -332,51 +332,19 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) smt_astt a; switch (expr->expr_id) { - case expr2t::points_to_id: { - assert(args.size() == 2); - a = mk_pt(args[0], args[1]); - break; - } - case expr2t::uplus_id: { - assert(args.size() >= 2); - a = args[0]; - for (int i = 1; i < args.size(); i++) { - a = mk_uplus(a, args[i]); - } - break; - } - case expr2t::locadd_id: { - assert(args.size() == 2); - a = mk_locadd(args[0], args[1]); - break; - } - case expr2t::heap_update_id: { - log_status("heap update"); - const heap_update2t& heap_upd = to_heap_update2t(expr); - smt_astt h = args[0]; - smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap")); - smt_astt adr = args[1]; - smt_astt val = args[2]; - smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val")); - // old heap state - smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(adr, v1), h1)); - assert_ast(o_state); - // new heap state - a = mk_uplus(mk_pt(adr, val), h1); - break; - } - case expr2t::heap_load_id: { - log_status("TODO: heap load"); - abort(); - } - case expr2t::heap_contains_id: { - log_status("TODO: heap contains"); - abort(); - } - case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: case expr2t::pointer_with_region_id: + case expr2t::points_to_id: + case expr2t::uplus_id: + case expr2t::locadd_id: + case expr2t::heap_update_id: + case expr2t::heap_load_id: + case expr2t::heap_contains_id: { + a = convert_slhv_opts(expr, args); + break; + } + case expr2t::constant_int_id: case expr2t::constant_fixedbv_id: case expr2t::constant_floatbv_id: @@ -1333,10 +1301,8 @@ smt_sortt smt_convt::convert_sort(const type2tc &type) switch (type->type_id) { case type2t::intheap_id: - result = mk_intheap_sort(); - break; case type2t::intloc_id: - result = mk_intloc_sort(); + result = convert_slhv_sorts(type); break; case type2t::bool_id: @@ -1461,20 +1427,7 @@ smt_astt smt_convt::convert_terminal(const expr2tc &expr) log_status("convert terminal: "); expr.get()->dump(); switch (expr->expr_id) - { - case expr2t::constant_intheap_id: { - return mk_emp(); - } - case expr2t::constant_intloc_id: { - return mk_nil(); - } - case expr2t::pointer_with_region_id: { - const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); - const symbol2t& nsym = to_symbol2t(pwr.loc_ptr); - std::string name = nsym.get_symbol_name(); - smt_sortt sort = convert_sort(nsym.type); - return mk_smt_symbol(name, sort); - } + { case expr2t::constant_int_id: { const constant_int2t &theint = to_constant_int2t(expr); @@ -3458,34 +3411,15 @@ smt_astt smt_convt::mk_isint(smt_astt a) abort(); } -smt_astt smt_convt::mk_emp() { abort(); } - -smt_astt smt_convt::mk_nil() { abort(); } - -smt_astt smt_convt::mk_pt(smt_astt a, smt_astt b) { - (void)a; - (void)b; - abort(); -} - -smt_astt smt_convt::mk_uplus(smt_astt a, smt_astt b) { - (void)a; - (void)b; - abort(); -} - -smt_astt smt_convt::mk_locadd(smt_astt a, smt_astt b) { - (void)a; - (void)b; - abort(); -} +/** Heap sorts and operators */ -smt_sortt smt_convt::mk_intheap_sort() { - log_error("Chosen solver doesn't support intheap sorts"); +smt_sortt smt_convt::convert_slhv_sorts(const type2tc &type) { + log_error("Chosen solver doesn't support inltoc sorts"); abort(); } -smt_sortt smt_convt::mk_intloc_sort() { +smt_astt smt_convt::convert_slhv_opts( + const expr2tc &expr, const std::vector& args) { log_error("Chosen solver doesn't support inltoc sorts"); abort(); } \ No newline at end of file diff --git a/src/solvers/smt/smt_conv.h b/src/solvers/smt/smt_conv.h index fd6301aa..25c67352 100644 --- a/src/solvers/smt/smt_conv.h +++ b/src/solvers/smt/smt_conv.h @@ -334,18 +334,7 @@ class smt_convt virtual smt_astt mk_real2int(smt_astt a); virtual smt_astt mk_int2real(smt_astt a); virtual smt_astt mk_isint(smt_astt a); - - // SLHV mk_operators - virtual smt_astt mk_emp(); - virtual smt_astt mk_nil(); - virtual smt_astt mk_pt(smt_astt a, smt_astt b); - virtual smt_astt mk_uplus(smt_astt a, smt_astt b); - virtual smt_astt mk_locadd(smt_astt a, smt_astt b); - - // SLHV mk_sort - virtual smt_sortt mk_intheap_sort(); - virtual smt_sortt mk_intloc_sort(); - + /** Create an integer or SBV/UBV sort */ smt_sortt mk_int_bv_sort(std::size_t width) { @@ -549,6 +538,22 @@ class smt_convt /** @} */ + /** @{ + * @name SLHV operations solver-converter API. */ + + /** + * @param expr An SLHV sort expression to convert to an SMT AST. + * @return An AST representing the sort in the expression. */ + virtual smt_sortt convert_slhv_sorts(const type2tc &type); + + /** + * @param expr An SLHV expression to convert to an SMT AST. + * @return An AST representing the SLHV operation in the expression. */ + virtual smt_astt + convert_slhv_opts(const expr2tc &expr, const std::vector& args); + + /** @} */ + /** @{ * @name Internal foo. */ diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 39b5cf45..5ef039d5 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -188,7 +188,15 @@ const std::string z3_slhv_convt::solver_text() { // } -// heap terms +// constant and operators +smt_astt z3_slhv_convt::mk_emp() { + z3::expr emp = z3_ctx.emp_const(); + return new_ast(emp, this->mk_intheap_sort()); +} +smt_astt z3_slhv_convt::mk_nil() { + z3::expr nil = z3_ctx.nil_const(); + return new_ast(nil, this->mk_intloc_sort()); +} smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { z3::expr pt = z3::points_to( to_solver_smt_ast(a)->a, @@ -196,25 +204,30 @@ smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { ); return new_ast(pt, this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b){ +smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { z3::expr h = z3::uplus( to_solver_smt_ast(a)->a, to_solver_smt_ast(b)->a ); return new_ast(h, this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_emp() { - z3::expr emp = z3_ctx.emp_const(); - return new_ast(emp, this->mk_intheap_sort()); +smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { + z3::expr sh = z3::subh( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ); + return new_ast(sh, this->boolean_sort); +} +smt_astt z3_slhv_convt::mk_disjh(smt_astt a, smt_astt b) { + z3::expr sh = z3::disjh( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ); + return new_ast(sh, this->boolean_sort); } -// loc terms smt_astt z3_slhv_convt::mk_locadd(smt_astt loc, smt_astt i) { } -smt_astt z3_slhv_convt::mk_nil() { - z3::expr nil = z3_ctx.nil_const(); - return new_ast(nil, this->mk_intloc_sort()); -} bool z3_slhv_convt::get_bool(smt_astt a){ log_error("Can't get boolean value yet, solver not plugged."); @@ -225,14 +238,6 @@ BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed){ abort(); } -// smt_sortt z3_slhv_convt::mk_bool_sort() { -// return new solver_smt_sort(SMT_SORT_BOOL, z3_ctx.bool_sort()); -// } - -// smt_sortt z3_slhv_convt::mk_int_sort() { -// return new solver_smt_sort(SMT_SORT_INT, z3_ctx.int_sort()); -// } - smt_sortt z3_slhv_convt::mk_intheap_sort() { return new solver_smt_sort(SMT_SORT_INTHEAP, z3_ctx.intheap_sort()); } @@ -246,6 +251,88 @@ smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) { return mk_intloc_sort(); } +smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { + switch (type->type_id) { + case type2t::intheap_id: return mk_intheap_sort(); + case type2t::intloc_id: return mk_intloc_sort(); + default: { + log_error("Unexpected type for SLHV"); + abort(); + } + } +} + +smt_astt +z3_slhv_convt::convert_slhv_opts( + const expr2tc &expr, const std::vector& args) { + switch (expr->expr_id) { + case expr2t::constant_intheap_id: return mk_emp(); + case expr2t::constant_intloc_id: return mk_nil(); + case expr2t::pointer_with_region_id: { + const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); + const symbol2t& nsym = to_symbol2t(pwr.loc_ptr); + return mk_smt_symbol(nsym.get_symbol_name(), mk_intloc_sort()); + } + case expr2t::points_to_id: { + assert(args.size() == 2); + return mk_pt(args[0], args[1]); + } + case expr2t::uplus_id: { + assert(args.size() >= 2); + smt_astt h = args[0]; + for (int i = 1; i < args.size(); i++) { + h = mk_uplus(h, args[i]); + } + return h; + } + case expr2t::locadd_id: { + assert(args.size() == 2); + return mk_locadd(args[0], args[1]); + } + case expr2t::heap_update_id: { + const heap_update2t& heap_upd = to_heap_update2t(expr); + smt_astt h = args[0]; + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap")); + smt_astt adr = args[1]; + smt_astt val = args[2]; + smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val")); + // current heap state + smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(adr, v1), h1)); + assert_ast(o_state); + // new heap state + return mk_uplus(mk_pt(adr, val), h1); + } + case expr2t::heap_load_id: { + const heap_load2t& heap_load = to_heap_load2t(expr); + // TODO: fix v1 sort + smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")); + //current heap state + assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); + return v1; + } + case expr2t::heap_contains_id: { + const heap_contains2t& heap_ct = to_heap_contains2t(expr); + assert(heap_ct.byte_len >= 1); + smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val"))); + for (int i = 1; false && i < heap_ct.byte_len; i++) { + sh = mk_uplus( + sh, + mk_pt( + mk_add(args[1], mk_smt_int(BigInt(i))), + // TODO: fix sort + mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")) + ) + ); + } + return mk_subh(sh, args[0]); + } + default: { + log_status("Invalid SLHV operations!!!"); + abort(); + } + } +} + // smt_astt z3_slhv_convt::convert_ast_slhv(const expr2tc &expr) { // log_status("== convert ast slhv"); // expr->dump(); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index a64bad17..8c452f43 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -37,13 +37,14 @@ class z3_slhv_convt : public z3_convt { resultt dec_solve() override; const std::string solver_text() override; - // heap terms - smt_astt mk_pt(smt_astt a, smt_astt b) override; - smt_astt mk_uplus(smt_astt a, smt_astt b) override; - smt_astt mk_emp() override; - // loc terms - smt_astt mk_locadd(smt_astt loc, smt_astt i) override; - smt_astt mk_nil() override; + // constant and operators + smt_astt mk_emp(); + smt_astt mk_nil(); + smt_astt mk_pt(smt_astt a, smt_astt b); + smt_astt mk_uplus(smt_astt a, smt_astt b); + smt_astt mk_subh(smt_astt a, smt_astt b); + smt_astt mk_disjh(smt_astt a, smt_astt b); + smt_astt mk_locadd(smt_astt loc, smt_astt i); // value obtaining from solver, not supported here @@ -51,11 +52,14 @@ class z3_slhv_convt : public z3_convt { BigInt get_bv(smt_astt a, bool is_signed) override; // sort making - smt_sortt mk_intheap_sort() override; - smt_sortt mk_intloc_sort() override; - + smt_sortt mk_intheap_sort(); + smt_sortt mk_intloc_sort(); smt_sortt mk_struct_sort(const type2tc &type) override; + smt_sortt convert_slhv_sorts(const type2tc &type) override; + smt_astt + convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; + private: std::vector assertions; }; From f4d7d55cded30e5e0333aa2c17587a5675fc67d8 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 12 Jul 2024 16:50:33 +0800 Subject: [PATCH 004/126] encoding and dump smt2 --- src/esbmc/bmc.cpp | 12 ++--- src/solvers/z3-slhv/z3_slhv_conv.cpp | 74 ++++++++++++++++------------ src/solvers/z3-slhv/z3_slhv_conv.h | 5 +- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 29455ac8..d3795ce9 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -655,12 +655,12 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); - log_status("smt_convt created"); - if (options.get_bool_option("z3-slhv")) { - show_vcc(*eq); - generate_smt_from_equation(*runtime_solver, *eq); - return smt_convt::P_SMTLIB; - } + // log_status("smt_convt created"); + // if (options.get_bool_option("z3-slhv")) { + // show_vcc(*eq); + // generate_smt_from_equation(*runtime_solver, *eq); + // return smt_convt::P_SMTLIB; + // } } // if (!options.get_bool_option("smt-during-symex") && options.get_bool_option("z3-slhv")) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 5ef039d5..bc78d7ba 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -59,9 +59,11 @@ smt_convt *create_new_z3_slhv_solver( // log_status("{}\n sort is {}", print_str, a.get_sort().to_string()); // } -z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : z3_convt(_ns, _options) { +z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) + : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here int_encoding = true; + solver = z3::solver(z3_ctx); log_status("z3_slhv_convt created"); } @@ -75,9 +77,9 @@ z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } // } -void z3_slhv_convt::assert_ast(smt_astt a) { - this->assertions.push_back(a); -} +// void z3_slhv_convt::assert_ast(smt_astt a) { +// this->assertions.push_back(a); +// } smt_convt::resultt z3_slhv_convt::dec_solve() { return P_SMTLIB; @@ -190,43 +192,51 @@ const std::string z3_slhv_convt::solver_text() { // constant and operators smt_astt z3_slhv_convt::mk_emp() { - z3::expr emp = z3_ctx.emp_const(); - return new_ast(emp, this->mk_intheap_sort()); + return new_ast(z3_ctx.emp_const(), this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_nil() { - z3::expr nil = z3_ctx.nil_const(); - return new_ast(nil, this->mk_intloc_sort()); + return new_ast(z3_ctx.nil_const(), this->mk_intloc_sort()); } smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { - z3::expr pt = z3::points_to( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a - ); - return new_ast(pt, this->mk_intheap_sort()); + return new_ast( + z3::points_to( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ), + this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { - z3::expr h = z3::uplus( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a - ); - return new_ast(h, this->mk_intheap_sort()); + return new_ast( + z3::uplus( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ), + this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { - z3::expr sh = z3::subh( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a - ); - return new_ast(sh, this->boolean_sort); + return new_ast( + z3::subh( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ), + this->boolean_sort); } smt_astt z3_slhv_convt::mk_disjh(smt_astt a, smt_astt b) { - z3::expr sh = z3::disjh( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a - ); - return new_ast(sh, this->boolean_sort); + return new_ast( + z3::disjh( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ), + this->boolean_sort); } -smt_astt z3_slhv_convt::mk_locadd(smt_astt loc, smt_astt i) { - +smt_astt z3_slhv_convt::mk_locadd(smt_astt a, smt_astt b) { + return new_ast( + z3::locadd( + to_solver_smt_ast(a)->a, + to_solver_smt_ast(b)->a + ), + this->mk_intloc_sort() + ); } bool z3_slhv_convt::get_bool(smt_astt a){ @@ -314,11 +324,11 @@ z3_slhv_convt::convert_slhv_opts( const heap_contains2t& heap_ct = to_heap_contains2t(expr); assert(heap_ct.byte_len >= 1); smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val"))); - for (int i = 1; false && i < heap_ct.byte_len; i++) { + for (int i = 1; i < heap_ct.byte_len; i++) { sh = mk_uplus( sh, mk_pt( - mk_add(args[1], mk_smt_int(BigInt(i))), + mk_locadd(args[1], mk_smt_int(BigInt(i))), // TODO: fix sort mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")) ) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 8c452f43..b40e4ff6 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -33,7 +33,7 @@ class z3_slhv_convt : public z3_convt { // TODO slhv: move to the api later, currently we use the smt-lib2 string translation // interfaces of smt_convt need implementation - void assert_ast(smt_astt a) override; + // void assert_ast(smt_astt a) override; resultt dec_solve() override; const std::string solver_text() override; @@ -44,8 +44,7 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_uplus(smt_astt a, smt_astt b); smt_astt mk_subh(smt_astt a, smt_astt b); smt_astt mk_disjh(smt_astt a, smt_astt b); - smt_astt mk_locadd(smt_astt loc, smt_astt i); - + smt_astt mk_locadd(smt_astt a, smt_astt b); // value obtaining from solver, not supported here bool get_bool(smt_astt a) override; From 596fde0287dd78de9c2fa31fa274774805ce0219 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Tue, 16 Jul 2024 12:12:16 +0800 Subject: [PATCH 005/126] add tests --- mk_cmake.py | 2 +- tests/CMakeCache.txt | 336 ++++++++ .../CMakeFiles/3.22.1/CMakeCXXCompiler.cmake | 83 ++ .../3.22.1/CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 15992 bytes tests/CMakeFiles/3.22.1/CMakeSystem.cmake | 15 + .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ++++++++++++++++++ tests/CMakeFiles/3.22.1/CompilerIdCXX/a.out | Bin 0 -> 16096 bytes .../CMakeDirectoryInformation.cmake | 16 + tests/CMakeFiles/CMakeOutput.log | 279 ++++++ tests/CMakeFiles/Makefile.cmake | 48 ++ tests/CMakeFiles/Makefile2 | 112 +++ tests/CMakeFiles/TargetDirectories.txt | 3 + tests/CMakeFiles/cmake.check_cache | 1 + .../cpp_example.dir/DependInfo.cmake | 19 + tests/CMakeFiles/cpp_example.dir/build.make | 111 +++ .../cpp_example.dir/cmake_clean.cmake | 11 + .../cpp_example.dir/compiler_depend.internal | 237 ++++++ .../cpp_example.dir/compiler_depend.make | 700 ++++++++++++++++ .../cpp_example.dir/compiler_depend.ts | 2 + tests/CMakeFiles/cpp_example.dir/depend.make | 2 + .../CMakeFiles/cpp_example.dir/example.cpp.o | Bin 0 -> 69080 bytes .../cpp_example.dir/example.cpp.o.d | 184 ++++ tests/CMakeFiles/cpp_example.dir/flags.make | 10 + tests/CMakeFiles/cpp_example.dir/link.txt | 1 + .../CMakeFiles/cpp_example.dir/progress.make | 3 + tests/CMakeFiles/progress.marks | 1 + tests/CMakeLists.txt | 46 + tests/Makefile | 181 ++++ tests/cmake_install.cmake | 54 ++ tests/cpp_example | Bin 0 -> 44888 bytes tests/example.cpp | 50 ++ 31 files changed, 3297 insertions(+), 1 deletion(-) create mode 100644 tests/CMakeCache.txt create mode 100644 tests/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake create mode 100755 tests/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin create mode 100644 tests/CMakeFiles/3.22.1/CMakeSystem.cmake create mode 100644 tests/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100755 tests/CMakeFiles/3.22.1/CompilerIdCXX/a.out create mode 100644 tests/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 tests/CMakeFiles/CMakeOutput.log create mode 100644 tests/CMakeFiles/Makefile.cmake create mode 100644 tests/CMakeFiles/Makefile2 create mode 100644 tests/CMakeFiles/TargetDirectories.txt create mode 100644 tests/CMakeFiles/cmake.check_cache create mode 100644 tests/CMakeFiles/cpp_example.dir/DependInfo.cmake create mode 100644 tests/CMakeFiles/cpp_example.dir/build.make create mode 100644 tests/CMakeFiles/cpp_example.dir/cmake_clean.cmake create mode 100644 tests/CMakeFiles/cpp_example.dir/compiler_depend.internal create mode 100644 tests/CMakeFiles/cpp_example.dir/compiler_depend.make create mode 100644 tests/CMakeFiles/cpp_example.dir/compiler_depend.ts create mode 100644 tests/CMakeFiles/cpp_example.dir/depend.make create mode 100644 tests/CMakeFiles/cpp_example.dir/example.cpp.o create mode 100644 tests/CMakeFiles/cpp_example.dir/example.cpp.o.d create mode 100644 tests/CMakeFiles/cpp_example.dir/flags.make create mode 100644 tests/CMakeFiles/cpp_example.dir/link.txt create mode 100644 tests/CMakeFiles/cpp_example.dir/progress.make create mode 100644 tests/CMakeFiles/progress.marks create mode 100644 tests/CMakeLists.txt create mode 100644 tests/Makefile create mode 100644 tests/cmake_install.cmake create mode 100755 tests/cpp_example create mode 100644 tests/example.cpp diff --git a/mk_cmake.py b/mk_cmake.py index 5a7e8d62..b0d2e835 100644 --- a/mk_cmake.py +++ b/mk_cmake.py @@ -1,4 +1,4 @@ import os import sys -os.system("cd build && cmake .. -GNinja -DBUILD_TESTING=On -DENABLE_REGRESSION=On $ESBMC_CLANG -DENABLE_Z3=On -DZ3_DIR=/../../../z3-release -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../../release ") +os.system("cd build && rm -rf * && cmake .. -GNinja -DBUILD_TESTING=On -DENABLE_REGRESSION=On $ESBMC_CLANG -DENABLE_Z3_SLHV=On -DZ3_DIR=/home/clexma/Desktop/fox3/slhv/Z3-slhv/z3_slhv_lib -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../../release ") diff --git a/tests/CMakeCache.txt b/tests/CMakeCache.txt new file mode 100644 index 00000000..3777c9d7 --- /dev/null +++ b/tests/CMakeCache.txt @@ -0,0 +1,336 @@ +# This is the CMakeCache file. +# For build in directory: /home/clexma/Desktop/fox3/tests +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-11 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-11 + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Z3_C_EXAMPLE + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Z3_C_EXAMPLE_BINARY_DIR:STATIC=/home/clexma/Desktop/fox3/tests + +//Value Computed by CMake +Z3_C_EXAMPLE_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Z3_C_EXAMPLE_SOURCE_DIR:STATIC=/home/clexma/Desktop/fox3/tests + +//The directory containing a CMake configuration file for Z3. +Z3_DIR:PATH=/usr/local/lib/cmake/z3 + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/clexma/Desktop/fox3/tests +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Test CMAKE_HAVE_LIBC_PTHREAD +CMAKE_HAVE_LIBC_PTHREAD:INTERNAL=1 +//Have include pthread.h +CMAKE_HAVE_PTHREAD_H:INTERNAL=1 +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/clexma/Desktop/fox3/tests +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding Threads +FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] + diff --git a/tests/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake b/tests/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake new file mode 100644 index 00000000..345e9307 --- /dev/null +++ b/tests/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "11.4.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-11") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-11") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/11;/usr/include/x86_64-linux-gnu/c++/11;/usr/include/c++/11/backward;/usr/lib/gcc/x86_64-linux-gnu/11/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/11;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/tests/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin b/tests/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..cfa527b53452d63fe64b6a8e2d060ddc5e29a3a6 GIT binary patch literal 15992 zcmeHOYit}>6~4Q666fh{noyIZ%}^TT5InIR$2dlA){nJk!LK9^1VWh1ddK#VeYmr; z#15f}lorK=pim(~k&r@p6bXJb5+VXo*ea-q@=)_5B&dG^p(u!ix;&RLJg z>z1d4&>U;`-1FV@-FxTUJL@|$XO6{syThT7V5txf3$&sU7l~3u%R8w6Dk@sUO8CBC zY!HjVu9TQtA9WSfx^guiWZUxI(%>{juhF zVodPULhY9IP5mu24-tw#YYMN}nz9njOcgFYzO9xoBL zu}}2Dc%0nz#gJlF)*`kPJ}4cr%Qru~wDafRx&Fk_OXkngD_YMk|HgZ+7a9{U-Mae7 zz72NHPgyIp2*N7S) zj>rEXeEhNt0HsVjhXB6^qpP?Kj5P{Id9_$o`n`LbM1?p8IwET3jq`r;-+Yhj_)+o~ zx;{K%=p$CfNLfcrFkt}=>p91;9X)MW8G$ygpJt)Qhx+uSX`7=~&N1zwzRpxOV-6XK z6!6TX;TS+i<fCh?dbKv=>5w&{bW3oNKp9DlZ zz32&4J7%1<(Di$<3|%iRUaQ`C933x`27gQXZ%?4wd{>*A)}H(QPVKpw3N7@!cImFO z1{&Bz4OA7cjZ|-haWNmqd%O*+MSja(?L=D`i`vx7&I;{R+hQL?DPj5P={9K?H&b z1Q7@#5Jcb~j{rX3c|D2ucMr7Y;E7gtL{E-8_Wt^o1783B_&|4})tS^yJ8LHQ+wl&) zr#}|&>Teg)Px2F!j;UvDc;vOeH$F7f8`ER`UGesQ@R0RJ!rBjc2uKL6uXqL?DPj5P={9K?MFcBEb20oPWo;b@HMI zhPZ-u=vJX3>6zlJqcd6-A>0=KG<{ zQ2jF36yGJioOBK8wWL{b?q7lO`zRe;3{t~9jsg)lXO`Q0fN=KvYtbDq#7RPT$yTU6 zcrq-HhvNvBrqZsY`oECPi4s zzS%zxg^(wom*)%fe?xG$fY&SgAB6(;%jXN@C#C+Uw;2MH%7YGA-25fR4;fGhzi3&m}d^j|Fo-$ITaRc@Tyz&|Xi1)t~azC*Ti zpWyYuc(=siXngB$0C3E-KBKUws}t0YKkqvu@iz%RUzzn7;9&u0yKjC!0eHFm^rr#$ zbt#+riNxpUm0twBTps!hgo`MT#MM`1J99C#egk;9yz<+!o%wm|F9KdJ-~2W5_s3^3 z+@3>!f4=#0z?J#K5t{&iunaEt4BJkFnuSbpxZ9>X#;5=w=j2C5)L}83jIKLreHhcx zbC`pk)kjm=gptydPS(!pMt(vJXVc>;(=n53eR&Vefwy$Swhg!`m~re$F=88OQ%~m8 z=}Dk?EFCI_2YMTtt;|SP_uPv_w9!Rp?=b2K zYZO!BEh8iAcSx3}K4m#h%JjIjNDqh#46b{3d!M{JsY9MU9ta*|E~}3jnIvZCcfG&A zy)WJgD7>Jd$21~nUAqB-M1H)niPWCnfsXcGeW1I0Pi#mZYVUx1oGRCA0L-dGa&Y`J`Q1-c9_L*qu;8iwKE>liA$T_IFh z`e|6v<<72u8pC}PobvD+=ZgP5INmo=we;mO>bJrN_cqL5=zTBrMdAI7YYEW|1ux(K z-WT2{_X^&R_X_?$_44`uIcvr13}rw6eSrNL_C`E@-Vd_Yh|l{$|M(54$Gsr)dB4bd z5Q7VXW5go!d7ozihFcKk^Zt`H?>E6k3N^>3cmztg_hUZq_gM4%@%Y(~^`pSYy(HVb zpJZK6J^9Da12_!@j4AVZf6KZ+j@-Zh_|HN;9uwD>{?F3?Ti(}GGxO%}3qHO=Jl4K{ z+y3UoQ$Bt@5m>(w|LZ<}lnAVoz6tZUcizY6eGhBC?g2L`{`GqSQ0#)^FBIt}SbvI4 zR$R@tyDyyO^L~jnzyHYo{{DXo72f^})B)?yFp)IRKf_m`fO|;3F5&$wzbEPUXPfnP z;8uJ1ynmjl0}zD$Tx-^5{1vFcwa5LJ_K~W~DB!_?;QB{l9?#=f0Yew&^Zv206}^Rs z%J11P=ChuGDlfl8sCPNs54XTPw(mj#G47xDZ4u)8{poO+E-C;(jND5&^S6``x4?X_ zF0DO}Z>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/tests/CMakeFiles/3.22.1/CompilerIdCXX/a.out b/tests/CMakeFiles/3.22.1/CompilerIdCXX/a.out new file mode 100755 index 0000000000000000000000000000000000000000..9944be481759fba2110a3ba6af6d9c647c7ea1a9 GIT binary patch literal 16096 zcmeHOYit}>6~4Pk8izc*NgEQ9(k!K|5?W7e$4O0)$vXBrV`Rr^;*>yYMq}^VyJ8<^ zcb3`_v_XMllLR#a0Y8FNwGv1mBoL^m6)jE+MX3r(evwKDg-6vOrLB3J5@k8(-t(=; z({&KgAN-hOdCooGdE7ha-kH5KbMM2+zMg0#qCiX32Ng?+m_ZVvcWxzsPG~kpstHS4Y=HSiBDIEP@vn!MR4MzaMs zmpzsykrF)Ols&iPIe9l*P%LwPcd31Sy?eWyR;$(8Su5{oQ%>(-zmrOr(qq}Omo5$V zcjbzO^q@PO<8Wj7VnM<=#>XE37wOix8f=JsN|R5oQ-aMpSJG4_KqU!gQd>5gXz z*Dc;A8@r7Gyd-!$fPY@_tpWT?f;R{7?+AWrkJ7|r zhx-b2*@yEO16}dq7~8Cy_2E2jL32J_-*2G^d6Zh5VD z`r^mz>EGHXem{F)FxfKGa^61O@gfDNt}m12Uq-FQEuYo#2tP-NeR|o`%-%oet*5H* z=Q35jqI$V;%W*b*UO3sG(e^vPz--%fdwSMB_xc|D+}sj7@`8Qwx_1i&xKjc&R4>D*I%|O(a~|R;^aAr0DR14igz7-v$1Ec#xDF z=rH+BfBLFDUAg?Tq-uP2CX&2H_|x@pV|aS~PuEa3 zpIjQNS)Z+EO;JwO!%rr!4N>>h`mWYn+@z4g41^g7GZ1DV%s`ldFau!*!VH8N2s037 zAk4s9Gr-@!ZbZHNdj@uo6!YWRT)K3WzDf=)v|gZhKAA3+v&F*EW=$CyjF6!#1R$u+S@qFt+RicV3@41^SBAk09RfiMGM2Eq)483;2FW+2Q!n1Q!9 z16Z$!^@&&ms2^Uas#T~?)-SFW`A4$O@m(Tg9pq+_@d&d?WUPne=N=~L|9ZVzWcjmr-Q9p8F*xKi*caeC0FC;X*PZ)&T$Hc3#BlL8Sajii* ze2V_LUR+ner>GE7H!EBxz`sd_dhLH!+s9NQZY*03qX_lwFAyG~mE2SB5knuV7ysAV zp01X_czIR(t*x!YN0>LY{X1*d5%3r#WE}(_Zz4SIlTkdP@eN8PfEeCOcuZ}mD%@{?-!JyTI3qeftmb)%@U_tm3ga4@hZ(1uRoozQnW`^pe1i(EzdkE?a6R=i zgvV%{Boc^h_ydHmqw$cC@uuG)k?J{#6BB#f4=zX?j5kF4mBiU5_g($Yh?KwKICNe? z``0A?)-aJ}p!d@c1?JYnq6esyT117v0QQ3%{eKrSSmYiWkT^g#$4Jy4s z7QA;L>$s(oJL#kgUTIQ|mfU>WNmcUsNpkT?4q18&OuPEskEgqi9O;rbnY}4%WPDsX zAMI;t%@#(Bcymc{dJcB>C!OT}Zin^}bbn-jXMb-O!Sw3WN!p^dyALX7U*Evq&OT?L zr{_>|&>8I9+m|Gd;J$_gb~F6D9SrG|>$yswB}HMuY-b>0;ob%(RW3RidOgbf9(o7J zDwQobm2x_z^r_(8s*!STVXWegrJc9FH&v8J@xdEjs%*GimWuVZ49B637LpDfz7{a} ziuMM(E*5V7sHKEAc<8<|P38B$N?GN}yyp%R_ezFmP|6l)-^aMJ3Pmq%jTI`^c&Rv^ zE_staXt~N z!1(vr?~nNacpQepgZ>{T{BJY|L;ErB1V{atch>G}63->hb58hUUJCxG*l`;F8CDb{1nXpCrHV2O!#A736A+X+7CPMhsdAjtdKEp1#gzhgY8F~PE&z% z3V+O_!7-0U{lWA9D*5s`L0|h_k>3|QKah#0VE=ucP``g%{J=#N@A;oC;ExCVn?(T* zI|P6X{_TK&LKNV~0v!fF#QR>rAM+Y;JYT^+c>X^Wf8<}q#Zvfr5y1q8sD4Z(ZX*0& z5(DsiYL=!DtpDc(`~By{AN9sQv|#u27)> literal 0 HcmV?d00001 diff --git a/tests/CMakeFiles/CMakeDirectoryInformation.cmake b/tests/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 00000000..596d2f4c --- /dev/null +++ b/tests/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/clexma/Desktop/fox3/tests") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/clexma/Desktop/fox3/tests") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/tests/CMakeFiles/CMakeOutput.log b/tests/CMakeFiles/CMakeOutput.log new file mode 100644 index 00000000..c01c588b --- /dev/null +++ b/tests/CMakeFiles/CMakeOutput.log @@ -0,0 +1,279 @@ +The system is: Linux - 6.5.0-1025-oem - x86_64 +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /usr/bin/c++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/home/clexma/Desktop/fox3/tests/CMakeFiles/3.22.1/CompilerIdCXX/a.out" + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_a48a9/fast && /usr/bin/gmake -f CMakeFiles/cmTC_a48a9.dir/build.make CMakeFiles/cmTC_a48a9.dir/build +gmake[1]: Entering directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o +/usr/bin/c++ -v -o CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/' + /usr/lib/gcc/x86_64-linux-gnu/11/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_a48a9.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccsnvSLO.s +GNU C++17 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu) + compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/11" +ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/include/c++/11 + /usr/include/x86_64-linux-gnu/c++/11 + /usr/include/c++/11/backward + /usr/lib/gcc/x86_64-linux-gnu/11/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +GNU C++17 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu) + compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: d591828bb4d392ae8b7b160e5bb0b95f +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/' + as -v --64 -o CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccsnvSLO.s +GNU assembler version 2.38 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.38 +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.' +Linking CXX executable cmTC_a48a9 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_a48a9.dir/link.txt --verbose=1 +/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_a48a9 +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_a48a9' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a48a9.' + /usr/lib/gcc/x86_64-linux-gnu/11/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/11/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper -plugin-opt=-fresolution=/tmp/ccQLd5PL.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_a48a9 /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_a48a9' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a48a9.' +gmake[1]: Leaving directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' + + + +Parsed CXX implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/usr/include/c++/11] + add: [/usr/include/x86_64-linux-gnu/c++/11] + add: [/usr/include/c++/11/backward] + add: [/usr/lib/gcc/x86_64-linux-gnu/11/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/include/c++/11] ==> [/usr/include/c++/11] + collapse include dir [/usr/include/x86_64-linux-gnu/c++/11] ==> [/usr/include/x86_64-linux-gnu/c++/11] + collapse include dir [/usr/include/c++/11/backward] ==> [/usr/include/c++/11/backward] + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/11/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/11/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/11;/usr/include/x86_64-linux-gnu/c++/11;/usr/include/c++/11/backward;/usr/lib/gcc/x86_64-linux-gnu/11/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_a48a9/fast && /usr/bin/gmake -f CMakeFiles/cmTC_a48a9.dir/build.make CMakeFiles/cmTC_a48a9.dir/build] + ignore line: [gmake[1]: Entering directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp'] + ignore line: [Building CXX object CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/11/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_a48a9.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccsnvSLO.s] + ignore line: [GNU C++17 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 11.4.0 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.1 isl version isl-0.24-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/11"] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/include/c++/11] + ignore line: [ /usr/include/x86_64-linux-gnu/c++/11] + ignore line: [ /usr/include/c++/11/backward] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/11/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++17 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 11.4.0 GMP version 6.2.1 MPFR version 4.1.0 MPC version 1.2.1 isl version isl-0.24-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: d591828bb4d392ae8b7b160e5bb0b95f] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccsnvSLO.s] + ignore line: [GNU assembler version 2.38 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.38] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.'] + ignore line: [Linking CXX executable cmTC_a48a9] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_a48a9.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_a48a9 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_a48a9' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_a48a9.'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/11/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/11/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper -plugin-opt=-fresolution=/tmp/ccQLd5PL.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_a48a9 /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/11/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/11/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccQLd5PL.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_a48a9] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/11] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/11] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/11/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../..] + arg [CMakeFiles/cmTC_a48a9.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/11] ==> [/usr/lib/gcc/x86_64-linux-gnu/11] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/11/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/11;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + +Determining if the include file pthread.h exists passed with the following output: +Change Dir: /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_344b0/fast && /usr/bin/gmake -f CMakeFiles/cmTC_344b0.dir/build.make CMakeFiles/cmTC_344b0.dir/build +gmake[1]: Entering directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_344b0.dir/CheckIncludeFile.cxx.o +/usr/bin/c++ -o CMakeFiles/cmTC_344b0.dir/CheckIncludeFile.cxx.o -c /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp/CheckIncludeFile.cxx +Linking CXX executable cmTC_344b0 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_344b0.dir/link.txt --verbose=1 +/usr/bin/c++ CMakeFiles/cmTC_344b0.dir/CheckIncludeFile.cxx.o -o cmTC_344b0 +gmake[1]: Leaving directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' + + + +Performing C++ SOURCE FILE Test CMAKE_HAVE_LIBC_PTHREAD succeeded with the following output: +Change Dir: /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_c18bd/fast && /usr/bin/gmake -f CMakeFiles/cmTC_c18bd.dir/build.make CMakeFiles/cmTC_c18bd.dir/build +gmake[1]: Entering directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_c18bd.dir/src.cxx.o +/usr/bin/c++ -DCMAKE_HAVE_LIBC_PTHREAD -o CMakeFiles/cmTC_c18bd.dir/src.cxx.o -c /home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp/src.cxx +Linking CXX executable cmTC_c18bd +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_c18bd.dir/link.txt --verbose=1 +/usr/bin/c++ CMakeFiles/cmTC_c18bd.dir/src.cxx.o -o cmTC_c18bd +gmake[1]: Leaving directory '/home/clexma/Desktop/fox3/tests/CMakeFiles/CMakeTmp' + + +Source file was: +#include + +static void* test_func(void* data) +{ + return data; +} + +int main(void) +{ + pthread_t thread; + pthread_create(&thread, NULL, test_func, NULL); + pthread_detach(thread); + pthread_cancel(thread); + pthread_join(thread, NULL); + pthread_atfork(NULL, NULL, NULL); + pthread_exit(NULL); + + return 0; +} + diff --git a/tests/CMakeFiles/Makefile.cmake b/tests/CMakeFiles/Makefile.cmake new file mode 100644 index 00000000..ea6bf273 --- /dev/null +++ b/tests/CMakeFiles/Makefile.cmake @@ -0,0 +1,48 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "CMakeFiles/3.22.1/CMakeCXXCompiler.cmake" + "CMakeFiles/3.22.1/CMakeSystem.cmake" + "CMakeLists.txt" + "/usr/local/lib/cmake/z3/Z3Config.cmake" + "/usr/local/lib/cmake/z3/Z3ConfigVersion.cmake" + "/usr/local/lib/cmake/z3/Z3Targets-release.cmake" + "/usr/local/lib/cmake/z3/Z3Targets-relwithdebinfo.cmake" + "/usr/local/lib/cmake/z3/Z3Targets.cmake" + "/usr/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + "/usr/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/share/cmake-3.22/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake-3.22/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-3.22/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake-3.22/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-3.22/Modules/Platform/Linux.cmake" + "/usr/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/cpp_example.dir/DependInfo.cmake" + ) diff --git a/tests/CMakeFiles/Makefile2 b/tests/CMakeFiles/Makefile2 new file mode 100644 index 00000000..95c2d2ce --- /dev/null +++ b/tests/CMakeFiles/Makefile2 @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/clexma/Desktop/fox3/tests + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/clexma/Desktop/fox3/tests + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/cpp_example.dir/all +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/cpp_example.dir/clean +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/cpp_example.dir + +# All Build rule for target. +CMakeFiles/cpp_example.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/clexma/Desktop/fox3/tests/CMakeFiles --progress-num=1,2 "Built target cpp_example" +.PHONY : CMakeFiles/cpp_example.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/cpp_example.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/clexma/Desktop/fox3/tests/CMakeFiles 2 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/cpp_example.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/clexma/Desktop/fox3/tests/CMakeFiles 0 +.PHONY : CMakeFiles/cpp_example.dir/rule + +# Convenience name for target. +cpp_example: CMakeFiles/cpp_example.dir/rule +.PHONY : cpp_example + +# clean rule for target. +CMakeFiles/cpp_example.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/clean +.PHONY : CMakeFiles/cpp_example.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/tests/CMakeFiles/TargetDirectories.txt b/tests/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..c0eb1eab --- /dev/null +++ b/tests/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/clexma/Desktop/fox3/tests/CMakeFiles/cpp_example.dir +/home/clexma/Desktop/fox3/tests/CMakeFiles/edit_cache.dir +/home/clexma/Desktop/fox3/tests/CMakeFiles/rebuild_cache.dir diff --git a/tests/CMakeFiles/cmake.check_cache b/tests/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/tests/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/tests/CMakeFiles/cpp_example.dir/DependInfo.cmake b/tests/CMakeFiles/cpp_example.dir/DependInfo.cmake new file mode 100644 index 00000000..fa669e98 --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/DependInfo.cmake @@ -0,0 +1,19 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + "/home/clexma/Desktop/fox3/tests/example.cpp" "CMakeFiles/cpp_example.dir/example.cpp.o" "gcc" "CMakeFiles/cpp_example.dir/example.cpp.o.d" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/tests/CMakeFiles/cpp_example.dir/build.make b/tests/CMakeFiles/cpp_example.dir/build.make new file mode 100644 index 00000000..d482477e --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/build.make @@ -0,0 +1,111 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/clexma/Desktop/fox3/tests + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/clexma/Desktop/fox3/tests + +# Include any dependencies generated for this target. +include CMakeFiles/cpp_example.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include CMakeFiles/cpp_example.dir/compiler_depend.make + +# Include the progress variables for this target. +include CMakeFiles/cpp_example.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/cpp_example.dir/flags.make + +CMakeFiles/cpp_example.dir/example.cpp.o: CMakeFiles/cpp_example.dir/flags.make +CMakeFiles/cpp_example.dir/example.cpp.o: example.cpp +CMakeFiles/cpp_example.dir/example.cpp.o: CMakeFiles/cpp_example.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/clexma/Desktop/fox3/tests/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/cpp_example.dir/example.cpp.o" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/cpp_example.dir/example.cpp.o -MF CMakeFiles/cpp_example.dir/example.cpp.o.d -o CMakeFiles/cpp_example.dir/example.cpp.o -c /home/clexma/Desktop/fox3/tests/example.cpp + +CMakeFiles/cpp_example.dir/example.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/cpp_example.dir/example.cpp.i" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/clexma/Desktop/fox3/tests/example.cpp > CMakeFiles/cpp_example.dir/example.cpp.i + +CMakeFiles/cpp_example.dir/example.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/cpp_example.dir/example.cpp.s" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/clexma/Desktop/fox3/tests/example.cpp -o CMakeFiles/cpp_example.dir/example.cpp.s + +# Object files for target cpp_example +cpp_example_OBJECTS = \ +"CMakeFiles/cpp_example.dir/example.cpp.o" + +# External object files for target cpp_example +cpp_example_EXTERNAL_OBJECTS = + +cpp_example: CMakeFiles/cpp_example.dir/example.cpp.o +cpp_example: CMakeFiles/cpp_example.dir/build.make +cpp_example: /usr/local/lib/libz3.so.4.12.2.0 +cpp_example: CMakeFiles/cpp_example.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/clexma/Desktop/fox3/tests/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX executable cpp_example" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/cpp_example.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/cpp_example.dir/build: cpp_example +.PHONY : CMakeFiles/cpp_example.dir/build + +CMakeFiles/cpp_example.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/cpp_example.dir/cmake_clean.cmake +.PHONY : CMakeFiles/cpp_example.dir/clean + +CMakeFiles/cpp_example.dir/depend: + cd /home/clexma/Desktop/fox3/tests && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/clexma/Desktop/fox3/tests /home/clexma/Desktop/fox3/tests /home/clexma/Desktop/fox3/tests /home/clexma/Desktop/fox3/tests /home/clexma/Desktop/fox3/tests/CMakeFiles/cpp_example.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/cpp_example.dir/depend + diff --git a/tests/CMakeFiles/cpp_example.dir/cmake_clean.cmake b/tests/CMakeFiles/cpp_example.dir/cmake_clean.cmake new file mode 100644 index 00000000..07a3564b --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/cmake_clean.cmake @@ -0,0 +1,11 @@ +file(REMOVE_RECURSE + "CMakeFiles/cpp_example.dir/example.cpp.o" + "CMakeFiles/cpp_example.dir/example.cpp.o.d" + "cpp_example" + "cpp_example.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/cpp_example.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/tests/CMakeFiles/cpp_example.dir/compiler_depend.internal b/tests/CMakeFiles/cpp_example.dir/compiler_depend.internal new file mode 100644 index 00000000..0d8af6cd --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/compiler_depend.internal @@ -0,0 +1,237 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +CMakeFiles/cpp_example.dir/example.cpp.o + /home/clexma/Desktop/fox3/tests/example.cpp + /usr/include/stdc-predef.h + /usr/include/c++/11/iostream + /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h + /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h + /usr/include/features.h + /usr/include/features-time64.h + /usr/include/x86_64-linux-gnu/bits/wordsize.h + /usr/include/x86_64-linux-gnu/bits/timesize.h + /usr/include/x86_64-linux-gnu/sys/cdefs.h + /usr/include/x86_64-linux-gnu/bits/long-double.h + /usr/include/x86_64-linux-gnu/gnu/stubs.h + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h + /usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h + /usr/include/c++/11/ostream + /usr/include/c++/11/ios + /usr/include/c++/11/iosfwd + /usr/include/c++/11/bits/stringfwd.h + /usr/include/c++/11/bits/memoryfwd.h + /usr/include/c++/11/bits/postypes.h + /usr/include/c++/11/cwchar + /usr/include/wchar.h + /usr/include/x86_64-linux-gnu/bits/libc-header-start.h + /usr/include/x86_64-linux-gnu/bits/floatn.h + /usr/include/x86_64-linux-gnu/bits/floatn-common.h + /usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h + /usr/include/x86_64-linux-gnu/bits/wchar.h + /usr/include/x86_64-linux-gnu/bits/types/wint_t.h + /usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h + /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h + /usr/include/x86_64-linux-gnu/bits/types/__FILE.h + /usr/include/x86_64-linux-gnu/bits/types/FILE.h + /usr/include/x86_64-linux-gnu/bits/types/locale_t.h + /usr/include/x86_64-linux-gnu/bits/types/__locale_t.h + /usr/include/c++/11/exception + /usr/include/c++/11/bits/exception.h + /usr/include/c++/11/bits/exception_ptr.h + /usr/include/c++/11/bits/exception_defines.h + /usr/include/c++/11/bits/cxxabi_init_exception.h + /usr/include/c++/11/typeinfo + /usr/include/c++/11/bits/hash_bytes.h + /usr/include/c++/11/new + /usr/include/c++/11/bits/move.h + /usr/include/c++/11/type_traits + /usr/include/c++/11/bits/nested_exception.h + /usr/include/c++/11/bits/char_traits.h + /usr/include/c++/11/bits/stl_algobase.h + /usr/include/c++/11/bits/functexcept.h + /usr/include/c++/11/bits/cpp_type_traits.h + /usr/include/c++/11/ext/type_traits.h + /usr/include/c++/11/ext/numeric_traits.h + /usr/include/c++/11/bits/stl_pair.h + /usr/include/c++/11/bits/stl_iterator_base_types.h + /usr/include/c++/11/bits/stl_iterator_base_funcs.h + /usr/include/c++/11/bits/concept_check.h + /usr/include/c++/11/debug/assertions.h + /usr/include/c++/11/bits/stl_iterator.h + /usr/include/c++/11/bits/ptr_traits.h + /usr/include/c++/11/debug/debug.h + /usr/include/c++/11/bits/predefined_ops.h + /usr/include/c++/11/cstdint + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdint.h + /usr/include/stdint.h + /usr/include/x86_64-linux-gnu/bits/types.h + /usr/include/x86_64-linux-gnu/bits/typesizes.h + /usr/include/x86_64-linux-gnu/bits/time64.h + /usr/include/x86_64-linux-gnu/bits/stdint-intn.h + /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h + /usr/include/c++/11/bits/localefwd.h + /usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h + /usr/include/c++/11/clocale + /usr/include/locale.h + /usr/include/x86_64-linux-gnu/bits/locale.h + /usr/include/c++/11/cctype + /usr/include/ctype.h + /usr/include/x86_64-linux-gnu/bits/endian.h + /usr/include/x86_64-linux-gnu/bits/endianness.h + /usr/include/c++/11/bits/ios_base.h + /usr/include/c++/11/ext/atomicity.h + /usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h + /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h + /usr/include/pthread.h + /usr/include/sched.h + /usr/include/x86_64-linux-gnu/bits/types/time_t.h + /usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h + /usr/include/x86_64-linux-gnu/bits/sched.h + /usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h + /usr/include/x86_64-linux-gnu/bits/cpu-set.h + /usr/include/time.h + /usr/include/x86_64-linux-gnu/bits/time.h + /usr/include/x86_64-linux-gnu/bits/timex.h + /usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h + /usr/include/x86_64-linux-gnu/bits/types/clock_t.h + /usr/include/x86_64-linux-gnu/bits/types/struct_tm.h + /usr/include/x86_64-linux-gnu/bits/types/clockid_t.h + /usr/include/x86_64-linux-gnu/bits/types/timer_t.h + /usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h + /usr/include/x86_64-linux-gnu/bits/thread-shared-types.h + /usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h + /usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h + /usr/include/x86_64-linux-gnu/bits/struct_mutex.h + /usr/include/x86_64-linux-gnu/bits/struct_rwlock.h + /usr/include/x86_64-linux-gnu/bits/setjmp.h + /usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h + /usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h + /usr/include/x86_64-linux-gnu/bits/pthread_stack_min-dynamic.h + /usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h + /usr/include/x86_64-linux-gnu/sys/single_threaded.h + /usr/include/c++/11/bits/locale_classes.h + /usr/include/c++/11/string + /usr/include/c++/11/bits/allocator.h + /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h + /usr/include/c++/11/ext/new_allocator.h + /usr/include/c++/11/bits/ostream_insert.h + /usr/include/c++/11/bits/cxxabi_forced.h + /usr/include/c++/11/bits/stl_function.h + /usr/include/c++/11/backward/binders.h + /usr/include/c++/11/bits/range_access.h + /usr/include/c++/11/initializer_list + /usr/include/c++/11/bits/basic_string.h + /usr/include/c++/11/ext/alloc_traits.h + /usr/include/c++/11/bits/alloc_traits.h + /usr/include/c++/11/bits/stl_construct.h + /usr/include/c++/11/ext/string_conversions.h + /usr/include/c++/11/cstdlib + /usr/include/stdlib.h + /usr/include/x86_64-linux-gnu/bits/waitflags.h + /usr/include/x86_64-linux-gnu/bits/waitstatus.h + /usr/include/x86_64-linux-gnu/sys/types.h + /usr/include/endian.h + /usr/include/x86_64-linux-gnu/bits/byteswap.h + /usr/include/x86_64-linux-gnu/bits/uintn-identity.h + /usr/include/x86_64-linux-gnu/sys/select.h + /usr/include/x86_64-linux-gnu/bits/select.h + /usr/include/x86_64-linux-gnu/bits/types/sigset_t.h + /usr/include/alloca.h + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h + /usr/include/c++/11/bits/std_abs.h + /usr/include/c++/11/cstdio + /usr/include/stdio.h + /usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h + /usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h + /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h + /usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h + /usr/include/c++/11/cerrno + /usr/include/errno.h + /usr/include/x86_64-linux-gnu/bits/errno.h + /usr/include/linux/errno.h + /usr/include/x86_64-linux-gnu/asm/errno.h + /usr/include/asm-generic/errno.h + /usr/include/asm-generic/errno-base.h + /usr/include/x86_64-linux-gnu/bits/types/error_t.h + /usr/include/c++/11/bits/charconv.h + /usr/include/c++/11/bits/functional_hash.h + /usr/include/c++/11/bits/basic_string.tcc + /usr/include/c++/11/bits/locale_classes.tcc + /usr/include/c++/11/system_error + /usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h + /usr/include/c++/11/stdexcept + /usr/include/c++/11/streambuf + /usr/include/c++/11/bits/streambuf.tcc + /usr/include/c++/11/bits/basic_ios.h + /usr/include/c++/11/bits/locale_facets.h + /usr/include/c++/11/cwctype + /usr/include/wctype.h + /usr/include/x86_64-linux-gnu/bits/wctype-wchar.h + /usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h + /usr/include/c++/11/bits/streambuf_iterator.h + /usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h + /usr/include/c++/11/bits/locale_facets.tcc + /usr/include/c++/11/bits/basic_ios.tcc + /usr/include/c++/11/bits/ostream.tcc + /usr/include/c++/11/istream + /usr/include/c++/11/bits/istream.tcc + /usr/include/c++/11/sstream + /usr/include/c++/11/bits/sstream.tcc + /usr/include/c++/11/vector + /usr/include/c++/11/bits/stl_uninitialized.h + /usr/include/c++/11/bits/stl_vector.h + /usr/include/c++/11/bits/stl_bvector.h + /usr/include/c++/11/bits/vector.tcc + /usr/local/include/z3++.h + /usr/include/c++/11/cassert + /usr/include/assert.h + /usr/include/c++/11/memory + /usr/include/c++/11/bits/stl_tempbuf.h + /usr/include/c++/11/bits/stl_raw_storage_iter.h + /usr/include/c++/11/bits/align.h + /usr/include/c++/11/bit + /usr/include/c++/11/bits/uses_allocator.h + /usr/include/c++/11/bits/unique_ptr.h + /usr/include/c++/11/utility + /usr/include/c++/11/bits/stl_relops.h + /usr/include/c++/11/tuple + /usr/include/c++/11/array + /usr/include/c++/11/bits/invoke.h + /usr/include/c++/11/bits/shared_ptr.h + /usr/include/c++/11/bits/shared_ptr_base.h + /usr/include/c++/11/bits/allocated_ptr.h + /usr/include/c++/11/bits/refwrap.h + /usr/include/c++/11/ext/aligned_buffer.h + /usr/include/c++/11/ext/concurrence.h + /usr/include/c++/11/bits/shared_ptr_atomic.h + /usr/include/c++/11/bits/atomic_base.h + /usr/include/c++/11/bits/atomic_lockfree_defines.h + /usr/include/c++/11/backward/auto_ptr.h + /usr/local/include/z3.h + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdbool.h + /usr/local/include/z3_macros.h + /usr/local/include/z3_api.h + /usr/local/include/z3_ast_containers.h + /usr/local/include/z3_algebraic.h + /usr/local/include/z3_polynomial.h + /usr/local/include/z3_rcf.h + /usr/local/include/z3_fixedpoint.h + /usr/local/include/z3_optimization.h + /usr/local/include/z3_fpa.h + /usr/local/include/z3_spacer.h + /usr/lib/gcc/x86_64-linux-gnu/11/include/limits.h + /usr/lib/gcc/x86_64-linux-gnu/11/include/syslimits.h + /usr/include/limits.h + /usr/include/x86_64-linux-gnu/bits/posix1_lim.h + /usr/include/x86_64-linux-gnu/bits/local_lim.h + /usr/include/linux/limits.h + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h + /usr/include/x86_64-linux-gnu/bits/uio_lim.h + /usr/include/c++/11/functional + /usr/include/c++/11/bits/std_function.h + diff --git a/tests/CMakeFiles/cpp_example.dir/compiler_depend.make b/tests/CMakeFiles/cpp_example.dir/compiler_depend.make new file mode 100644 index 00000000..1ebbab0d --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/compiler_depend.make @@ -0,0 +1,700 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +CMakeFiles/cpp_example.dir/example.cpp.o: example.cpp \ + /usr/include/stdc-predef.h \ + /usr/include/c++/11/iostream \ + /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h \ + /usr/include/features.h \ + /usr/include/features-time64.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/bits/timesize.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/long-double.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h \ + /usr/include/c++/11/ostream \ + /usr/include/c++/11/ios \ + /usr/include/c++/11/iosfwd \ + /usr/include/c++/11/bits/stringfwd.h \ + /usr/include/c++/11/bits/memoryfwd.h \ + /usr/include/c++/11/bits/postypes.h \ + /usr/include/c++/11/cwchar \ + /usr/include/wchar.h \ + /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \ + /usr/include/x86_64-linux-gnu/bits/floatn.h \ + /usr/include/x86_64-linux-gnu/bits/floatn-common.h \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/x86_64-linux-gnu/bits/types/wint_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \ + /usr/include/x86_64-linux-gnu/bits/types/FILE.h \ + /usr/include/x86_64-linux-gnu/bits/types/locale_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/__locale_t.h \ + /usr/include/c++/11/exception \ + /usr/include/c++/11/bits/exception.h \ + /usr/include/c++/11/bits/exception_ptr.h \ + /usr/include/c++/11/bits/exception_defines.h \ + /usr/include/c++/11/bits/cxxabi_init_exception.h \ + /usr/include/c++/11/typeinfo \ + /usr/include/c++/11/bits/hash_bytes.h \ + /usr/include/c++/11/new \ + /usr/include/c++/11/bits/move.h \ + /usr/include/c++/11/type_traits \ + /usr/include/c++/11/bits/nested_exception.h \ + /usr/include/c++/11/bits/char_traits.h \ + /usr/include/c++/11/bits/stl_algobase.h \ + /usr/include/c++/11/bits/functexcept.h \ + /usr/include/c++/11/bits/cpp_type_traits.h \ + /usr/include/c++/11/ext/type_traits.h \ + /usr/include/c++/11/ext/numeric_traits.h \ + /usr/include/c++/11/bits/stl_pair.h \ + /usr/include/c++/11/bits/stl_iterator_base_types.h \ + /usr/include/c++/11/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/11/bits/concept_check.h \ + /usr/include/c++/11/debug/assertions.h \ + /usr/include/c++/11/bits/stl_iterator.h \ + /usr/include/c++/11/bits/ptr_traits.h \ + /usr/include/c++/11/debug/debug.h \ + /usr/include/c++/11/bits/predefined_ops.h \ + /usr/include/c++/11/cstdint \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdint.h \ + /usr/include/stdint.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/include/x86_64-linux-gnu/bits/time64.h \ + /usr/include/x86_64-linux-gnu/bits/stdint-intn.h \ + /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h \ + /usr/include/c++/11/bits/localefwd.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h \ + /usr/include/c++/11/clocale \ + /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h \ + /usr/include/c++/11/cctype \ + /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endianness.h \ + /usr/include/c++/11/bits/ios_base.h \ + /usr/include/c++/11/ext/atomicity.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h \ + /usr/include/pthread.h \ + /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/types/time_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h \ + /usr/include/x86_64-linux-gnu/bits/cpu-set.h \ + /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/timex.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h \ + /usr/include/x86_64-linux-gnu/bits/types/clock_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_tm.h \ + /usr/include/x86_64-linux-gnu/bits/types/clockid_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/timer_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/thread-shared-types.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h \ + /usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h \ + /usr/include/x86_64-linux-gnu/bits/struct_mutex.h \ + /usr/include/x86_64-linux-gnu/bits/struct_rwlock.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h \ + /usr/include/x86_64-linux-gnu/bits/pthread_stack_min-dynamic.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h \ + /usr/include/x86_64-linux-gnu/sys/single_threaded.h \ + /usr/include/c++/11/bits/locale_classes.h \ + /usr/include/c++/11/string \ + /usr/include/c++/11/bits/allocator.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h \ + /usr/include/c++/11/ext/new_allocator.h \ + /usr/include/c++/11/bits/ostream_insert.h \ + /usr/include/c++/11/bits/cxxabi_forced.h \ + /usr/include/c++/11/bits/stl_function.h \ + /usr/include/c++/11/backward/binders.h \ + /usr/include/c++/11/bits/range_access.h \ + /usr/include/c++/11/initializer_list \ + /usr/include/c++/11/bits/basic_string.h \ + /usr/include/c++/11/ext/alloc_traits.h \ + /usr/include/c++/11/bits/alloc_traits.h \ + /usr/include/c++/11/bits/stl_construct.h \ + /usr/include/c++/11/ext/string_conversions.h \ + /usr/include/c++/11/cstdlib \ + /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/bits/uintn-identity.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/types/sigset_t.h \ + /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \ + /usr/include/c++/11/bits/std_abs.h \ + /usr/include/c++/11/cstdio \ + /usr/include/stdio.h \ + /usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h \ + /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h \ + /usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/c++/11/cerrno \ + /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h \ + /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h \ + /usr/include/asm-generic/errno-base.h \ + /usr/include/x86_64-linux-gnu/bits/types/error_t.h \ + /usr/include/c++/11/bits/charconv.h \ + /usr/include/c++/11/bits/functional_hash.h \ + /usr/include/c++/11/bits/basic_string.tcc \ + /usr/include/c++/11/bits/locale_classes.tcc \ + /usr/include/c++/11/system_error \ + /usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h \ + /usr/include/c++/11/stdexcept \ + /usr/include/c++/11/streambuf \ + /usr/include/c++/11/bits/streambuf.tcc \ + /usr/include/c++/11/bits/basic_ios.h \ + /usr/include/c++/11/bits/locale_facets.h \ + /usr/include/c++/11/cwctype \ + /usr/include/wctype.h \ + /usr/include/x86_64-linux-gnu/bits/wctype-wchar.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h \ + /usr/include/c++/11/bits/streambuf_iterator.h \ + /usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h \ + /usr/include/c++/11/bits/locale_facets.tcc \ + /usr/include/c++/11/bits/basic_ios.tcc \ + /usr/include/c++/11/bits/ostream.tcc \ + /usr/include/c++/11/istream \ + /usr/include/c++/11/bits/istream.tcc \ + /usr/include/c++/11/sstream \ + /usr/include/c++/11/bits/sstream.tcc \ + /usr/include/c++/11/vector \ + /usr/include/c++/11/bits/stl_uninitialized.h \ + /usr/include/c++/11/bits/stl_vector.h \ + /usr/include/c++/11/bits/stl_bvector.h \ + /usr/include/c++/11/bits/vector.tcc \ + /usr/local/include/z3++.h \ + /usr/include/c++/11/cassert \ + /usr/include/assert.h \ + /usr/include/c++/11/memory \ + /usr/include/c++/11/bits/stl_tempbuf.h \ + /usr/include/c++/11/bits/stl_raw_storage_iter.h \ + /usr/include/c++/11/bits/align.h \ + /usr/include/c++/11/bit \ + /usr/include/c++/11/bits/uses_allocator.h \ + /usr/include/c++/11/bits/unique_ptr.h \ + /usr/include/c++/11/utility \ + /usr/include/c++/11/bits/stl_relops.h \ + /usr/include/c++/11/tuple \ + /usr/include/c++/11/array \ + /usr/include/c++/11/bits/invoke.h \ + /usr/include/c++/11/bits/shared_ptr.h \ + /usr/include/c++/11/bits/shared_ptr_base.h \ + /usr/include/c++/11/bits/allocated_ptr.h \ + /usr/include/c++/11/bits/refwrap.h \ + /usr/include/c++/11/ext/aligned_buffer.h \ + /usr/include/c++/11/ext/concurrence.h \ + /usr/include/c++/11/bits/shared_ptr_atomic.h \ + /usr/include/c++/11/bits/atomic_base.h \ + /usr/include/c++/11/bits/atomic_lockfree_defines.h \ + /usr/include/c++/11/backward/auto_ptr.h \ + /usr/local/include/z3.h \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/stdbool.h \ + /usr/local/include/z3_macros.h \ + /usr/local/include/z3_api.h \ + /usr/local/include/z3_ast_containers.h \ + /usr/local/include/z3_algebraic.h \ + /usr/local/include/z3_polynomial.h \ + /usr/local/include/z3_rcf.h \ + /usr/local/include/z3_fixedpoint.h \ + /usr/local/include/z3_optimization.h \ + /usr/local/include/z3_fpa.h \ + /usr/local/include/z3_spacer.h \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/11/include/syslimits.h \ + /usr/include/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/uio_lim.h \ + /usr/include/c++/11/functional \ + /usr/include/c++/11/bits/std_function.h + + +/usr/include/x86_64-linux-gnu/bits/uio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/limits.h: + +/usr/local/include/z3_spacer.h: + +/usr/local/include/z3_fpa.h: + +/usr/local/include/z3_rcf.h: + +/usr/local/include/z3_polynomial.h: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/stdbool.h: + +/usr/include/c++/11/bits/shared_ptr_atomic.h: + +/usr/include/c++/11/bits/refwrap.h: + +/usr/include/c++/11/array: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/syslimits.h: + +/usr/include/c++/11/bits/stl_relops.h: + +/usr/include/c++/11/bits/uses_allocator.h: + +/usr/include/c++/11/bits/stl_raw_storage_iter.h: + +/usr/include/c++/11/memory: + +/usr/include/c++/11/cassert: + +/usr/include/c++/11/bits/vector.tcc: + +/usr/include/c++/11/bits/stl_bvector.h: + +/usr/include/c++/11/backward/auto_ptr.h: + +/usr/include/c++/11/bits/stl_uninitialized.h: + +/usr/include/c++/11/bits/align.h: + +/usr/include/c++/11/vector: + +/usr/include/c++/11/sstream: + +/usr/include/limits.h: + +/usr/include/c++/11/bits/istream.tcc: + +/usr/local/include/z3_api.h: + +/usr/include/c++/11/istream: + +/usr/include/c++/11/bits/basic_ios.tcc: + +/usr/include/c++/11/bits/locale_facets.tcc: + +/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_inline.h: + +/usr/include/c++/11/bits/streambuf_iterator.h: + +/usr/include/c++/11/cwctype: + +/usr/include/c++/11/bits/locale_facets.h: + +/usr/include/c++/11/bits/basic_ios.h: + +/usr/include/c++/11/bits/atomic_lockfree_defines.h: + +/usr/include/c++/11/bits/streambuf.tcc: + +/usr/include/c++/11/stdexcept: + +/usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h: + +/usr/include/c++/11/bits/stl_vector.h: + +/usr/include/c++/11/system_error: + +/usr/include/c++/11/bits/locale_classes.tcc: + +/usr/include/c++/11/bits/basic_string.tcc: + +/usr/include/c++/11/bits/functional_hash.h: + +/usr/include/c++/11/bits/charconv.h: + +/usr/include/x86_64-linux-gnu/bits/types/error_t.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/ctype_base.h: + +/usr/include/wctype.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/c++/11/utility: + +/usr/include/errno.h: + +/usr/include/c++/11/cerrno: + +/usr/include/stdio.h: + +/usr/local/include/z3++.h: + +/usr/include/c++/11/cstdio: + +/usr/include/c++/11/bits/std_abs.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: + +/usr/include/x86_64-linux-gnu/bits/uintn-identity.h: + +/usr/include/c++/11/bits/shared_ptr.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/11/ext/aligned_buffer.h: + +/usr/include/endian.h: + +/usr/local/include/z3_fixedpoint.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/stdlib.h: + +/usr/include/c++/11/bits/ostream.tcc: + +/usr/include/c++/11/clocale: + +/usr/include/c++/11/bits/stl_iterator_base_funcs.h: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h: + +/usr/include/c++/11/initializer_list: + +/usr/include/c++/11/streambuf: + +/usr/include/x86_64-linux-gnu/bits/types/sigset_t.h: + +/usr/include/c++/11/bits/functexcept.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h: + +/usr/include/c++/11/bits/ptr_traits.h: + +/usr/include/c++/11/bits/stl_iterator.h: + +/usr/include/c++/11/new: + +/usr/include/c++/11/bits/hash_bytes.h: + +/usr/include/c++/11/typeinfo: + +/usr/include/x86_64-linux-gnu/bits/cpu-set.h: + +/usr/include/c++/11/bits/exception_defines.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h: + +/usr/include/c++/11/bits/concept_check.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/stdint.h: + +/usr/include/c++/11/bits/exception.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/11/bits/range_access.h: + +example.cpp: + +/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h: + +/usr/local/include/z3_ast_containers.h: + +/usr/include/c++/11/bits/stl_tempbuf.h: + +/usr/include/x86_64-linux-gnu/bits/types/__FILE.h: + +/usr/include/x86_64-linux-gnu/bits/types/clock_t.h: + +/usr/include/c++/11/bits/nested_exception.h: + +/usr/include/c++/11/bits/stl_algobase.h: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/stdint.h: + +/usr/include/c++/11/cwchar: + +/usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h: + +/usr/include/x86_64-linux-gnu/bits/long-double.h: + +/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h: + +/usr/include/c++/11/bits/unique_ptr.h: + +/usr/include/c++/11/ostream: + +/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h: + +/usr/include/c++/11/bits/ostream_insert.h: + +/usr/include/c++/11/debug/assertions.h: + +/usr/include/x86_64-linux-gnu/bits/wctype-wchar.h: + +/usr/include/x86_64-linux-gnu/bits/types/locale_t.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h: + +/usr/include/c++/11/ios: + +/usr/include/c++/11/functional: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/c++/11/bits/char_traits.h: + +/usr/include/c++/11/bits/std_function.h: + +/usr/include/c++/11/bits/allocator.h: + +/usr/include/x86_64-linux-gnu/sys/single_threaded.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/types/FILE.h: + +/usr/local/include/z3_algebraic.h: + +/usr/include/features.h: + +/usr/include/c++/11/bits/atomic_base.h: + +/usr/include/c++/11/ext/numeric_traits.h: + +/usr/include/c++/11/ext/type_traits.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h: + +/usr/include/c++/11/iosfwd: + +/usr/local/include/z3_macros.h: + +/usr/include/x86_64-linux-gnu/bits/time64.h: + +/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/11/bits/stl_function.h: + +/usr/include/stdc-predef.h: + +/usr/include/x86_64-linux-gnu/bits/libc-header-start.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h: + +/usr/include/c++/11/bits/memoryfwd.h: + +/usr/include/c++/11/bits/stringfwd.h: + +/usr/include/features-time64.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/bits/pthread_stack_min-dynamic.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/c++/11/bits/postypes.h: + +/usr/local/include/z3.h: + +/usr/include/c++/11/bits/invoke.h: + +/usr/include/x86_64-linux-gnu/bits/timex.h: + +/usr/include/c++/11/bits/exception_ptr.h: + +/usr/include/c++/11/ext/string_conversions.h: + +/usr/include/c++/11/exception: + +/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h: + +/usr/include/x86_64-linux-gnu/bits/timesize.h: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/floatn.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h: + +/usr/include/c++/11/tuple: + +/usr/include/c++/11/type_traits: + +/usr/include/x86_64-linux-gnu/bits/types/time_t.h: + +/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h: + +/usr/include/c++/11/string: + +/usr/include/c++/11/bits/cxxabi_init_exception.h: + +/usr/include/wchar.h: + +/usr/include/x86_64-linux-gnu/bits/types/wint_t.h: + +/usr/include/x86_64-linux-gnu/bits/floatn-common.h: + +/usr/include/c++/11/debug/debug.h: + +/usr/include/c++/11/bits/predefined_ops.h: + +/usr/include/c++/11/cstdint: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h: + +/usr/include/c++/11/bits/move.h: + +/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/stdint-intn.h: + +/usr/include/c++/11/cctype: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: + +/usr/include/c++/11/bits/localefwd.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/x86_64-linux-gnu/bits/endianness.h: + +/usr/include/c++/11/bits/ios_base.h: + +/usr/include/c++/11/ext/concurrence.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h: + +/usr/include/c++/11/bits/cpp_type_traits.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/c++/11/bits/stl_pair.h: + +/usr/include/c++/11/ext/atomicity.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h: + +/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h: + +/usr/include/x86_64-linux-gnu/bits/types/timer_t.h: + +/usr/include/c++/11/bits/allocated_ptr.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/c++/11/ext/new_allocator.h: + +/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h: + +/usr/include/c++/11/bits/shared_ptr_base.h: + +/usr/include/x86_64-linux-gnu/bits/struct_mutex.h: + +/usr/include/c++/11/bit: + +/usr/include/assert.h: + +/usr/include/c++/11/bits/stl_iterator_base_types.h: + +/usr/include/c++/11/cstdlib: + +/usr/include/c++/11/bits/sstream.tcc: + +/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h: + +/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/local/include/z3_optimization.h: + +/usr/include/c++/11/bits/locale_classes.h: + +/usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/c++/11/iostream: + +/usr/include/c++/11/backward/binders.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/c++/11/bits/basic_string.h: + +/usr/include/c++/11/bits/cxxabi_forced.h: + +/usr/include/c++/11/ext/alloc_traits.h: + +/usr/include/c++/11/bits/alloc_traits.h: + +/usr/include/c++/11/bits/stl_construct.h: diff --git a/tests/CMakeFiles/cpp_example.dir/compiler_depend.ts b/tests/CMakeFiles/cpp_example.dir/compiler_depend.ts new file mode 100644 index 00000000..c0f1167b --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for cpp_example. diff --git a/tests/CMakeFiles/cpp_example.dir/depend.make b/tests/CMakeFiles/cpp_example.dir/depend.make new file mode 100644 index 00000000..8eade316 --- /dev/null +++ b/tests/CMakeFiles/cpp_example.dir/depend.make @@ -0,0 +1,2 @@ +# Empty dependencies file for cpp_example. +# This may be replaced when dependencies are built. diff --git a/tests/CMakeFiles/cpp_example.dir/example.cpp.o b/tests/CMakeFiles/cpp_example.dir/example.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..324727506a0ecb28c9238e6f79fb3a9a69e0beea GIT binary patch literal 69080 zcmc(I3w%_?_5V%QNTjH!sAzqJ6fFqG1j4hZL0m~NU?c>oN|%r<5D7_4HVBFp1uZe4 zX+=fr1Fb)$*0xx+VyiYPMYR4ZTB}%J{HzZusQ75bR?GjKnRD(vckWDfSKH5jK5S<0 zcg}0hoS8d!cJFXWyz;c%oE(o+j(3t5Trui-YaR{CWvW=_otQIDah?a)^WlSh3*gfP zpJuvlf&6?bw?f`V*bJN4xcON`UjM+fV=}fSJHJSG~$hZ-)F9D&GqES}Na0`R$PZgvxh7{y$W{6Y{&Lybki8Qu%Jke@5kd zApbd)e*yU~;j^Bu?}hwVRK5@L`>Ff@j-cC3;T~KTdShrzgE}Bx0H9h7;s&yrN+BM z=;c*PR?U|3Rgz=GT4kM7aCwWPBEGbT#>BgNssyuYmWB*QQ#O^a z%F|vUqdLh+qPf!K_}ZwL^$J=wxhvFY?fT3VfL)mwqCK1uX?%TVA}KPUhb++n4PQkO zuu65g>{RS$BLZCg9Kyjc?tgG*PzLY$IQWChIuwFS6*9r4in-uYg==uBjrK+9IHSwX z`1bnpA$s)ezq}3x*WbQNBdomR3EehLx}z5kI}L7O%l?Mbt_9z5jtvwNx>pMk) zzIP<(yGeq+zXTX^oW!LEB`#elap_ZuOXo^FHB zL830TsNlpC3ufygsYO-EMJ=sbXKh<50iSVS+Z_mLTFJ9bZ+I3E7!7&bK}Bf>)5fi^;U3A5IFG92ZP* zfefk9I_CH6$>}{SZ&{AFE(gM#X8;^8Duyw5mv#H&H;DZ#C_37AfvvmzcB$bFVW3fO2Z3(Dw1funw-b{aDgDF6b|6Ut#(C#=8F7~wd(z8|G z1{{=f46_d+_S0MuX@}KH%?)6aDu2 zab}4zEq`nIlV$lz=BoHM76D75Z6F)MFz~*pHiGJy9Y+O0707S}(!OIMgeK>;cpc7I z>MYAIzq~tz0S_*Liw^BfXYZBe2i-S*8n(JXjV^41;O~gC&*}ELkK-~^* ztbzW8ML;LSYe*nM5WZ?8K^f*uwN~IU$@%N-0|@EJ+6K(lT3AEpfpCikK`=H*aMlX^ zzQA_$R~nRb9q@&^F=TBpYn6AHhT zDHox8g5J=RPZs{+nBI!30cbvaR8K)}bwdX_NIcgnj(muCgh7bk2kKHe&9@G9jRv=E zHtz_lP;Jd-IgAh@r*%Bh1*?wW5{6w3t}FVf{fkuS7T{BryKVt}ieRc6n^)^y2sw8K z7#8VI5kz`gF9y@Kn>xT&v{yMohAT8d4{w}urJK}DE{xMul^t)&5VQG~wzz)18TUM}z6e>v{)_DluwooY%)5=)()jwClU zneVkv50g1G8BCvyp|v|4T9(zACem#*?gF}RLw78gM3-H>%S#L11k;V0;xfG{h30xa4A7a|)g4epk+yYtce}hr@95oQuLi3WNOW%1j2A-UvlpI6c%LQH=hDlOH3P{wV=DpxVvRn?}lAd)zxtS zG`hP3mwrM2Ks8)X-VA-cEgZ%W-8gYh-VM`PA3dGv-iyxZfy>3B5;kvlgC>wl&BKS0 zP9E=aF5WIA@;n?&W*w8UEfAmVB@9GAzSQJ{Q#7uI{~}uunXy!BfYNa*5OWmzG-N=; zx6ui<16xXWnoclTJu1L$i_L~_IeU4174M}!C3s>yhR+ECt!BVPL` zbWbuyV5YYuoG5UV!YJE!B;1asE1@W2k;O~>vSj-g|0;)`u-Ic-8HXd!e9293)$&f=%+e&@g# zZyNIJT<__ep||CF&*s8)bPXC>r})l*6$nfda|Z)UMc$43cnx`%?c-gN_g=ntZBE{2 zdwajk$$N8eZ(B~@^ZDNAIeEXy_pZy$yFK5#FE?*hzPBkiZ+9>6)!aj`?&YnDVfl_& z-d}rpkHmhN^T%G^^1Qr(BPyZ7NJ+ChBr5x`(sO-wY(k`UKdO76!t7##twTI6Sb3k8U-wjc@3wm)k z#MrJ-e95gl4n>?CfkXO_?df41^B-Q1WYg;Kv=O>fb<{i@8Ho^fdeH~Asn=={y&i5b4gi&+PKPU0iQ72_F#c`?29{X8sgVFxV6JU1SVg_=ykOlE89}~H z95SdM234?@KsmG{9MazNSQO7m5uM>t>!74Zb1lv( z>PfJV_JDSX&ARk*1VyL;s^xvNmnr1++%AZzG=BLnDo>+XdgA||6`ujUa+)G(t^X% zq$$HL96lzws4m%(YG`hXyQwEmm@u|rP|fW2rc`@DNl8&@QStF5?dr1R`@@D66_*Ys zSjpH6{`Q3rEF-*$Q))c;hN&B|7<@4G)0vlZ;Z!eYQQw?z_UV=11q+iS0LKreBk@ms zzrI)GPS|(vX+Qv%T$giURi)zW^<$*^CiCMrANaw9^APIvWyF`oa_1*V zz8lovfjA^r{YG8wjmDhqY!3L}qWYs{{d8Sl0GPT1LXPtHf{!ml*nqzm!=!$g#5yVi z9pzL%6p6ULE~uYJ^(V^uR8YTy>Jzd)R~tDHuokMv--3p0L|=9WZCOKf#U|a{K-Z^4 zbBNS6S=XbkSE>FHQ^v%Vv1NPZ{v0W>|HnZvVRHH8T&jmvZ{U-fz>Xzp_-~^60g``4 z!2dASPnGq#6^a1udzI?P%KGyI{x7KB=7$2{If4es9LbOVCL55ZjA&|2nrf{FX@(Nb zL@1kmw;0IK))hqKvSl6B&j4CKzR;FQL3^GdnqiWrA*kQkgATNzk1`J0B>6!{E7>@d z>M=%q8_o&jS5m!eoHbJYG|7)`I4zLTMKrcH6ae3Ps-JJln5kt91pFqVxf05%$m0=p zEeUjeL3A#AkHAS268;X_Z?7H$H=`8vSsBsbZ*_f|+;^1{te-{oHXT^Mlh7AX66>b6{kl8~m)-dO2*XW<{|Gd-kK zdy9$Y5=oQ0P#J^msiOKbL-pmVz5uWms=rLuV|&D0xSD7dNt#?ep$`OX3Dw^UWwX7x zKUAuet*;VYs6Dw;d|SUrQ-4G+G{Ez0ZNavV>!H2?>d&S67AS}OIa}L^G)sx*Zb_s2 zpXxV(kdU16WwF=;dnrPsdzI*( zhjNGx`)Q+=SAcc65P;;0JG5yQ(YWG!Db>$GK^$|s{p#k2GVUOnlOzq;(gLOw0Jf3p zL*o=}y)|h2dZNMKrJHSv<)8=knx-#&hlc4K{KNL-PW9`Hsor(ZtD<_>J+Fo8D?;+i zeED5eZ|g(!#rib$Td01Nl;5QNfc(3t-eq6k-pJ^AuKHrCciC5!hQEdCN1_t;?}EU- zt~C7X)6{RF`T>;sw;Q2**Q z{P(A+e<4l%r&NzV@b$~~_rVHy2Lu1GeP;%JR7&*+%6f5+m`3%k7)qt7UrqJxACrTXczK36ZGv3?rWA13RowEqyYC76~V z9zWV+tBZMRc8pZTyoLydK+HSOfj35QG&RQyaI^!{Ao%16`HbVdg7kdNc_rbrr1tB- zOSl?qQ05$pVCMqNA}OZc`isCoukNIgikR0L!4QafDF?pLfvXiqq%Nl3B8-mpJfC9r!W_zTAOd;lO|3z*ji%D;;>J17GRDS2=KeTQZtrURM+ZBA=@H@Vg!OJq{e- z42`CkdQ;Sf-x~!1iFx=IX*9(=_0$uohfW$m}LpGXX-k+l&ATjSH2mZ1H zf5m~n=D=Tf;M*Mdn-2Uf2mX!&-|oQQbKpB2IKJH*O)+m*6a*yZedNILE#PR1d4G?B zfW*Ad9QfxB{9g|IO9yUUwt!x7Ab{YEdH9xbG{ro8<2agP9=?4XO)(GOM2@DIhi@fE zQ_RCRl%px;;ZtEW#XNj-IhtY~zQr6(F%REpj;5H0Z#PF%%)>XGqbcU$ThGxH^Y9Jm zXo`9GMszgAyrUgBzAYV1F%RFIj;5H0Z&F87%)>XUqbcSMa^U#3bvP}B%UoFBuA%)Y zwWbDaJ>ee^ei&S1(lb~@jC%JTC7B7|gNL`+O<29N?s>G)A!@ZJ`v^oA@jY4*Y5dev1SD%;AS$0)3%)-sJXfQg{nDOMM537q2_y9|==Np?KabB+iiv z51uzi6J8Ct%|D%rK6nm2n&@wK(BJK#e^}v*h+BV$i5KugG^<|R+b#5>^dBhvB3};A zT>C))6pH8Bp+r%v@QZ!=6RC72;I{V8R`kJhZi49H_jFcz__duC-=O4N>g&CMN`G+R zuPc1HPhU)>j~wzn*dHzQqVxwT{0F|AL#Q-D;VXRn5h_gs+~$WliavN=WQeZfK7KTn);jR@3SZ~b z^PPAz;5NN~QS^8F^xWP(4tyXi^$NXveERuR8V9&dez~F#_Cu~D`h>!ReGhI|vje|G z;lX~$&q>bpfZO!0RrC+|cJ89m3l93X6#aufJ=^2$hwTlXPtPHWu?mmUPgnRuzMLv5 zT>!Yv&JIQYTc4gSzFXlNef$zCJ>`(I%^@cTzAPy8c=pxbNusEO0Jqt5jDvoZ!n?@| zeZCrA)HvkKQS^`d^k-3NiGzNn17EA;Z1UxtNu}R7=$}&bn|=DrsPs<<{ode&Lhosx zo>u_JEBqNBzm-ap6#lG_bGzmP4*w!)k)nUj$C>_m2mS4eKGhbBkT8H)Z*A3vE&?FtX}(~cv& z!-4+}>JJp(L*Z`-Fx~9XdzS-$#DVX2;QPRO2KBPO=e1gIKfrD69pJ!+JMamB56IO| z_b3{cg(`gy@Io)@x8)8wH!AvQzdz%ke@)SULfYUx6e=Ck&)%-VfERk(efpEARPCUj zqv+rB>3>e8RSx=F6@4@g-*C{st>{1V<#YTDfq=C2OC{ii-se93C@TFx;UD-o-*+BU z_`iId<3A4;9);eQ5qy%u_xL#5^Ps|meMpw`Dd09cdmoDO{~nRkqVQnfawJjw%0b^B z7T$$o-<9q8p2CBDPPS*0!h?NI#`izWZs#F@7mEE)URR%^@L>P*XtMJrg-7jwUE#sL zDC;eQFaHb0z9{4C6dvr0GJfDUkv^)oTH(Qd=@7E#T7?Jur7UNg!h`)%#!rH+u0pY2 z%J}UH5B5vBz1tKX?3aSsD)l}RTW`Q{hoNuU2@}&W98p?7Ol(IncmDvG25-z5UNhIbrwI}KpEvg(=l1S7i=hU`0rV_w1Khe_M*ig4P4rHZJ)t0JFHPj_g zbVF@p!-a6w+?1$oss|=*0A3e2Gx=5pjiuULpXn>hwA!1$ZPhaZbZrK}g7{0qZEB!Bgo35krD%q&}$*h^9`d zPA~zsQ0Zw~ykK^7qgh*3Qk;PE;dCXD4u@mrB6OpW3@Qwo)2oXU0uttwwl%j##f(e7)v1!=_NIpO+mnfwRBOff zgzo{UDdljlPc|k~$%^V>z{RbE`Vol)@*-yfkJ$^{XJHaCl(fim}%3^_pLCDYAfpE6G&!tYE%Me^pcX2Vc-myv|)a3XqsD5 zhn-Y6uNH=9Yi&cS4R{nIa>8^AgL$|PCzN)oFD?JT^nSZaMx>g-<#--zEA&HSDn1%4X~gqE$qK%^mEs*+ z-S0?bJg^z>n2A=t&oW0zNgEuSN;lMa6^v^TO_#`vwdyp{#5}nDHzr#d#QDDkA}y6z z&|D9Zq3)_I6@r`Z^F9=Kh#?hWpo3h51{!jtlb8#=B(2n%(2Y!iagWYYcI$4#17CGB z>d4vD9a?QEFM{1+SBP%4b8+5|1BL>+n{kOzTHMh7vc%~tHGd9BSCkf=GWNhwCV zjF&0H?8_8d#FRv9Rp99A;c&EW;0BUtdO@oz86G;=SKm>IBM$dOFtxU=E!moq<9j46 zmJAzhizOyC433a0>$O-v?DeH?2y~}fcbO`AO@o~PXAHxDm_zPYBvw)G3-NVkS}Buoj&ZhM=wi*L9MTY5iQ!Qs#JrO>`05%g4S#?JCNO? zh|C5{B4sL4jmD9Pn!;`Jn}amb<{+x?Z))07D_8DU@MQ9QJudW$7DolR3ugZ0`DEZ| zc)U@EO^d~8U8B)KzP;pYWWlqkNk(L;%Lc(sDa&P|Fg+?Y=p|bF>zf3R$Ywl-8r!GW z{l=i;#|5*){Ko}<&Mk((rspQLu+bhPp>yCVp|N>x1K)jEtl7oBSR&w2NMh=faxgMY zq=CcXcx>5$qIG(1qaGjuBh-wjP?s_mGASjU~l+ z>Ue|}L4$HkazP8x@%ji5lc=ddErMVsWFkO_sH6lRw_qZ#Yi^Bn8+cUI633Vp*z`!X z!E7pfIT)rbyo?wDk0|YJasSygcsP$dL;5thJ`PQ^Y^M8(cT7ur+dOy_shbb>(6b)Q zB9Wmup+rm<+VqGW{48tZ9}dr^dP>IWFCxCQt>MC??_kyR^tOwsL(O)ua+A;b8Uv5e z?XfylTG!kT{-tf7Gfq3L8lFq1jX$L_j*k;ipM+(i?dij|+6K;ISZ|NiPa@558>u=C zmhjbyxVNCTp$W&toCbU#x-gkokX+E*x|o(yvy*chnqZSDRX2|iP)pbRNOktK3d_?I zcrN1fp!0dc!MU1tH^P%n54`9)ki;X7m)?P>^u57Tb1CgEkqzjFKuiL|4P{{z^k9#O z2f>U%k^ytWqWF1+TDa3v3nHO6VOYkI-Bh~(rDT7TgVAH`g#-(17<~1x~}v_IjY@U(rHw1OF;JG$Rv}ara4&@a*j_DZ!(S{ zrBQ15!h?Ob>z3hQv7WF*fQnT;NR*Duep_ysA;GmRC$(g}p#~c`!N#7HkiDHH8QPiU zx)6q?F=SwZMyIPSv&?qvU`m5c6188LfSuC?$);4r4BRA1@h0M_EjWqCDIBI&kJqz# zxbHIcDs1dc4h3<2ZI#+e!0?hz&Qzc=s@UjYzYyd`#|U&R?l+cLc0Rv~5x6a;V+FJg zgUvn|sq>PJu-|8FUfTCSwKY@0&A4L~+Iq#Vm;^Ua=mazwrdGd)VMjHiR({1E_Vr}C z_lqmv>_X{uKbErVwqcfT3wbSz4QqPnHT|Bsgi#RC^I)$U)<0^UV~K#Yo6?iw@g91A zM5y<_dVHOZ0fyr&t5dmp$m-R^xrY3Ru`)?mP8_)UT69@-H9N{tg@ zM)3Ui6>Sehoz5#`xU+`7??@Xk`dbXA8#C&zj9ut-c4lSSY8XzcV@Oe3eWSXO!B;xanfR4W?d*nyCBvZH){v-cgq?{5 zuBTuJVNNs7r|Fabn)89?k`2VtELVEla70aI}@OPn(@fyNW4*u$g@tK1DuY$gw zaQyvDfuL^|^!RHamUEH7-xPAL5;*?Wlj;9Q;P~q*#(zz?Y3HMY{$(Nm_k^2vZV~j- z&et9C-x2gu{`(I3y9K?Juirb={U!Z;05%8`_Lr33pK#OuZwY!Szl3nir2H|0Udk^c z+?0R1pqKJz5{?;;(_c|L=L!1VfOCIcE^z!cCF5%Z{)NEr5ct0ZzFy#ReDRrw=(m3f z`ppjd7aaID2fovR|I2~*R_{~lew20|=D-Iz@KFx@G=bw>#Qr>A;8O1u4*V8@zbWM0 zCvYiev%saFUlX{b|JZ@|!j6K3nWR6$ftNaPK3mb0Q}3W(;=ors@OuO<{rsT7Z-+Lp z{~s3kPXzvg!0}g&O#ceu7)Cgb9;9*fw!r21eP77ATgd-Z(4(A(NY1|nF6HcvM3Asr z%K3)C@mG^<=RkqW_6`*|{wkB{M-k5L`W@LbUf|N63L!_@ga4fYCbaXX@L~B$AqR`> zw-!M!<+KYN-_B<_%N+Ps0+;Q5m~dzz9trFtDgb(9V@4W&asHnC5_Y0hVACGb#5cmW^|7(HI5cq=v|Bk@%9R{{X_Tzm5 zKU>h_nwIG=ao|@9T=vV=0+;-nWFDY}+g2N4AUaBiN7Ig?t$gPYZk|lrbUwtMK7|JOM#Sh|A~D z?vU6>f>c@^hIOpHIQFZ~nXP`;d3(N~xdmwuCR@)6W= zznp-?kdR*bf0RNsF8xp;@K2%4awNT+&!zwWA?Uv++}n;MWOU z#@o*XF2~UTflEIO7P$0-To2%$82dr4AO0rr<46woBkx0HdOy7~M+-Qep4oz4+RyVF#-VGy zA?=alRN7M`;L^@kfgdRByiDM7yxbsgX+O`yru}kVB<+`R-cRUl7V`0}XpRSI zkHoJP^oI!g+XRl^p|G6w0`D(yY$GPLU-}380u$nRN+rvAMWGs({`pwo(myy?V?sGd z!*cjdal{W7@{6I2$)t}9T+&wwT+Rdh{SL~J^T4;1bS?i+P-c5p5S|NpaLOIN!>kj^ zk^MMW;L>k$e#W<}S-#XO*EuIR@Lt zSnmvh|EKQb_;xtUm+h5yo-FiAJEsa9V}|9-7Pz!i-lwGePC@?xlv&QL0+;b4=jY>v zUU|P5CUEIDJXMk9*9-Yl&U}I6cbZHu?`tOr9Bspd@i{`^zf!2iWjs74@EuTQ`8Z}V zp&Yr+$1*0w<@myTHzvfTfBGv_#?#Dr0sKmGORbGkp5cwOlWq3ryUPGR|)UTE(14 z1|N;Q@4+8#k8E!OD=Be3LbC+U^$1}b_#9`6OTS6{4!(fAfXXNX+ra5`Dj{3@Cq)z*h?T!2-WW;5;W_^%j8- z5%jwRK2+d+X;7hFe%8b4Vu2S4`YM6*+7+u?1YRuY`S%7WzeM2o3;JOK-zxCo0{=gO z^IAex<7Ox%ls`h1^q&HO^W2CvrwW|coQT&8d^7@-mJ6Jp^|0y=f%BdT;+qA|d;5q# zC-89yP}(W*6B&fO@80?X+r?{jL`ntDYh%Qx3A_veN-2SlXAtr=0zXCI8w5T<;ExIX zRDo|3cwFFov_9H@n!pQs=?lbpuK>!Qd98>Q%LP73(619X-y^X4UV-y7 z4&qw`&TDwYcL^MA<@CA0r!WY4|9pLcwD{rk3I_-r=^HhfS0?Z?2*a#G;7Grc>gokv zMHptw1%9T$*9n}Tm9ToVz^euQPJvGo_}>MN_HL(4GalsQ!)?c$2_q2)tR~iv->x z@HGNIU*H=A-YW2|0&f%eZh@x+-k%ncXn(uFM++S5`2RbZVc`Bcxd=|}NY&2vir_tY zozLS^YqGJn2!3Cl@`~`4IIn1STbl>R9T8fjUIPt&&aMuPDQa!jv>~$4FY$p6kLM|x zTUSR1wj@9?9GRzIhYtx1jda90v#U_gf9?8 zgvir^TrCRGpg*ytXe3qm2dKdNnsCk#s$nW1>gn{Lh&lZ7vgIHlCvA^M2sycQZ#(*s z&7hEw5d$saTJ^rI%V}XE_6K^6YtU`RK|*0`C9!#$j#X`s3^o%=tOpOt-g6xf0&kMZg|A1yhu&`$z3WM-r2( zlM1ZDdW;uj*95Yo5Dg#j6Ok;Y0i?D}0P3_32<6b}0KqXmVgD#%;}oB;PV}Op3LWU< zpb=-^geh2vZgXgggeuV}I%_1#tq$oiTjd{m6Q)--o9Fd7NTkWO`N5YZ3C#wS`bYeP zwLsgVr~5=mvOC`=!X7yv!R}-_e})fz&?k@T^LQd6i8c~Ncq261&IjYD8;;F`;Div3 zLqOyl9hWBm1f2*0&$VzWZ1{K}C#5`6$4#V;x#{sZoeX%5({!91#=$z)sUKX*Z8gbF z?=qd`NFJvNkpp?0l%WH8+*I;Jo(PruNS+9(`z)RasqHi#moKffrX$rD#}Of>d^6mm zqoaotQ|!aE2L^LEW~D81Y*5%^IL-B-nooDhibJ<=aT5>c3?BO@n$gav+uvsu(J zIAJMlLgymr)qbGUzE5`reX*W^5SvG_Yz6s0uitdFuNS!Sb5|;hp z9NC`Dfk$(MRH6VmOfn4*Y*-nm6@Ko@fFW^2`RN4Et08v7zgJ53UtxeK7#{~;0T#$>G!nfTx5EFOFBjJAdDW5 z3d-y#mykM(>oYngM7f=xnZY^XlS-t;`egPj>4T#_@WAr_gvCN4oHvqAVy592NL8n{ z`1>;vkE9Kj;Ov&KDKEibmmSBsv2>+XrM%ado9#9|lCoI2$ zy;1w}TGZpYD^XpbC327>Z4;vfkz-P{1YFtaBLPj3+V&n!i8M?I)7uW}FRE)^fCr;_ zMNQ4AWYNSaHOIH%Ir(%A|LICmOKUTn_LW*p#w6z@=CszriTXuzTbtYE#=qE$&!$)g zKa!BY+hE=@D$v&e9{wh55n%K+wV%8AD~Z1^<;cG{3x57COX|Nf3x57iNAj=Bf}g+h zko-T*f`2K{Vv_t9!gZ$pTdBB%-zTB}F3N)cCgP{BH&y@Ln+5+J7XDvl!G90&%l6-w z1^)&M{{va@ZzO&he@n99f5F0kaTfe<5x?~RBU$k8wCH~{3;r)G`n$8>$9HTnN&CMK z*O|s|9}E9eS@7e#1DIs|JPp^G>MyYH{~-(hp%(s2vf#(x0ArH=dls%UwZF`we`yx{ zl@|U>v*5?yf?|^6=Q6m?)c$$IFWbL03;q_1{V!+1zr@17EDQb>7W-ezg1^h6|Me{R z`TR2(|J$g8x$s zKhEiyjvw`d6`+^>|3Mb~eeg#ZkR<;P;5t+N{Cif(|4A1711wy z^7DCeGXC(~!%X@4+&RgQ=S^nH&*#%getf4dQ+__jPV(=Y1wWs6C;9O_#Z2|{xp@B5|wS7pIpMf&CXuYVTy&#>5kXcqkS7Jhu6G*kbz zSop8bqWw!O{9Re_udwjr`;VF0zuLl&@6lz-zt+N!&or6x^ZOeze(?RrO!+rh^y3~# zru-W%{6EaX|NNebv>%_zGS&a8ML)hLnJNEv3qQU$nJNFL7XBY)(SBAW+mG*CW~#pr z5lVi1FEdmA{uci7Ecgdn_^-*L{rrBAv>)FG&D8#J7XA24o+*F1g&*H9&6Izdg@1Jx z?Vm;ba{j(H3;uZ)etfSrQ~UXSE9rlH|20#7J|9-{<9o81@~^Pie_a;s@3QdYd$*bD zUt{6NJ(*1T*Ak&@|IJz0&*$a#10GB`_g)Wqruw@r`Zs35{|xcV_`~;dGu8isML(W< zktzQ+3qS6uoBRcUfmm;E_{g-A2zwb7NGlV*LyDwj5`=Pp{IUd6`93;F|IdLU`=h^x zy<;IqnKa!K>Up2g`!ha31ylb}z)_})-=sIM@!dnj_NMhZ6jkE)dX8j(a)V60GpX8d zRLr_eGjKbx{rKLE+5RfPP`|e%MJ0WGiA^1*uZ)QK@=ger1dXL*?|NX>Y$c&U5YSh^lHv6lVX$H0v z?Qa3dv>*4>ZTer#Q2!?2x9Oi}(U0#fnfgC;=-*BHM?<|#rvKi9N}K+rq`#P$vHkd+ zps639No?&erjC>EaHA;G|9Cc&P5*jJ`xjdDmpb%Uk^Xf3&(D-)hGCm6`WIRB?Png- z{yK;K+sS@8{~=`Bf2qU%;=WoV`bH+x{yQD^mlFRWk{QaT{eN=sPa^(D((wNg_|e8P zQ!sv618JAe)cS7)l+E_+dnvF@4v%|Ki&AB=HM?T{-aniqi~KL+?<$aG`u{P9{>w@KR71b%|A!s=^RLj1vxpzZ zZx@tJ{hv7WZzcWm>F z%+!CqL;oQBvJq0T&eZ&Y_Yzb8y`EA&5<@mYPq94zT z!8V!W=hY1TcbK}e~(4~ zc!&OZv~anS6;p2NALr0tfIoJCg!f!b=>K0pZu3UdO8lt*K8yaR9s2)B`ga-n z&HnqnL;qUpc>K-`6Y75ea1B`KN8xwbn9})wFW|Su?^gV>9Fp|^gK%x?FLvmE zo%B~JDZwAJ{X-o3cai>bV#W49WYK@FLw^w&jy{vg)PI&k|LB#PtDBfn|8Jpewts~~ z|68R0Wa8({)W6K3e>dru?Z;;^Q~z4hZ;sz@9i}y6-^xVcz6>>ot@xA>I0VA{XY zVSm{wP0#U<{_6(FwEts={!OI+EG@?WYwCaBp}!a(b|5X%nHoQjL)p}S5CG^CbNzDE z;hOOh;^)lNzaQ}1#?Ly^KZ_W#{Trcd>Oaw;{}$4JCM%}g)IZvxKOcW=0I6JOs{Naw zZ0euw(7%iHUq<|#nfhls^jDF7>Hp0Z{kJ&ux8fHYkeFXzMW0`8aOmG`Y5&t81jtpQ z;puI0=zov&-%9kHneG3BLx0~c%|V&+|1$uY`adE4=J@S6Li5vOFsoOw>R&+N+wlF4 zEq-q#{&eG~5cqBJyOszuKYy;|%prap>P}(f^!9|HTgdlaADeryDKIw1K&G7$XtjM&{p}(8-^Z3L5 ze+d}P{>SqJZSgmgHqLO(Et9GLLx=v+Khj*?#Ekl1hO(*u=-zhyy=dVx$53codWQqQ zE&g|t{`JIw`d_i=KbiEK<99)UHk{`feWh*XGUhD~`>!a_RLAMe|7*@a^BwlDTdi4G zKidB~K&Jn$X8U~&y0E^0asx+S$#f;_mmrk8E&8_sZtB02^qcqJSp&4dbnB6iZBZqa{*L;q^hZ$7`7`Y(0p zFS||~ypHTf|G#I^kLPkiRb>5l%C|Hl{$^SxQ~!Mq{o6@@0r8{$ogm2U|5zWp{;31C z)^ntCD4Y8K?a-gUMl(wPe*loFe}Y5*FG&BvY4kTa_%{+i-3ELqru_}TZ;Rh5vR}?$ zA6e|b-l6|Z(qG|g)&*1lj~x2vS^W2jMgJ=f{X>t@`i@JZ|3!!X^_KSk-J-t|ey3oI z-{~3Zp9uUm|8KVF|IDKQW{3Wzq<>VJ_OEg1-)7POxkdk99r`zr{&ey8x|LM?w)Un#| zbpHRlLw}h?Kfb?Y&R?hOZ}d;7Z_`px!#>CnH{q95O%GWAb)=>G-j9}sG7^!{}w@Z0>q z!J;4EzcTgT>CnH0^wVR2Z-v?Z+Z_70SoGujTc-Yx9r{0X_#Z@s()$km+b#O>{V!90 z;sAU9@B3}7#vFg9{Yoi@2{EqS3C5#XW0I$9r|Zk+K=y#nfl*z=)WdI{ck(; zFS6*z-zu8=tKoZEfFtYYdo$EO1^8|L@3QE}|7X$E|F}c{7Sf+?{6FH*zs{onn-=|h z!}o-?_U|J7ho_0Zkq-XegES*_Pbi@-nNkk^BZxoU_-_V&oBz8l?LXSm{!I@3V>8tM zm_z?oi~a!?{r%wq#peGRq#tf?p=8egGadYMGxYz@9Q=zj*_xIP|X}{c`@s|0mRJ|8&xC`oCbXHk|#$ZeV`CKGUIpv!(q*E&4AY{pS8* z8R>`RK`5EmYk(h?(2@5qs)*mTm#;a$hV2h&fpc5%Wfe%=evBXdtvB;A{!_Bw^xup$ z`n7cUf1+5w5mz@uPsh7hD+b^VSf50TWWr{m1Y~(r@x_ApRD3K9 + $ + ) + endforeach() +endif() diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..44892e98 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,181 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.22 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/clexma/Desktop/fox3/tests + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/clexma/Desktop/fox3/tests + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/clexma/Desktop/fox3/tests/CMakeFiles /home/clexma/Desktop/fox3/tests//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/clexma/Desktop/fox3/tests/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named cpp_example + +# Build rule for target. +cpp_example: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 cpp_example +.PHONY : cpp_example + +# fast build rule for target. +cpp_example/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/build +.PHONY : cpp_example/fast + +example.o: example.cpp.o +.PHONY : example.o + +# target to build an object file +example.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/example.cpp.o +.PHONY : example.cpp.o + +example.i: example.cpp.i +.PHONY : example.i + +# target to preprocess a source file +example.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/example.cpp.i +.PHONY : example.cpp.i + +example.s: example.cpp.s +.PHONY : example.s + +# target to generate assembly for a file +example.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/cpp_example.dir/build.make CMakeFiles/cpp_example.dir/example.cpp.s +.PHONY : example.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... cpp_example" + @echo "... example.o" + @echo "... example.i" + @echo "... example.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/tests/cmake_install.cmake b/tests/cmake_install.cmake new file mode 100644 index 00000000..5218d698 --- /dev/null +++ b/tests/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/clexma/Desktop/fox3/tests + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/clexma/Desktop/fox3/tests/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/tests/cpp_example b/tests/cpp_example new file mode 100755 index 0000000000000000000000000000000000000000..ca18385dbd8e8d03e597e12b828a3cc4ceb90c3c GIT binary patch literal 44888 zcmeHweSDO~wf~clNVF)?LQQ>LC}>cL*(5+f(eSdc5rTmvG-&O^X0u7QY_f580|7-- z5hcdloA&1mxAi67+G?#sz@jJ1fgj*97AtgGvKuOH2h53hv_@fC{7B zI3E8`Gd#vIDCY>Aq*q7)s=W4Pr@}nOPXMHP1$2`Eo+igCd{hyKIm5&v882eV{ZLA{=6ubTNCuzrffE2!5a+Z1e&^n$BWVV+P1wj?IHSWhw+ zq58RAKi5;RnC+>cvM1?Cf8}gXCoBeyE(M+STDYDQE|t{`1*r|XYW61@KS_JlTyJEx zl;ec8tcQZCz166vOeJfM|3914Si|kPjYE}qDuJa?|hPh?uM;d2G!fhR$vpdV@ z&YoLV6pt2_2s%~s;E#rJ`Kmet!!kfPR^Q0(l4T{2XyhtHCw}7_yZ0V<=i>c0wr=wN z@poVC{LIC#E+ih(o9YN2K;q{i$DJ%M10)`4kFVf9#~>VC%klS8=*8CC{vK?ex^vPJ zfz0q>S_enY)ZeKta?Wz$Z+5{)UF_fF z(%-MSw7c0w{#7pguesPQ;9`en7yf5l^t{1EpK2FY~qg(a}u)e2okLTQ2R+aIpi$ z+f4Ey#_-_Jd7a`S=K`00o#0}h%U$&RzDvJ$quos7emWHNIF&^CJQw_3z-Q|3V=nq! z>Y~pj=bWo?z&7>b3O!|_BYR$H|s z5^W3B1{xwE!!(;)qitq95r`#B(-5o~880g}TQ``&Xj>xGnJ{BPLn6X$2{RszCAiow zZkj_9X>JI&H4>#U6f|R@Cc143w*?~MEg`ct)EbR#CKRy;;t7kJ?l*>liD*o(NL-;< z49M1avlJRp`cM(tb+ku1;!2|A4MrP7gwbTi(K?~RZI)7~8;?ddhGJ$DGFprwVKfN0>Dd4Kgze)Xbqw#jNo}EZo*?#y7V%L`8M3p^4Ud zg344c&h~3Z-Gtey^*9m5$dW|GCXLb(Xlsmwg!<@tsI^^?r2zu*c*q(~40lslR0dyT zAQ8YQ2BR@CrZnniN(10Qg}Bg3)3UuI-oo9pv4m(0i2o7o4%U4@bJr4)g-CmMHff|x!bF?CC0<|kir|_RHKi<|JRFUis2eJ) zYzrq?r&Tr4NZePwY)wtH#`K}3wm>T;Sg(h};k5Y&K4+-3#?iC_!38Y9(;5QxCd0*R2R+0bn6>@?d$ zv3Qi`Tw=4iu~>*EJEBWu$5kti+!}L&eNDsM-_@rC6}8Z4*M6 zxh53vXr*9DW2qt-igL1;O##ex)5JcAEJKmBH4ugm3wDf2XPDXpC5Rc)vO)5LdrK+p zlFEv_B?e0IL}T#Wa|tt-ip@a?qmq|OL5W|!WQkc?RBS9?S-E(LSyEJH-Idz6B}H?L zCH3`-7FU|yqSB&r$x~mCnq@^LUX7+xjPpCwM{9$j>wW#JDR*Z^sIpV`M`L>G1Q1H-Iw1IFZYVSzpDGLAG%k%5e8sC(9>%1tIu)_F8#E=31tZfI}Ky&!_fj_)|3gVGX}P!zVTTA`L&H z;TLQ8Q4R0Y@C9A6K>C+yc$J623B;L#BB?x#@P35^Om3Bhi2x)^T_YME4rX1W8Xl>l zeO)7ONe)tA>&nyc)V8|vH9WhfAQfnMlBF(>hF4=xv_cJ!iDO;G8vZy7i*q&&kBMYm z6&ik$g@vs&JSMJnRcrVYEUaPFYxv0;e!YfQK1k#i4X@|>?Hc~mnw(Az&qtVo+NI&A zYWzDi{AVot6-hHugEb2NOrhM%k9J2m_~4d12V%QgHC4L@JQ_i6YGH2h8tf1!r&*YFE9 z{QVmKA`QPw!(Xi7_h|Sf8h${-FV*lzZ;x8ws0EH%;HU+TT0pnJA19yjp?}-EdH$Z< z*G#0T+XoWaV?+LJPv<=)*v963?+U{>G&b}50F%!&h`)s>hYtLDY;3Gglqumqbl@ec zOo{%X15a3GO7IUI_z$a0iT$Ai_gH00=nozEidCjW{?LIhTV+ay4js7CDpTTq=s>_K zQ^J1ez-p^ZiTa@fi>xvw=!Xt?tuiI%hYn1$%9M~FI&h*@rbPVEfh?;`3HYG{?|-EF zONlr7Zj? zqyJW!5?u7(DpO*M{##{AXfgg)nG#uy|KC;rDS^fKTV+aI(SNH<2`l<nLw`l(#y{9gcFVqa1RS zuW*#>9OWuU+2<%Pbd={f%CjBinU3=5j`CDT`FKY;*HQjQed_rA$x;5jqrBfye$!EY z#Zi92QU0l;{J5jM+fjbVQU0c*e5a#)tE1fOC~tR^w>rulj&iG`9CDPeaFpvDECpct<%`FMEGq+5OTN{oQZ-x4kn`UF-7>c>l}ayRZ+- z>e$pje%>%XXeyd~=Jf~ySm1jX&O%*(Z|-yg^G6d?vGo4}OtkbLJ2pJ|%r4@4iXr&_ zO2pndhX~C2$lpEUf8xE1{ZEWe@Mk^af9a#d6bSex3&CpwWkp}1i{y3cjix65V@I0ky}7?pG_RLiSv(@{ zk^4who`DZsw3Y-7CMOfNXX;Pts3^MoG6qGdychWs?)&|=m=dYeE`jQ;>SJwsWFLf) zx~YLTg~Y*R4^lET@I||UxNHD=5#Mg+3rfDZHs1=tCoL>kZ(`PR$@(dq)gwjjk|G!n~3PiedaEzMt-=%6nLEFnO%Jhdl<9{}2Y>E?fb{_heDH42r*!#cFaC6o+I{ zxGRcJ$f8twF!?=Mlzujt{BOhre~&NO=s#D^p2^n-k-Z;ShyQ4X`MaM|o#{l)gA;A! z5H%JA^1$1ebq@T)NWl+Y?m*6UND#J|0Q>4MiqKd&jqSl07zeKw7T@+^Rw9q8 z{VN(H_$nAEEJDQZkb6tnYgokp{Dp{5k{1x6`_<%=7<|I?=KcqB1Nju#k}smUga69I znj9dlWVdEgODR3VCNjT!>)*ROMz?MKdsfE)yF3Fyu3TdmsrnIJra z1tcPHgUQp-Y@cnXACruqKtCh-|KRUeSO)ZWZym+NeP|^__4r2p-T8f2JSBFc%DjbO z!4Px|Iai7vpBS0%i9kE`0x1Egd{4mw8lC5MsCO-iy z_mLT`$&~OOJjb2`LdG356x^c6w%>lTZl9p(Zb3#AJ)@y^n5g|4VI;Ok6{lK zd_p+H#62{M2Twv_tYe~d-`qWPQlO2S)rO|~T^#4WN@@weReiuLGcsx@YmfSS>d^aY zoNf3v&4p$jJi~S&A>%5NA*bDUF>1+mu)3Uk zE@M-XN4XriGfaR2^yqLKsfs*%s20^y4?SYukiJ~^*h6Du-M)9XZGG2BoGd#sn7jd< zynZ0Tqnazm6XnXEAdfPVkD>}KB`l?CSOBn~DA$y22X-unaH z^4ci|<__pAwQxncNFJ*QF|E4*)q*58{?)qDMsIkV}b-G|{L6dr>OCS!=|5AHr@7gu?WystaXlg zcNO`Qh&GKPaiw{MnJ04692jK#z~t+{LW?PLU6jW47Sw}3C)yOtsc9@f6f6@GD-_G9 z$inotb_$kk5x66?ZAakF!G;FmTI}MXQE%?o1z|9G>bqnCTG6Y>!$#SarcVSGvY^WQcCE zBU%(9r^`hO#lhq*i0=bU%WQI!cORrS)8<+Mv?g2P&t8DmiT(~IEA1AC4hWek_2m>G zLng&aCp-vi6`cF}feu=VZxR{C6OSFlW(~#qsnkgt(c1+9E&LB@B@?n2&|Nu4Qj~dK zC^4A)5i&x1a*T-XNDm$WM<0@s{1l(Jqn3y=qIa08ID=w=8$?nome&}1hcpYC2#zQ? zkOP7Ddl~b+3N_UFFpuIOObj#DNqeaMkc@Gq6hMs4Bx!PJsgzx#1nnV?I(Rajm z3S`|?)ED7(uL@rvClvZ;3*#a1z*R-Vuk$4QNm6ta+RK>sIoUk*2ApJ9(fmg8X)Ek& z@ri7jqClE$Q-W)oh~MNmysGp-Ws&St7Y38!H~=%--XG>B?;sV?wjC!vcHYWW2Zj)n zOyo^uh+gUw&0m`BgULCVeAfCyJ59&zOJ9EeCd??DZ7s$vnI%K zj2TW_rf!=55Fr9m`|pJLG1_S(J|TU?-Q?D%$?bHP`yJ`Cx+g)d$I@50v)lqTNawJ8 z^BA$^OVf1S;Y-}LU-ef8k4I?Nliv4+l5<;iApt;Ykyr#ZJO$OI{NW>!gOH_Ict6;S`vzg>GlJ}A1!ZqfWncj*SC>u z+aa;)9bpohfkNwhK+T}$2V!DEO=prIHC>PKyB~p|A2VyGJ_qTbzo%{|q=O`;Ls;0H zii63sq~g24f`e&mS)-re0@bgfzAI5XHPqL|P7TYWSonnO*KrUai#Q9yVFMX~m&J2Y z6gJpJ4Sy3kFKi&!#Sh;WCfEZd1@SJiL!gOT1Wj>g_Wdi(st6qUkke=$!2-r$h>Z6?DbQu=l4ZkEN0_P zLYh9^QX+bH-H*~d7_KQZ9WiWCmT3x^PxSbH1Ot#of0lf2n9L!jqF}v@Sb0$_m(@^2 z#6~{a+wm)Z_e=h6xXEDhMv*h5W?$3DF$H(Z2q|s%V2F05sd|Ow$HTOz8Sp=bb%w6V z{`o_jX8NBPo~AMgm}Wfbip6M7P{mg<=G%PF)4ARrqyh7N&&M9H56^%k#ptUf zJSVP{{ZGkAkGBR-&&xfQ!$ZO)LJ9I*`V$|MPQ$(Mo|S?o-4!Ic4Aw~ljQR(ur>QwV zpHV?w{p3o`5#jZN$%`Ps&JWUN5Olf_sXz7ZJSzvsq!MfJgVMKoo{57Zy=QK7@qkoR zEl_D~+OzgyjJ-A=bxuA66o!Iwn;=upWqe``H^~~(@;$2__xUa`XXx|zREjBLw}j7< zWgNK^ewax+mXpZbii%B8nmAMks?k*$uky!{8OSV?Tl{z`d}?ql>NHI0gPG8`0Z z!da0_^SF2FetacN8ZTb}{w(LkUy2YsN^|$5w}h+OJ#%RLE#ZB%4kC)Zp^l$1Z}PC7 z^S3jh^3m(41&&(as0EH%;HU*Yfd%N->*}JrjnQzUXG`gV1>*T2>QN+x;t?1EA8q&& zo?>#=d7d=XEd9s!c(zBRqcL>;mQwuszr_d?wVJ_1r)S|pPlLSWMyaV#XM0SxNsrRN z--QZ$(Sik0JnA8Ur=}FnDimtTXSJYxJZl52vseyF`V&_QgXehyv#2=`R@GJc)+}0S zE~=^ZTzxfRTv-=YS04`B>bga%YAcsj`qmr{_u55*O=xP_S3Uz}!Gb_zqh?()#aXkA zP*E69;)q5gg|iHLCW}}6Ut-YHO6aL8s1zeuv(mrTIL>H{wuO!}I@(YhV-srhh$o^f z@Sw$2C0k1EXKwh6tWzgkK+o0-gI4_F*w_x-8+*sbb^+!CJ_|VX%Gg*t;17NQJU+F! z7Fo+az}3h?M)4K5`v410G>iejVeq{L=)r-=ZEqsG0o()F0{A-M4nWFu?guOZd={`4 z@Lj+#AU)sbHo)@$Uj|$WScW7%0{9}}Er1^Z?g5;F-S9rZy@2%ayCk3o@EGiQDgaLd zTo1SqunVvcupjU_zyZKvz+u2;*a+rKG>rQJ3js#}R{|b`!-ojq7XkYK`v7+VehY92 z@V9^?fXCsSBOhP$m<3o2cnx4JAf10C08hi=%TB;=0S*BE6mS?Y_FJ@jtYI|ZJaY!% zb%09&_X0Ko?!XD<4!~yt9|UZ|sq7Hoj{!dbya*puOu?rZeSl?vC*kvldcd0iI|0wZ zZm=JaKA9N+d>wEY@I34m4UFGbKo8*W0ha>ajsu4lz>jc}&<9wE{k1U(za{Fdecz%sxO0BZryz+prJ&<}VE zU>D#cfOi4D4EQ6!4*-7)I0au1%)#kk8Q=oITEKe11mH%%TL5jBRP z>;zl{xD&7za1Y>D0rvsYg>Tx5D{IRdBdaq%>(ogT^ZKxlCp`V!rXF+aEaF%?QPh}$ z+cNz1KZh~K95PPGUv@&lC6hn3DX+`8_>=|bl+KtAtf>D5KtJXxH$`ZHr@d+g@B>tz zFKX*%{O#K}Hby_|F?=WF-;llJ_+x6J5Q;>nD{D*jN}=h*uTMS4Fiutal3w)pDC*OG zKIc;y7$w8EZ9?_~www<@U-sJAm{3<h4D;(0~6p^fJ&d0lge@tTv){{aVl)K&PJ{ zS@gA%?g8p~{1Khn&$$u~m_dh~kg*;-_|(s)ue95s)2ceq&(rBao4${ASg6wzHhmQI zF4Q-5dbU)O?AQ+a0Oll>5J()d3JInRO5%_h%-J^=a|;I;Ivv-Nlv^dFB? ze-ixh5zwdU_3Q2W=YhT(bbR^KmY-cI7)ZaBpeI2W&pT1}y3(#60X-XQQYJfiQ2%Do zM^V2C_m=)-Z`Of$XuVqi8389xjckW_NY762EXRG$g$Sfd7s%QSHqvzzJa>$vOF<6e z1nBkP)$3b2M_9bKraJ*gHy&8QU>WpdR`5ln{b~q zglMJNJNs(8Ey@ij=Wx^aX3*aR{UN14C}WIu?9^c)4x#kkL*#6s&YxjXUHL(UZBKXg87 z(Pdx$g(MNr)!_LT@O)n9p|<3d68-H5&y(P}R_DpyD3qc841hiz`4ql}ZMT!{7jzF$ z!=TrKew|LIHndnsIo0>T)2Z`h%YaVfOL`uM9PDn~=Mb~j-|Vl5ri8APi(Lo4l>TI| zvUH^!?Xhv_H-ml%^h|xBzCH;04CH*7=pN9Y2fYsTcHF1v*dTQz9vZHD!1I94Bgf@y z#6|rjJ#)rekZqBiM<6Hbzw!Gh%#WPE zz-g2m|F#JecIOC2;(G&pcmHf`Y%lI}F3{Seae7+H^AHW~dC;ElyV6uX@;lOrrr(9& zar5sH&?BHXf!ESU_FpW1Bx4G4*6)JnBAo}iw4)6VaAlxB4|>WxC0*~9x>BEZp`EqJ zpC^+Id$hiTZ$cJXQ06pUkaZFAYy7U&)+c+7MehfF3+QfZ-T>(Bpu4Sk!=Sf;UYR1l z!jg|&n6VS|Ok+s4@PPjB!455I`AY=cTPCx&*=&S89x)*fP|0JERtr1UyKAw-g1NwMAmV>PV`53lRcKce6Faz|5 z$7z2l==Y36Zv_1o(A{$J>p}k>=;!F|a~!4dxfk@+h@)$DdbUiUiT*U`H-i3Ion9^N zN2sx}tmD?_Zp$+6&q5$ViT;jXfcvW4cB5NEo^S?`;e0&Aye|t;j9DiY0lOeKU~JK< z&&BR@w04{g^1=^xU0QstCOda@qVY!d$^Sah=$%0K z_fE+D%|zqz2@hwzIMKL1H}?kIoebi)YdzM5rx3B@c)|y)both z^NZEMD2y}0rjirfv!k3FA*w#Cr1!0>fF4ex+ZvmtF_qQ?GKa7JweZ=J*_&kiRF)k}T@ezu!#|Rtn zuUuCBmbL!x{_p2;aY`)qNK6I8YKH3>wlnNv*vGJ+;Vy;)42KvFGaO-vmw1RPpP`3g zF~bUm)eP4&Y-iZTu#aIs!(9vq7!ENUW;nu7y<8+8xhY*9hQ$mk7*;b}&#;|g7sEb= z{S0?89AG%aaG2o;L*sL@-F$`~hQ$mk7*;b}&#;|g7sEb={S0?89AG%aaG0TN^^^af z*Cp$!xTYlG+58JUg>?-bZHW$#*NbQE7ti)~h@$tJl9Hn0vRRB)H8R62pmU7($DCA} zZ}g;nI4Ot+04km!+1|&DxMy_M*PnBP2nyJr;XKLmi(k2 zU3K`&GETPQn?T~ftMNy2)ViSXJ8+X_e8!5G3V$DNGU@+)!GDsGCl1!AuDo6p_|uHl z4t?Ha{$m~dhZujH15XCd!kc;~F&;;T;yMcrk^YN{WLfNial4lBYMoQ@-_8CV;LpOR zkA*=gNB=)lf3aJ}^=U)B=TGt9Cggn9aK@{<1^yH(zAJw0K{LL8Xb|}6=+}pHB&RqV z!7cWp0^fC^#9zmP^0Fmft=r-(0kqQ@U%yx~viXcl8Nb3W@oGJIi190zNc=+*7%wya z9iK#qvk2TSfPa&o$1(nL=1&06OA%uv=w|-bi)Fc;so!RNn>dKWXNHV_k@4-zBtq$V z5*&cq-N%dyUkrSvc9$@J7fl>o;xjnFHW&Ub=FjK+L7e@7|0gc|dzs&9pK`3K5AShBJUvileoXrxDFlH6aF-| z|7ylp0Izh=#2c$!@FvT7Z;|9y?Zz2Dy;$O>v#{+ha&Bk-Jv<DHKX;KtC_RT5 z-{g~cl}G(2ZalD$(ZvE7jDY_{>X{>Mi~*mizb7J*%7j0~1wYRPza4n8vvdC5D)6Z~ zQfZfqoTpgMZQ=mkFjO4)xeNb(=6A+{4;kOdcIM$XCgo-B?^+~s^xiVHZmPWTGcNpR z34Fd0oh|#em%Dhb3xCW7e;e>*w;L;@0Q!uHF8aKL@U#80tmgaQ7{6w|#4G!pj0HH; zI2Hm=a%OlX|G!CKT)_BWaJ-$t_%)30V*FRl z14F8K2E@K#j|O7dd0hKg98>iRF9_ z8z<`5DI5n>f0qJJdKPp^My2O^=6A-Q81R|;yVV7MC*iYCG}Qi))iJ)|!ao2!>G|Oj z$w{BA7^mapvm9^;+sLK!y3 zndDRePkJup@j^Hi*Lub~*V$`a&p$m zXOjO7=Ko-sY?Zrh?03PReWGl4xJ>dZKd%5jll*neU(WJ**)wi&;eVL$*>HA`l&}8Z z4Lrrww0w!>&t-iAT;XNLJLAtN;~!*w&SCx#l+W~D&+CAv@!iSt+1$og82@6C6tIWo z+|T%&5{Y=6@q>*2jbpsL*uaqdt2zHs@#IqAQ6=rV%mp82InMlTE92J{OHt>s#JgSO zJjndcy!|B?{x_Ka29~e(DgR)+bG?{6CG&eyX9Az8zhy4?&&L z-kCo<>>_7?`JH*!UdA7C#Jw{_97xx*4S3SWndjWZ_@~*PCRg1JJna{p`S6p>?~D)F z>Vy9@qyEdOZRY|{?LJm2@oN6gWc(H$z`MEHV#XINmWYcP-@^DO+0UVdxO#!lG>$)H ze&;+5VO^y-`RzhkpT0Xp*Ne>mW3Mc;IgDSs$R7os`s<7jIVa2hI@ePlO4Q6`Og486aPiPlm6N4C!Ne6a^b&<`HT2`V>R>N z%J`QZ^W_c3f0y&&YnlIVF7i);p)%=N2t4WO-0wHL@OQf4yIIbk%cLUptWQ7i9=_MX zkC@*%U*2Z?zc|M0Y)t7)`g>jQeiwWIc|EZ(h6EV>;^=lgNls^<-B^&2(X3PPeCBG7CA5l?h9H5CO7`+ekQ0zY`8HRV5by8Bn}b)Dn`Ssl5}31; z-@1&Kh6iHw7Hja#4L7$%V|ZEcWvk}n?dokEcnfgn$`UU$4>bikA_=@-9Pa^ck4D15 z&Gf40GLZ0Y-~?V*O`^l}dUTZVR(8Cm86?(rPcGHZ^ErWrJ7z z`Ic0A9TJ2-;HfEtBGtIzR*I>Oju5q?cPT>?H6^Gi%!*#q+u&1Q^Dalw>(yT1&I2S& ztwxv%PODoT%g}S7x5bb_twkpF+&9;(qCUvijl;%sp#9H@7xKBUGC_L-srvZ44p1Wxa2KOBFdaU$Q_NCMTHzRlK9YZOuC z|6=q@K6docaO(yWuG)csDEzHBr4PlvYRl>?8;X6tc`$GbI*CEGUQnOv?JHZ0eV5p^ z+{cPv3m+m^QH>v&8!joSBp-$|Z*1@(u80Wiue%1pBN|0CDbgR-xiL@m@5as z9?{l#GmQvlIMJKJ6l_IYQeL~FrdYH^O-T+Btx!k)d>B=OW-Qdi_2x=!DSjTDVJ=wu zgj(AzeYhiY#NuI3d0$yPyd^|ksk{_%yfNHncEm%C4tGXR2!nxbSMQ#02sMK@7)S(L zD(u&_3wzZh=F!XJJH1|S2|O1o0~UdBTXSU)Lk9~6VrC*12q)r|L0?S(|M}(!7T-oa zbkn=u*-9dMdr8TZSJ+E#yhom184vZe`A3~nwaLcHn&^QRN0`I@*|fGqu!&V%LPd-& zwZa1;9KmP}gxescCQ%k@Ym8*-ppSxgsWd|rb_fMpE3sY`o4%U4rruxf9IweCGt?Oj zwbR1sFfUwWj+kCPYq??PA?xa^#Np2ydk#V=wo00(C>xTQ6Hy*hW>zjIVh_8TSU~6T z@7v{Mp{XR$!Hw1BBK%=pmLyQhkp+my0%!|qFyaWCYHds(yJ9J*CSi}KRL5+LN6i+b zBN62jkvN7WD%SjzWu6Cpju>2r%Jaz!%?;tUMoVE$jNPV>XNvTB72ubCz6jH|$h@q! z()mk$nCr-A4Ed$*J@#yw-;NwF5yueep#h65Ta4oinVW1fEs#l2{J=GtAHa;^@^aOI&C(0cA7|e;?Xvwhl$PRMx??b0IFa|lN)mj50j8l zPR{dK$ZZ->%8UsU2{%yW2%rZv6RjSUma+UaCq{s`rVWxS%KFmMI3!n;Qeiqd6E=PE zx&-v}+)d;R<0Wl#ok^RrAEpGRFO0yssqKEYZsTzIJmRFtsYxZVaLUz;Iw$fSS(Gi(V#nE(BRL{pP(9?4RA%xP z({nO3CzESJ0O@=;v&uAsbog)^ke#5-*a?GY;5)Dqx`mJ*1>>Sgam(k7J^ z4LN$qxx{_vu#{E_Q_Q@qF;blp38>D;YzC|~Uvi2)OS!VQH8yGU!k#$JWY*GCWV2~{ zrlh*USAo$JTYX+Rl0umi)+8eFN*avR>><#irpL10H3ccvAI2jt}Id^S`3KVXx2or z%v3MKdR1fkGIUAb&K>Ti1|y_x)jp8~uO)$;jTQ>bakVsXM4{ZyxljrBgk_E})?okI zihz$;kMuj(vLSWFLb#Xb8fIP2R)SxsBqIU56!4rJOq+|@PnXt-S4k; zylh$J3Mkr<26K?sSf1@xcud=&9J%9SQ9LrwU17U!+JajuH_viupwP_$4mpZgz^DW0 zmvDIsE80ML=OE3L8?IO=jn6-cL*zZ zi*V#QtMpj0&DR~>PF>TSM{|7DTd$Xnh%oSEabIf6ga9FScOoMs3#9k=up+(~aBS#E zgh*oKDUFrH@G&9wqry*=YV*mbp;;Vy$(ac!8fO(%y`v_S4DURSDAx8bPQg^~87h=($P-d5@O_7!`D70sZkvgE+rK!#k2BcFDcbL!Znc+ z61(yzS;e)(P2pki`AkPTwKZvb)(l%ZJ%puB4EvZJ^FrTsV@T|fkf!5P91 zXG&`a9CK8brDg*@g1|{Q&uKAn?b)XHiNZ2M4=LP^<1B1B|H*S&j@vv17?u^5iw;)zfUc@KRERZH2($2+*T9vq?1dA+nxkRMghp*T;f zR($$Y*R~0VBjy?`)vcil{GP-trH{N2g((konYCIzgPhc5CVlMZB;wpVZH$k6Mk%|% z;Nn~;ZK~VbH0j~vM0c51RC~+#!<>u@vtp8;1w12OS8EZ9|el#g+AdUCw6n;!w9Hip|-bX zhy;iAF~KL=nqgST^=WA65Rm%0HZ3fQd?0kCG_=TR#nO`+4uzLdG!f%%A9`uK@zi5e z=L$&ccZyk!B80C*paC!uldwhIAyS26?M6{sG!ZJo2f9V=F?!T$VzY*7=m9oRDIMvJQG^fWX+zH60r+PCzV2b*D_Ho=mAne@`y9Fy#MduUF5=a%&!I38 zf2w{t*H=(|Z%ft5Q#TCf0_yc!xW0lj9Q^$CFbhlHL(%K2-{&dlu{h<8v;OCS#^W@j zN`LixUi5D5?&FH2BiT;X$JepM6~_P6W!1j={jq}T_r{W2 z%24+Nuf!kymRHqRzu#5xtIVwQS9}Uy13LXSSe4c9gB9Gx^+|uyQ|ZrWqZc=1Q&nI6 zURgo)du7$Ws;~NgJJ(;#0@d%I6;!{Mruz5_mDRqge-ChES0&%@pg@;L{7>JQOu3xn ze+Q^~eUC@7D>%gdsD$M6je_@~tk)m;oMcc?@wwF}`|9<@1KEgqhO9C0G421rQD1%E zT)}szNjd6&r#?S%)K|ZcP!M0|Pr01-`zhB~-*~@w}S6DI-vYd$=vU#e_l{hEa=eR+5TU^j-LjIxj{A6^9Ty~hXc<3 zs`eF}0QvZezg1s7ub`0YD?XAZ{+m z_H+GW9vGVcbg6cgobLdqx38XeFw`p84OL&3?D|U1Oo#qP7jv@W9#xT{s;AKBqCVl2 z{uN!4;^F!Qq?~qDX!mqm%V9?ynP7Y@6#{UuENoGAT!l}^P7@mzN3PpX#6i(s8`7V literal 0 HcmV?d00001 diff --git a/tests/example.cpp b/tests/example.cpp new file mode 100644 index 00000000..0bff92d1 --- /dev/null +++ b/tests/example.cpp @@ -0,0 +1,50 @@ + +/*++ +Copyright (c) 2015 Microsoft Corporation + +--*/ + +#include +#include +#include +#include "z3++.h" + +using namespace z3; + + +void slhv_cases() { + context c; + expr hvar1 = c.hvar_const("hvar1"); + expr hvar2 = c.hvar_const("hvar2"); + expr uplushvars = uplus(hvar1, hvar2); + expr emp = c.emp_const(); + expr nil = c.nil_const(); + expr data1 = c.int_const("datavar"); + expr locvar = c.locvar_const("addrvar"); + std::cout << data1.get_sort() << std::endl; + expr datar = data_record(data1); + expr pt_test = points_to(locvar, data1); + std::cout << hvar1 << std::endl; + std::cout << data1 << std::endl; + std::cout << uplushvars << std::endl; + std::cout << pt_test << std::endl; + solver s(c,"SLHV"); + expr constr1 = (hvar1 == hvar2); + s.add(constr1); + s.check(); +} + + +int main() { + + try { + slhv_cases(); std::cout << "\n"; + std::cout << "done\n"; + } + catch (exception & ex) { + std::cout << "unexpected error: " << ex << "\n"; + } + Z3_finalize_memory(); + return 0; + +} From 5c843a91ea18ff9870a0137ca9ab39b2bedbf6e6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 19 Jul 2024 09:21:53 +0800 Subject: [PATCH 006/126] add z3-slhv dec_check --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 15 +++++++++++++-- src/solvers/z3-slhv/z3_slhv_conv.h | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index bc78d7ba..5987766a 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -63,7 +63,7 @@ z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here int_encoding = true; - solver = z3::solver(z3_ctx); + solver = z3::solver(z3_ctx, "SLHV"); log_status("z3_slhv_convt created"); } @@ -82,7 +82,17 @@ z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } // } smt_convt::resultt z3_slhv_convt::dec_solve() { - return P_SMTLIB; + log_status("z3-slhv debug: before slhv check"); + z3::check_result result = solver.check(); + log_status("z3-slhv debug: after check"); + + if (result == z3::sat) + return P_SATISFIABLE; + + if (result == z3::unsat) + return smt_convt::P_UNSATISFIABLE; + + return smt_convt::P_ERROR; } const std::string z3_slhv_convt::solver_text() { @@ -198,6 +208,7 @@ smt_astt z3_slhv_convt::mk_nil() { return new_ast(z3_ctx.nil_const(), this->mk_intloc_sort()); } smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { + log_status("here"); return new_ast( z3::points_to( to_solver_smt_ast(a)->a, diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index b40e4ff6..6c901aec 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -34,7 +34,7 @@ class z3_slhv_convt : public z3_convt { // interfaces of smt_convt need implementation // void assert_ast(smt_astt a) override; - resultt dec_solve() override; + smt_convt::resultt dec_solve() override; const std::string solver_text() override; // constant and operators From adaa3f7e0debcf94c8434f930bd66399e8e6f8c7 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 19 Jul 2024 10:20:47 +0800 Subject: [PATCH 007/126] add print smt, using --output --- benchmark/case_0.c | 6 ++--- src/solvers/z3-slhv/z3_slhv_conv.cpp | 36 ++++++++++++++++++++++++---- src/solvers/z3-slhv/z3_slhv_conv.h | 3 +++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index f39ab73b..284605b9 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -3,9 +3,9 @@ int main(){ // int whatever; int * data = malloc(2*sizeof(int)); - int * data2 = malloc(sizeof(int)); - int i = *(data + 1); - free(data); + // int * data2 = malloc(sizeof(int)); + // int i = *(data + 1); + // free(data); // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 5987766a..0156b660 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -354,6 +354,38 @@ z3_slhv_convt::convert_slhv_opts( } } + +void z3_slhv_convt::dump_smt() { + const std::string &path = options.get_option("output"); + if(path == "-") { + print_smt_formulae(std::cout); + } else { + std::ofstream out(path); + print_smt_formulae(out); + } +} + +void z3_slhv_convt::print_smt_formulae(std::ostream& dest) { + auto smt_formula = solver.to_smt2(); + std::replace(smt_formula.begin(), smt_formula.end(), '\\', '_'); + Z3_ast_vector __z3_assertions = Z3_solver_get_assertions(z3_ctx, solver); + // Add whatever logic is needed. + // Add solver specific declarations as well. + dest << "(set-logic SLHV)" << std::endl; + dest << "(set-info :smt-lib-version 2.6)\n"; + dest << "(set-option :produce-models true)\n"; + dest << "(declare-fun emp () IntHeap)" << std::endl; + dest << "(declare-fun nil () IntLoc)" << std::endl; + dest << "; Asserts from ESMBC starts\n"; + dest << smt_formula; // All VCC conditions in SMTLIB format. + dest << "; Asserts from ESMBC ends\n"; + dest << "(get-model)\n"; + dest << "(exit)\n"; + log_status( + "Total number of safety properties: {}", + Z3_ast_vector_size(z3_ctx, __z3_assertions)); +} + // smt_astt z3_slhv_convt::convert_ast_slhv(const expr2tc &expr) { // log_status("== convert ast slhv"); // expr->dump(); @@ -888,7 +920,3 @@ z3_slhv_convt::convert_slhv_opts( // void z3_slhv_convt::print_smt_formulae(std::ostream &dest) { // log_status("TODO: slhv print smt"); // } - -// void z3_slhv_convt::dump_smt() { -// log_status("TODO: slhv dump smt"); -// } \ No newline at end of file diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 6c901aec..9111538e 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -59,7 +59,10 @@ class z3_slhv_convt : public z3_convt { smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; + void dump_smt() override; + private: + void print_smt_formulae(std::ostream& dest); std::vector assertions; }; From f63115a6046eca9af6a24600002ac6475cfab1a5 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 19 Jul 2024 14:02:12 +0800 Subject: [PATCH 008/126] update --- src/goto-symex/symex_main.cpp | 2 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 738e3b33..3a61ba8a 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1217,7 +1217,7 @@ void goto_symext::add_memory_leak_checks() log_status("memleak encoding"); for (auto const &it : dynamic_memory){ log_status("allocated object {}: ", it.name ); - expr2tc deallocated = notequal2tc(it.obj, constant_intheap2tc(get_intheap_type(), true)); + expr2tc deallocated = equality2tc(it.obj, constant_intheap2tc(get_intheap_type(), true)); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); cur_state->rename(cond); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 0156b660..21f43b18 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -374,8 +374,10 @@ void z3_slhv_convt::print_smt_formulae(std::ostream& dest) { dest << "(set-logic SLHV)" << std::endl; dest << "(set-info :smt-lib-version 2.6)\n"; dest << "(set-option :produce-models true)\n"; - dest << "(declare-fun emp () IntHeap)" << std::endl; - dest << "(declare-fun nil () IntLoc)" << std::endl; + dest << "(declare-datatype pt_record_0 ((Pt_R_0 (loc IntLoc))))" << std::endl; + dest << "(declare-datatype pt_record_1 ((Pt_R_1 (data Int))))" << std::endl; + // dest << "(declare-fun emp () IntHeap)" << std::endl; + // dest << "(declare-fun nil () IntLoc)" << std::endl; dest << "; Asserts from ESMBC starts\n"; dest << smt_formula; // All VCC conditions in SMTLIB format. dest << "; Asserts from ESMBC ends\n"; From f00465244adfb37e29cdb4bf4649c6a43d09b42d Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 21 Jul 2024 18:53:16 +0800 Subject: [PATCH 009/126] update --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 668 +-------------------------- src/solvers/z3-slhv/z3_slhv_conv.h | 20 - 2 files changed, 1 insertion(+), 687 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 21f43b18..e63587f2 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -42,23 +42,6 @@ smt_convt *create_new_z3_slhv_solver( return conv; } -// smt_astt z3_slhv_smt_ast::update(smt_convt *ctx, -// smt_astt value, -// unsigned int idx, -// expr2tc idx_expr) -// const { -// log_status("slhv_smt does not support update"); -// return nullptr; -// } -// smt_astt z3_slhv_smt_ast::project(smt_convt *ctx, unsigned int elem) const { -// log_status("slhv_smt does not support project"); -// return nullptr; -// } -// void z3_slhv_smt_ast::dump() const { -// std::string print_str = a.to_string(); -// log_status("{}\n sort is {}", print_str, a.get_sort().to_string()); -// } - z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here @@ -69,18 +52,6 @@ z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } -// void z3_slhv_convt::push_ctx() { - -// } - -// void z3_slhv_convt::pop_ctx() { - -// } - -// void z3_slhv_convt::assert_ast(smt_astt a) { -// this->assertions.push_back(a); -// } - smt_convt::resultt z3_slhv_convt::dec_solve() { log_status("z3-slhv debug: before slhv check"); z3::check_result result = solver.check(); @@ -99,108 +70,6 @@ const std::string z3_slhv_convt::solver_text() { return "Z3-slhv"; } -// smt_astt z3_slhv_convt::mk_smt_int(const BigInt &theint) { -// smt_sortt s = mk_int_sort(); -// if (theint.is_negative()) -// return new_ast(z3_ctx.int_val(theint.to_int64()), s); - -// return new_ast(z3_ctx.int_val(theint.to_uint64()), s); -// } - -// smt_astt z3_slhv_convt::mk_smt_real(const std::string &str) { -// log_error("SLHV does not support real yet"); -// abort(); -// return nullptr; -// } - -// smt_astt z3_slhv_convt::mk_smt_bv(const BigInt &theint, smt_sortt s) { -// log_error("SLHV does not support bv"); -// abort(); -// return nullptr; -// } -// smt_astt z3_slhv_convt::mk_smt_bool(bool val){ -// return new_ast(z3_ctx.bool_val(val), mk_bool_sort()); -// } - -// smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s){ -// switch (s->id) -// { -// case SMT_SORT_BOOL: { -// z3::expr bexpr = this->z3_ctx.bool_const(name.c_str()); -// return new_ast(bexpr, s); -// } -// case SMT_SORT_INT: { -// z3::expr ivar = this->z3_ctx.int_const(name.c_str()); -// return new_ast(ivar, s); -// } -// case SMT_SORT_INTHEAP: { -// z3::expr hvar_expr = this->z3_ctx.hvar_const(name.c_str()); -// return new_ast(hvar_expr, s); -// } -// case SMT_SORT_INTLOC: { -// z3::expr lvar_expr = this->z3_ctx.locvar_const(name.c_str()); -// return new_ast(lvar_expr, s); -// } -// default: -// log_status("unsupported sort in symbol making"); -// break; -// } -// } -// smt_astt z3_slhv_convt::mk_extract(smt_astt a, unsigned int high, unsigned int low){ -// log_error("SLHV does not support bv"); -// abort(); - -// } -// smt_astt z3_slhv_convt::mk_sign_ext(smt_astt a, unsigned int topwidth){ - -// log_error("SLHV does not support bv"); -// abort(); -// } -// smt_astt z3_slhv_convt::mk_zero_ext(smt_astt a, unsigned int topwidth){ - -// log_error("SLHV does not support bv"); -// abort(); -// } -// smt_astt z3_slhv_convt::mk_concat(smt_astt a, smt_astt b){ -// log_error("SLHV does not support bv"); -// abort(); -// } -// // logical connections -// smt_astt z3_slhv_convt::mk_ite(smt_astt cond, smt_astt t, smt_astt f){ - -// } - -// smt_astt z3_slhv_convt::mk_or(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_and(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_implies(smt_astt a, smt_astt b) { -// z3::expr premise = to_solver_smt_ast(a)->a; -// z3::expr conclusion = to_solver_smt_ast(b)->a; -// z3::expr impl = z3::implies(premise, conclusion); -// return new_ast(impl, boolean_sort); -// } -// smt_astt z3_slhv_convt::mk_not(smt_astt a) { -// z3::expr noteq = !to_solver_smt_ast(a)->a; -// return new_ast(noteq, boolean_sort); -// } -// // numeral assertions -// smt_astt z3_slhv_convt::mk_lt(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_le(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_gt(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_ge(smt_astt a, smt_astt b) {} -// smt_astt z3_slhv_convt::mk_eq(smt_astt a, smt_astt b) { -// assert(a->sort->id == b->sort->id); -// z3::expr lhs = to_solver_smt_ast(a)->a; -// z3::expr rhs = to_solver_smt_ast(b)->a; -// z3::expr z3eq = (lhs == rhs); -// return new_ast(z3eq, boolean_sort); -// } -// smt_astt z3_slhv_convt::mk_neq(smt_astt a, smt_astt b) {} -// // numeral terms -// smt_astt z3_slhv_convt::mk_add(smt_astt a, smt_astt b) { - -// } - -// constant and operators smt_astt z3_slhv_convt::mk_emp() { return new_ast(z3_ctx.emp_const(), this->mk_intheap_sort()); } @@ -386,539 +255,4 @@ void z3_slhv_convt::print_smt_formulae(std::ostream& dest) { log_status( "Total number of safety properties: {}", Z3_ast_vector_size(z3_ctx, __z3_assertions)); -} - -// smt_astt z3_slhv_convt::convert_ast_slhv(const expr2tc &expr) { -// log_status("== convert ast slhv"); -// expr->dump(); -// log_status("===="); -// smt_cachet::const_iterator cache_result = smt_cache.find(expr); -// if (cache_result != smt_cache.end()) { -// log_status("found -------------------::"); -// expr->dump(); -// return (cache_result->ast); -// } - -// if (is_vector_type(expr)) { -// log_status("WARNING!!!: does not support convert ast slhv vector type"); -// } - -// std::vector args; -// args.reserve(expr->get_num_sub_exprs()); - -// switch(expr->expr_id) { - -// case expr2t::with_id: -// case expr2t::constant_array_id: -// case expr2t::constant_vector_id: -// case expr2t::constant_array_of_id: -// case expr2t::index_id: -// case expr2t::address_of_id: -// case expr2t::ieee_add_id: -// case expr2t::ieee_sub_id: -// case expr2t::ieee_mul_id: -// case expr2t::ieee_div_id: -// case expr2t::ieee_fma_id: -// case expr2t::ieee_sqrt_id: -// case expr2t::pointer_offset_id: -// case expr2t::pointer_object_id: -// case expr2t::pointer_capability_id: -// break; // Don't convert their operands - -// default: -// { -// // Convert all the arguments and store them in 'args'. -// unsigned int i = 0; -// expr->foreach_operand( -// [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast_slhv(e); }); -// } -// } - -// log_status(" ------------- covert args ends ------------- "); -// expr->dump(); - -// smt_astt a; -// switch (expr->expr_id) -// { - -// case expr2t::constant_intheap_id: { -// const constant_intheap2t& intheap = to_constant_intheap2t(expr); -// log_status("{}", intheap.is_emp); -// expr->dump(); -// if (intheap.is_emp) { -// a = mk_emp(); -// } else { - -// } -// break; -// } -// case expr2t::constant_intloc_id: { -// const constant_intloc2t& intloc = to_constant_intloc2t(expr); -// if (intloc.value.is_zero()) { -// a = mk_nil(); -// } else { - -// } -// break; -// } -// case expr2t::points_to_id: { -// assert(args.size() == 2); -// a = mk_pt(args[0], args[1]); -// break; -// } -// case expr2t::uplus_id: { -// assert(args.size() >= 2); -// a = args[0]; -// for (int i = 1; i < args.size(); i++) { -// a = mk_uplus(a, args[i]); -// } -// break; -// } -// case expr2t::locadd_id: { -// assert(args.size() == 2); -// a = mk_locadd(args[0], args[1]); -// break; -// } -// case expr2t::constant_fixedbv_id: -// case expr2t::constant_floatbv_id: -// case expr2t::constant_string_id: -// { -// log_status("WARNING!!!: not supported expr id"); -// std::cout << expr->expr_id << std::endl; -// break; -// } -// case expr2t::constant_int_id: -// { -// const constant_int2t &theint = to_constant_int2t(expr); -// a = mk_smt_int(theint.value); -// break; -// } -// case expr2t::constant_bool_id: -// { -// const constant_bool2t &thebool = to_constant_bool2t(expr); -// a = mk_smt_bool(thebool.value); -// break; -// } -// case expr2t::symbol_id: -// { -// const symbol2t &sym = to_symbol2t(expr); -// std::string name = sym.get_symbol_name(); -// smt_sortt sort = convert_sort_slhv(sym.type); -// std::cout << "symbol name: " << name << std::endl; -// std::cout << "symbol thename: " << sym.thename << std::endl; -// std::cout << "sort name: " << sort->id << std::endl; -// a = mk_smt_symbol(name, sort); -// break; -// } -// case expr2t::constant_vector_id: -// { -// log_status("WARNING!!!: not supported constant vector id convert ast"); -// std::cout << expr->expr_id << std::endl; -// break; -// } - -// case expr2t::constant_array_id: -// { -// log_status("WARNING: constant array id encountered"); -// break; -// } -// case expr2t::constant_array_of_id: -// { -// const array_type2t &arr = to_array_type(expr->type); -// const constant_array_of2t &aof_expr = to_constant_array_of2t(expr); -// const expr2tc& init = aof_expr.initializer; -// std::cout << "array of argument type id: " << init->type->type_id << std::endl; -// if(is_constant_number(init)) { -// a = this->mk_emp(); -// } else { -// log_status("WARNING: initializer of array of not supported"); -// } - -// break; -// } -// case expr2t::add_id: -// { -// const add2t &add = to_add2t(expr); -// if ( -// is_pointer_type(expr->type) || is_pointer_type(add.side_1) || -// is_pointer_type(add.side_2)) -// { -// log_status("TODO: ptr adding not impled yet"); -// } -// else -// { -// a = mk_add(args[0], args[1]); -// } -// } -// case expr2t::sub_id: -// { -// const sub2t &sub = to_sub2t(expr); -// if ( -// is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || -// is_pointer_type(sub.side_2)) -// { -// log_status("TODO: ptr sub not impled yet"); -// } -// else -// { -// a = mk_sub(args[0], args[1]); -// } -// break; -// } -// case expr2t::mul_id: -// { -// log_status("WARNING: mul_id not supported"); -// break; -// } -// case expr2t::div_id: -// { -// log_status("WARNING: div_id not supported"); -// break; -// } -// case expr2t::ieee_add_id: -// case expr2t::ieee_sub_id: -// case expr2t::ieee_mul_id: -// case expr2t::ieee_div_id: -// case expr2t::ieee_fma_id: -// case expr2t::ieee_sqrt_id: -// { - -// log_status("WARNING: ieee expr2t not supported"); -// break; -// } -// case expr2t::modulus_id: -// { -// log_status("WARNING: modulus_id not supported"); -// break; -// } -// case expr2t::index_id: -// { -// log_status("TODO: index id not impled yet"); -// break; -// } -// case expr2t::with_id: -// { -// const with2t &with = to_with2t(expr); -// log_status("TODO: with id not impled yet"); -// // We reach here if we're with'ing a struct, not an array. Or a bool. -// if (is_struct_type(expr) || is_pointer_type(expr)) -// { -// log_status("expr struct/ptr type"); -// } -// else if (is_union_type(expr)) -// { -// log_status("expr union type"); -// } -// else -// { -// log_status("expr other type"); -// } -// break; -// } -// case expr2t::member_id: -// { -// log_status("TODO: member_id not impled yet"); -// break; -// } -// case expr2t::same_object_id: -// { -// log_status("TODO: same_object_id not impled yet"); -// break; -// } -// case expr2t::pointer_offset_id: -// { -// log_status("TODO: pointer_offset_id not impled yet"); -// break; -// } -// case expr2t::pointer_object_id: -// { -// log_status("TODO: pointer_object_id not impled yet"); -// break; -// } -// case expr2t::pointer_capability_id: -// { -// log_status("TODO: pointer_capability_id not impled yet"); -// break; -// } -// case expr2t::typecast_id: -// { -// log_status("TODO: typecast_id not impled yet"); -// break; -// } -// case expr2t::nearbyint_id: -// { -// log_status("WARNING: nearbyint_id not supported"); -// break; -// } -// case expr2t::if_id: -// { -// // Only attempt to handle struct.s -// const if2t &if_ref = to_if2t(expr); -// args[0] = convert_ast(if_ref.cond); -// args[1] = convert_ast(if_ref.true_value); -// args[2] = convert_ast(if_ref.false_value); -// a = args[1]->ite(this, args[0], args[2]); -// break; -// } -// case expr2t::isnan_id: -// { -// log_status("WARNING: isnan_id not supported"); -// break; -// } -// case expr2t::isinf_id: -// { -// log_status("WARNING: isinf_id not supported"); -// break; -// } -// case expr2t::isnormal_id: -// { -// log_status("WARNING: isnormal_id not supported"); -// break; -// } -// case expr2t::isfinite_id: -// { -// log_status("WARNING: isfinite_id not supported"); -// break; -// } -// case expr2t::signbit_id: -// { -// log_status("WARNING: signbit_id not supported"); -// break; -// } -// case expr2t::popcount_id: -// { -// log_status("WARNING: popcount_id not supported"); -// break; -// } -// case expr2t::bswap_id: -// { -// log_status("WARNING: bswap_id not supported"); -// break; -// } -// case expr2t::overflow_id: -// { -// log_status("WARNING: overflow_id not supported"); -// break; -// } -// case expr2t::overflow_cast_id: -// { -// log_status("WARNING: overflow_cast_id not supported"); -// break; -// } -// case expr2t::overflow_neg_id: -// { -// log_status("WARNING: overflow_neg_id not supported"); -// break; -// } -// case expr2t::byte_extract_id: -// { -// log_status("WARNING: byte_extract_id not supported"); -// break; -// } -// case expr2t::byte_update_id: -// { -// log_status("WARNING: byte_update_id not supported"); -// break; -// } -// case expr2t::address_of_id: -// { -// log_status("WARNING: address_of_id not supported"); -// break; -// } -// case expr2t::equality_id: -// { -// a = args[0]->eq(this, args[1]); -// break; -// } -// case expr2t::notequal_id: -// { -// auto neq = to_notequal2t(expr); -// a = args[0]->eq(this, args[1]); -// a = mk_not(a); -// break; -// } -// case expr2t::shl_id: -// { -// log_status("WARNING: shl_id not supported"); -// break; -// } -// case expr2t::ashr_id: -// { -// log_status("WARNING: ashr_id not supported"); -// break; -// } -// case expr2t::lshr_id: -// { -// log_status("WARNING: lshr_id not supported"); -// break; -// } -// case expr2t::abs_id: -// { -// log_status("WARNING: abs_id not supported"); -// break; -// } -// case expr2t::lessthan_id: -// { -// log_status("TODO: lessthan_id not impled yet"); -// break; -// } -// case expr2t::lessthanequal_id: -// { -// log_status("TODO: lessthanequal_id not impled yet"); -// break; -// } -// case expr2t::greaterthan_id: -// { -// log_status("TODO: greaterthan_id not impled yet"); -// break; -// } -// case expr2t::greaterthanequal_id: -// { - -// log_status("TODO: greaterthanequal_id not impled yet"); -// break; -// } -// case expr2t::concat_id: -// { -// log_status("WARNING: concat_id not supported"); -// break; -// } -// case expr2t::implies_id: -// { -// a = mk_implies(args[0], args[1]); -// break; -// } -// case expr2t::bitand_id: -// case expr2t::bitor_id: -// case expr2t::bitxor_id: -// case expr2t::bitnand_id: -// case expr2t::bitnor_id: -// case expr2t::bitnxor_id: -// case expr2t::bitnot_id: -// { -// log_status("WARNING: bit operations not supported"); -// break; -// } -// case expr2t::not_id: -// { -// assert(is_bool_type(expr)); -// a = mk_not(args[0]); -// break; -// } -// case expr2t::neg_id: -// { -// const neg2t &neg = to_neg2t(expr); -// a = mk_neg(args[0]); -// break; -// } -// case expr2t::and_id: -// { -// a = mk_and(args[0], args[1]); -// break; -// } -// case expr2t::or_id: -// { -// a = mk_or(args[0], args[1]); -// break; -// } -// case expr2t::xor_id: -// { -// a = mk_xor(args[0], args[1]); -// break; -// } -// case expr2t::bitcast_id: -// { -// log_status("WARNING: bitcast_id not supported"); -// break; -// } -// case expr2t::extract_id: -// { -// log_status("WARNING: extract_id not supported"); -// break; -// } -// case expr2t::code_comma_id: -// { -// log_status("WARNING: code_comma_id not supported"); -// break; -// } -// default: -// log_error("Couldn't convert expression in unrecognised format\n{}", *expr); -// abort(); -// } - -// struct smt_cache_entryt entry = {expr, a, ctx_level}; -// smt_cache.insert(entry); - -// log_status("==== converted reuslt: "); -// a->dump(); -// log_status("===="); -// return a; -// } - -// smt_sortt z3_slhv_convt::convert_sort_slhv(const type2tc &type) { -// std::cout << "convert sort slhv, type name: " << type->type_id << std::endl; -// smt_sort_cachet::const_iterator it = sort_cache.find(type); -// if (it != sort_cache.end()) -// { -// return it->second; -// } - -// smt_sortt result = nullptr; -// switch (type->type_id) -// { -// case type2t::bool_id: -// result = boolean_sort; -// break; - -// case type2t::struct_id: -// { -// log_status("INFO: convert struct_id sort"); - -// break; -// } -// case type2t::code_id: -// case type2t::pointer_id: -// log_status("TODO: convert code pointer id sort"); -// result = this->mk_intloc_sort(); -// break; - - -// case type2t::intheap_id: -// case type2t::array_id: -// { -// log_status("INFO: convert array id type to intheap sort"); -// result = this->mk_intheap_sort(); - -// break; -// } -// case type2t::signedbv_id: -// { -// result = this->mk_int_sort(); -// break; -// } - -// default: -// log_error( -// "Unexpected type ID {} reached SMT conversion", get_type_id(type)); -// abort(); -// } - -// sort_cache.insert(smt_sort_cachet::value_type(type, result)); -// return result; -// } - -// smt_astt z3_slhv_convt::convert_assign_slhv(const expr2tc &expr) { -// const equality2t &eq = to_equality2t(expr); -// smt_astt side1 = convert_ast_slhv(eq.side_1); // LHS -// smt_astt side2 = convert_ast_slhv(eq.side_2); // RHS -// side2->assign(this, side1); - -// smt_cache_entryt e = {eq.side_1, side2, ctx_level}; -// smt_cache.insert(e); -// return side2; -// } - - -// void z3_slhv_convt::print_smt_formulae(std::ostream &dest) { -// log_status("TODO: slhv print smt"); -// } +} \ No newline at end of file diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 9111538e..551383b4 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -1,29 +1,9 @@ #ifndef _ESBMC_SOLVERS_Z3_SLHV_CONV_H #define _ESBMC_SOLVERS_Z3_SLHV_CONV_H -// this file does not follow the translation procedure in the - -// #include #include #include -// class z3_slhv_smt_ast : public solver_smt_ast -// { -// public: -// using solver_smt_ast::solver_smt_ast; -// ~z3_slhv_smt_ast() override = default; - -// smt_astt update(smt_convt *ctx, -// smt_astt value, -// unsigned int idx, -// expr2tc idx_expr) -// const override; - -// smt_astt project(smt_convt *ctx, unsigned int elem) const override; - -// void dump() const override; -// }; - class z3_slhv_convt : public z3_convt { public: z3_slhv_convt(const namespacet &ns, const optionst &options); From da171cb4098d64a022c87e097ed3dcc7401bdc50 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 22 Jul 2024 16:04:38 +0800 Subject: [PATCH 010/126] make hvar and lvar via specific api --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 15 +++++++++++++++ src/solvers/z3-slhv/z3_slhv_conv.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index e63587f2..07cdc839 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -141,6 +141,21 @@ smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) { return mk_intloc_sort(); } +smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s) { + z3::expr e(z3_ctx); + switch (s->id) { + case SMT_SORT_INTHEAP: + e = z3_ctx.hvar_const(name.c_str()); + break; + case SMT_SORT_INTLOC: + e = z3_ctx.locvar_const(name.c_str()); + break; + default: + e = z3_ctx.constant(name.c_str(), to_solver_smt_sort(s)->s); + } + return new_ast(e, s); +} + smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { switch (type->type_id) { case type2t::intheap_id: return mk_intheap_sort(); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 551383b4..479ae9f0 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -35,6 +35,9 @@ class z3_slhv_convt : public z3_convt { smt_sortt mk_intloc_sort(); smt_sortt mk_struct_sort(const type2tc &type) override; + // SLHV variable + smt_astt mk_smt_symbol(const std::string &name, smt_sortt s) override; + smt_sortt convert_slhv_sorts(const type2tc &type) override; smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; From 1c1df8080fff327f7c9895764dffa6a9e0ee7dad Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 24 Jul 2024 14:45:31 +0800 Subject: [PATCH 011/126] use z3_conv get_bool --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 4 ---- src/solvers/z3-slhv/z3_slhv_conv.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 07cdc839..d2475d24 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -119,10 +119,6 @@ smt_astt z3_slhv_convt::mk_locadd(smt_astt a, smt_astt b) { ); } -bool z3_slhv_convt::get_bool(smt_astt a){ - log_error("Can't get boolean value yet, solver not plugged."); - abort(); -} BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed){ log_error("SLHV does not support bv"); abort(); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 479ae9f0..a080ebe8 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -27,7 +27,7 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_locadd(smt_astt a, smt_astt b); // value obtaining from solver, not supported here - bool get_bool(smt_astt a) override; + // bool get_bool(smt_astt a) override; BigInt get_bv(smt_astt a, bool is_signed) override; // sort making From 06d8caf4347949c964ace57712c14dc178bfdf38 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 25 Jul 2024 12:53:29 +0800 Subject: [PATCH 012/126] adjust to byte-level points-to --- src/goto-symex/builtin_functions.cpp | 136 ++++++++++++--------------- src/goto-symex/symex_main.cpp | 2 +- src/solvers/smt/smt_conv.cpp | 6 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 2 + src/solvers/z3-slhv/z3_slhv_conv.h | 1 - 5 files changed, 67 insertions(+), 80 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index f66b19ca..d213325f 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -244,8 +244,6 @@ expr2tc goto_symext::symex_mem( } else { log_status("create heap symbol for allocation"); - unsigned int &dynamic_counter = get_dynamic_counter(); - dynamic_counter++; // value symbolt symbol; @@ -256,7 +254,23 @@ expr2tc goto_symext::symex_mem( symbol.lvalue = true; symbol.type = typet(typet::t_intheap); - symbol.type.size(migrate_expr_back(size)); + + // Size in SLHV is byte level + expr2tc bytesize; + if (!size_is_one) size = size.simplify(); + if (is_constant_int2t(size)) { + bytesize = + constant_int2tc(get_uint32_type(), + BigInt( + to_constant_int2t(size).value.to_uint64() + * type->get_width() / 8 + ) + ); + symbol.type.size(migrate_expr_back(bytesize)); + } else { + log_error("SLHV does not support dynamic array size"); + abort(); + } symbol.type.dynamic(true); symbol.mode = "C"; @@ -266,90 +280,62 @@ expr2tc goto_symext::symex_mem( type2tc heap_type = get_intheap_type(); expr2tc allocated_heap = symbol2tc(heap_type, symbol.id); std::vector pts; - expr2tc size_simplified; - if(!is_constant_int2t(size)) { - size_simplified = size.simplify(); - } else { - size_simplified = size; - } + guardt alloc_guard = cur_state->guard; - // TODO SLHV: add size simplification later - if(!is_constant_int2t(size_simplified)) { - log_error("Currently does not support constant size"); - assert(false); - } - log_status("dump alloc size: "); - size_simplified->dump(); - constant_int2t constant_size = to_constant_int2t(size_simplified); - unsigned usize = constant_size.as_ulong(); - log_status("Unsiged size: {}", usize); + + unsigned bytes = to_constant_int2t(bytesize).as_ulong(); + log_status("Unsiged size: {}", bytes); expr2tc alloc_base_addr = lhs; expr2tc heaplet; - bool need_heap_assignment = false; - if(usize == 0) { - log_status("zero size"); - // We can do nothing - expr2tc null_loc = constant_intloc2tc(get_intloc_type(), BigInt(0)); - - - } else if(usize == 1) { - log_status("single byte points_to"); - need_heap_assignment = true; - expr2tc addr = alloc_base_addr; - expr2tc fresh_data_symbol = sideeffect2tc( - get_int8_type(), - expr2tc(), - expr2tc(), - std::vector(), - type2tc(), - sideeffect2t::nondet); - heaplet = points_to2tc(get_intheap_type(), addr, fresh_data_symbol, false); - } else { - std::vector pt_vec; - expr2tc first_addr = alloc_base_addr; - expr2tc first_fresh_data = sideeffect2tc( - get_int8_type(), - expr2tc(), - expr2tc(), - std::vector(), - type2tc(), - sideeffect2t::nondet); - expr2tc first_pt = points_to2tc(get_intheap_type(), first_addr, first_fresh_data, false); - pt_vec.push_back(first_pt); - for(unsigned i = 1; i < usize; i ++) { - expr2tc offset = constant_int2tc(int_type2(), BigInt(i)); - expr2tc addr_i = locadd2tc(get_intloc_type(), first_addr, offset); - expr2tc fresh_data_i = sideeffect2tc( - get_int8_type(), - expr2tc(), - expr2tc(), - std::vector(), - type2tc(), - sideeffect2t::nondet); - expr2tc pt_i = points_to2tc(get_intheap_type(), addr_i, fresh_data_i, false); - pt_vec.push_back(pt_i); - } + std::vector pt_vec; + for(unsigned i = 0; i < bytes; i ++) { + expr2tc offset = constant_int2tc(int_type2(), BigInt(i)); + expr2tc addr_i = + i == 0 ? alloc_base_addr : + locadd2tc(get_intloc_type(), alloc_base_addr, offset); + expr2tc fresh_data_i = + sideeffect2tc( + get_int8_type(), + expr2tc(), + expr2tc(), + std::vector(), + type2tc(), + sideeffect2t::nondet + ); + expr2tc pt_i = points_to2tc(get_intheap_type(), addr_i, fresh_data_i, false); + pt_vec.push_back(pt_i); + } + + if (pt_vec.size() > 1) { heaplet = uplus2tc(get_intheap_type(), pt_vec); - log_status("multi byte points_to"); - need_heap_assignment = true; + } else { + heaplet = pt_vec[0]; } - expr2tc origin_base_addr( alloc_base_addr); + + expr2tc origin_base_addr(alloc_base_addr); cur_state->rename(alloc_base_addr); expr2tc alloc_base_addr_copy(alloc_base_addr); - if(need_heap_assignment) { - log_status("symex assign in symex_mem: allocated_heap = heaplet"); - symex_assign(code_assign2tc(allocated_heap, heaplet)); - } + + log_status("symex assign in symex_mem: allocated_heap = heaplet"); + symex_assign(code_assign2tc(allocated_heap, heaplet)); + log_status("create valueset base addr symbol and assign"); - expr2tc base_value_symbol = symbol2tc(get_intloc_type(), to_symbol2t(origin_base_addr).get_symbol_name()); - expr2tc base_pointer_region_object = pointer_with_region2tc(get_intloc_type(), base_value_symbol, allocated_heap); - symex_assign(code_assign2tc(origin_base_addr, typecast2tc(origin_base_addr->type, base_pointer_region_object))); + expr2tc base_value_symbol = + symbol2tc(get_intloc_type(), to_symbol2t(origin_base_addr).get_symbol_name()); + expr2tc base_pointer_region_object = + pointer_with_region2tc(get_intloc_type(), base_value_symbol, allocated_heap); + symex_assign( + code_assign2tc( + origin_base_addr, + typecast2tc(origin_base_addr->type, base_pointer_region_object) + ) + ); // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), alloc_base_addr); - track_new_pointer(ptr_obj, get_intheap_type(), size_simplified); + track_new_pointer(ptr_obj, get_intheap_type(), bytesize); dynamic_memory.emplace_back( allocated_heap, alloc_guard, @@ -359,8 +345,6 @@ expr2tc goto_symext::symex_mem( return expr2tc(); } - - } void goto_symext::track_new_pointer( diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 3a61ba8a..5012edfd 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -138,7 +138,7 @@ goto_symext::symex_resultt goto_symext::get_symex_result() return goto_symext::symex_resultt(target, total_claims, remaining_claims); } -void goto_symext:: symex_step(reachability_treet &art) +void goto_symext::symex_step(reachability_treet &art) { log_status(" ======= goto_symext symex_step"); assert(!cur_state->call_stack.empty()); diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 03275acf..dcef5882 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -442,7 +442,9 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) is_pointer_type(expr->type) || is_pointer_type(add.side_1) || is_pointer_type(add.side_2)) { - a = convert_pointer_arith(expr, expr->type); + a = this->solver_text() == "Z3-slhv" ? + convert_slhv_opts(expr, args) : + convert_pointer_arith(expr, expr->type); } else if (int_encoding) { @@ -741,7 +743,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) ptr = &to_typecast2t(*ptr).from; args[0] = convert_ast(*ptr); - a = args[0]->project(this, 1); + a = this->solver_text() == "Z3-slhv" ? args[0] : args[0]->project(this, 0); break; } case expr2t::pointer_object_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index d2475d24..c9067ecf 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -186,8 +186,10 @@ z3_slhv_convt::convert_slhv_opts( } return h; } + case expr2t::add_id: case expr2t::locadd_id: { assert(args.size() == 2); + // TODO return mk_locadd(args[0], args[1]); } case expr2t::heap_update_id: { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index a080ebe8..abaef41f 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -27,7 +27,6 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_locadd(smt_astt a, smt_astt b); // value obtaining from solver, not supported here - // bool get_bool(smt_astt a) override; BigInt get_bv(smt_astt a, bool is_signed) override; // sort making From c9ce912d789d97c69307e4eac311a55499bfe640 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Thu, 25 Jul 2024 14:46:33 +0800 Subject: [PATCH 013/126] update --- benchmark/case_0.c | 8 ++++---- src/goto-symex/builtin_functions.cpp | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 284605b9..15d8d406 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -3,14 +3,14 @@ int main(){ // int whatever; int * data = malloc(2*sizeof(int)); - // int * data2 = malloc(sizeof(int)); - // int i = *(data + 1); - // free(data); + int * data2 = malloc(sizeof(int)); + int i = *(data + 1); + // free(data2); // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; // int n = *(data+1); - // if(n > 0) { + // if(i > 0) { // free(data); // } } diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index d213325f..5bcb7bb5 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -257,7 +257,9 @@ expr2tc goto_symext::symex_mem( // Size in SLHV is byte level expr2tc bytesize; - if (!size_is_one) size = size.simplify(); + if (!is_constant_int2t(size)) { + size = size.simplify(); + } if (is_constant_int2t(size)) { bytesize = constant_int2tc(get_uint32_type(), From ec27cb3db3f004babc005e38cfb05ab5eca0683f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 25 Jul 2024 15:24:58 +0800 Subject: [PATCH 014/126] write vccs and its smt formulas in file --- src/esbmc/bmc.cpp | 9 +-------- src/goto-symex/symex_target_equation.cpp | 4 ---- src/solvers/z3-slhv/z3_slhv_conv.cpp | 12 ++++++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index d3795ce9..2ee08408 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -165,14 +165,6 @@ void bmct::generate_smt_from_equation( "Encoding to solver time: {}s", time2string(encode_stop - encode_start)); } -// std::string bmct::generate_slhv_smt_from_equation(z3_slhv_convt& slhv_converter, symex_target_equationt &eq) { -// log_status("generate slhv formula from equation"); -// std::string result; -// eq.convert2slhv(slhv_converter); -// log_status("here"); -// return result; -// } - smt_convt::resultt bmct::run_decision_procedure(smt_convt &smt_conv, symex_target_equationt &eq) { @@ -655,6 +647,7 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); + show_vcc(*eq); // log_status("smt_convt created"); // if (options.get_bool_option("z3-slhv")) { // show_vcc(*eq); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 8af8f8a2..8b1c3429 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -144,10 +144,6 @@ void symex_target_equationt::convert(smt_convt &smt_conv) if (!assertions.empty()) smt_conv.assert_ast(smt_conv.make_n_ary_or(assertions)); log_status("final convert result ============= "); - - smt_conv.dump_smt(); - log_status("================================== "); - } // void symex_target_equationt::convert2slhv(z3_slhv_convt& slhv_convt) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index c9067ecf..ac8e9065 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -54,7 +54,19 @@ z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } smt_convt::resultt z3_slhv_convt::dec_solve() { log_status("z3-slhv debug: before slhv check"); + + const std::string &path = options.get_option("output"); + if (path != "-") + { + std::ofstream out(path, std::ios_base::app); + out << "SMT formulas for VCCs:\n"; + for(z3::expr expr : solver.assertions()) { + out << expr.to_string() << '\n'; + } + } + z3::check_result result = solver.check(); + log_status("z3-slhv debug: after check"); if (result == z3::sat) From 6850b766a16cf238299d6a72d22c9a50eef8a1f0 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 25 Jul 2024 17:03:08 +0800 Subject: [PATCH 015/126] add symex_assign on heap_load = val --- src/goto-symex/goto_symex.h | 17 +++++++++++++ src/goto-symex/symex_assign.cpp | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 71e2513b..ce79f5ce 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -747,6 +747,23 @@ class goto_symext expr2tc &full_rhs, guardt &guard, const bool hidden); + + /** + * This method is used when we need to assign a value + * to a heap_load, which is obatained via load `byte_len` + * bytes in a heap(SLHV). + * @param lhs Heap(points-to) to assign to + * @param full_lhs The original assignment symbol + * @param rhs Value to assign to lhs + * @param guard Assignment guard. + */ + void symex_assign_heap_laod( + const expr2tc &lhs, + const expr2tc &full_lhs, + expr2tc &rhs, + expr2tc &full_rhs, + guardt &guard, + const bool hidden); /** Symbolic implementation of malloc. */ expr2tc symex_malloc(const expr2tc &lhs, const sideeffect2t &code); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 89e80ac9..0559709b 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -318,6 +318,11 @@ void goto_symext::symex_assign_rec( log_status("symex_assign_bitfield"); symex_assign_bitfield(lhs, full_lhs, rhs, full_rhs, guard, hidden); } + else if (is_heap_load2t(lhs)) + { + log_status("symex_assign_heap_load"); + symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); + } else { log_error("assignment to {} not handled", get_expr_id(lhs)); @@ -852,6 +857,45 @@ void goto_symext::symex_assign_bitfield( return symex_assign_rec(val, full_lhs, new_rhs, full_rhs, guard, hidden); } +void goto_symext::symex_assign_heap_laod( + const expr2tc &lhs, + const expr2tc &full_lhs, + expr2tc &rhs, + expr2tc &full_rhs, + guardt &guard, + const bool hidden) +{ + log_status("lhs : "); + lhs->dump(); + log_status("full lhs : "); + full_lhs->dump(); + log_status("rhs : "); + rhs->dump(); + log_status("guard : "); + guard.dump(); + + assert(is_scalar_type(rhs)); + + const heap_load2t& heap_load = to_heap_load2t(lhs); + assert(heap_load.byte_len * 8 == rhs->type->get_width()); + + // Pin one set of rhs version numbers: if we assign part of a value to itself, + // it'll change during the assignment + cur_state->rename(rhs); // shall we? + + expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_addr); + expr2tc updated_heap = + heap_update2tc( + get_intheap_type(), + heap_load.heap, + ptr_obj, + rhs, + heap_load.byte_len + ); + + symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); +} + void goto_symext::replace_nondet(expr2tc &expr) { if ( From 293124d6838a98efde2f15f7a939138f178492fd Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 25 Jul 2024 20:10:09 +0800 Subject: [PATCH 016/126] set default points-to bytes(4) --- src/goto-symex/builtin_functions.cpp | 6 +++++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 5bcb7bb5..4cba378a 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -245,6 +245,9 @@ expr2tc goto_symext::symex_mem( } else { log_status("create heap symbol for allocation"); + // TODO: fix the right width of pointee + uint32_t pt_bytes = 4; + // value symbolt symbol; symbol.name = "dynamic_heap_"+ i2string(dynamic_counter); @@ -292,7 +295,8 @@ expr2tc goto_symext::symex_mem( expr2tc heaplet; std::vector pt_vec; - for(unsigned i = 0; i < bytes; i ++) { + uint n = bytes % pt_bytes == 0 ? bytes / pt_bytes : bytes; + for(unsigned i = 0; i < n; i ++) { expr2tc offset = constant_int2tc(int_type2(), BigInt(i)); expr2tc addr_i = i == 0 ? alloc_base_addr : diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index ac8e9065..7baa5892 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -89,7 +89,6 @@ smt_astt z3_slhv_convt::mk_nil() { return new_ast(z3_ctx.nil_const(), this->mk_intloc_sort()); } smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { - log_status("here"); return new_ast( z3::points_to( to_solver_smt_ast(a)->a, @@ -201,11 +200,12 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::add_id: case expr2t::locadd_id: { assert(args.size() == 2); - // TODO return mk_locadd(args[0], args[1]); } case expr2t::heap_update_id: { const heap_update2t& heap_upd = to_heap_update2t(expr); + // TODO : fix width + assert(heap_upd.byte_len == 4); smt_astt h = args[0]; smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap")); smt_astt adr = args[1]; @@ -219,6 +219,8 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_load_id: { const heap_load2t& heap_load = to_heap_load2t(expr); + // TODO : fix width + assert(heap_load.byte_len == 4); // TODO: fix v1 sort smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")); //current heap state @@ -227,9 +229,10 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_contains_id: { const heap_contains2t& heap_ct = to_heap_contains2t(expr); - assert(heap_ct.byte_len >= 1); + // TODO : fix width + assert(heap_ct.byte_len == 4); smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val"))); - for (int i = 1; i < heap_ct.byte_len; i++) { + for (int i = 1; i < heap_ct.byte_len / 4; i++) { sh = mk_uplus( sh, mk_pt( From 52cc1123bf944646d83575e55c06cc65d95994cb Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 26 Jul 2024 12:39:02 +0800 Subject: [PATCH 017/126] add definition of heap append --- benchmark/case_0.c | 4 +- src/irep2/irep2.h | 3 +- src/irep2/irep2_expr.cpp | 1 + src/irep2/irep2_expr.h | 39 +++++++++++++++++++ src/irep2/templates/irep2_templates.cpp | 2 + .../templates/irep2_templates_expr_data.cpp | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 15d8d406..649a254e 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -2,9 +2,9 @@ int main(){ // int whatever; - int * data = malloc(2*sizeof(int)); + // int * data = malloc(2*sizeof(int)); int * data2 = malloc(sizeof(int)); - int i = *(data + 1); + int i = *(data2); // free(data2); // int* j = NULL; // int* i = j; diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 8a59587f..74dd5539 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -109,6 +109,7 @@ BOOST_PP_LIST_CONS(pointer_with_region, \ BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ + BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_contains, \ BOOST_PP_LIST_CONS(isnan, \ BOOST_PP_LIST_CONS(overflow, \ @@ -150,7 +151,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 910b71b9..2148f8e5 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -80,6 +80,7 @@ static const char *expr_names[] = { "pointer_with_region", "heap_load", "heap_update", + "heap_append", "heap_contains", "isnan", "overflow", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 5f513ee2..f58e9385 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1059,6 +1059,36 @@ class heap_update_data : public expr2t }; + +class heap_append_data : public expr2t { +public: + heap_append_data( + const type2tc & t, + datatype_ops::expr_ids id, + expr2tc original_heap, + expr2tc start_addr, + unsigned int byte_len + ) : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), byte_len(byte_len) {} + + expr2tc src_heap; + expr2tc start_addr; + unsigned int byte_len; + + + // Type mangling: + typedef esbmct::field_traits + heap_append_data_src_heap_field; + typedef esbmct::field_traits + heap_append_data_start_addr_field; + typedef esbmct::field_traits + heap_append_data_byte_len_field; + typedef esbmct::expr2t_traits + < + heap_append_data_src_heap_field, heap_append_data_start_addr_field, heap_append_data_byte_len_field + > traits; + +}; + class heap_contains_data : public expr2t { public: heap_contains_data( @@ -1720,6 +1750,7 @@ irep_typedefs(locadd, locadd_data); irep_typedefs(pointer_with_region, pointer_with_region_data); irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); +irep_typedefs(heap_append, heap_append_data); irep_typedefs(heap_contains, heap_contains_data); irep_typedefs(isnan, bool_1op); irep_typedefs(overflow, overflow_ops); @@ -3242,6 +3273,14 @@ class heap_update2t : public heap_update_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +class heap_append2t : public heap_append_expr_methods { + public: + heap_append2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, unsigned int byte_len) : heap_append_expr_methods(type, heap_append_id, source_heap, start_addr, byte_len) {} + heap_append2t(const heap_append2t &ref) = default; + + static std::string field_names[esbmct::num_type_fields]; +}; + class heap_contains2t : public heap_contains_expr_methods { public: diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 28578c25..05a2f686 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -172,6 +172,8 @@ std::string heap_load2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "updated_val", "byte_len", ""}; +std::string heap_append2t::field_names[esbmct::num_type_fields] = +{"src_heap", "start_addr", "byte_len", "", ""}; std::string heap_contains2t::field_names[esbmct::num_type_fields] = {"heapvar", "start_loc", "byte_len", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index a9808e82..ffdc0de3 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -35,6 +35,7 @@ expr_typedefs2(locadd, locadd_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs3(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); +expr_typedefs3(heap_append, heap_append_data); expr_typedefs3(heap_contains, heap_contains_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); From 734fb5ccf2b98474fff1d178866683cd68e6c4e5 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 26 Jul 2024 14:27:28 +0800 Subject: [PATCH 018/126] add create value for heap append --- src/goto-symex/builtin_functions.cpp | 4 ++-- src/irep2/irep2_expr.h | 10 +++++++--- src/irep2/templates/irep2_templates.cpp | 2 +- src/irep2/templates/irep2_templates_expr_data.cpp | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 4cba378a..909d82c3 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -390,7 +390,7 @@ void goto_symext::track_new_pointer( // TODO SLHV: add non-constant size later assert(is_constant_int2t(size)); - expr2tc updated_heap = heap_update2tc(allocsize_heap_type, allocsize_symbol, ptr_obj, size, 4); + expr2tc updated_heap = heap_append2tc(allocsize_heap_type, allocsize_symbol, ptr_obj, size, 4); symex_assign(code_assign2tc(allocsize_symbol, updated_heap), true); } } @@ -484,7 +484,7 @@ void goto_symext::symex_free(const expr2tc &expr) bool is_definite_free = true; for(auto const& item : internal_deref_items) { expr2tc deref_object = item.object; - assert(is_pointer_with_region2tA(deref_object)); + assert(is_pointer_with_region2t(deref_object)); expr2tc simplified_offset = item.offset.simplify(); log_status("simplified offset: "); simplified_offset->dump(); diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index f58e9385..ac849c76 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1067,11 +1067,13 @@ class heap_append_data : public expr2t { datatype_ops::expr_ids id, expr2tc original_heap, expr2tc start_addr, + expr2tc create_val, unsigned int byte_len - ) : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), byte_len(byte_len) {} + ) : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), create_val(create_val), byte_len(byte_len) {} expr2tc src_heap; expr2tc start_addr; + expr2tc create_val; unsigned int byte_len; @@ -1080,11 +1082,13 @@ class heap_append_data : public expr2t { heap_append_data_src_heap_field; typedef esbmct::field_traits heap_append_data_start_addr_field; + typedef esbmct::field_traits + heap_append_data_create_val_field; typedef esbmct::field_traits heap_append_data_byte_len_field; typedef esbmct::expr2t_traits < - heap_append_data_src_heap_field, heap_append_data_start_addr_field, heap_append_data_byte_len_field + heap_append_data_src_heap_field, heap_append_data_start_addr_field, heap_append_data_create_val_field, heap_append_data_byte_len_field > traits; }; @@ -3275,7 +3279,7 @@ class heap_update2t : public heap_update_expr_methods class heap_append2t : public heap_append_expr_methods { public: - heap_append2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, unsigned int byte_len) : heap_append_expr_methods(type, heap_append_id, source_heap, start_addr, byte_len) {} + heap_append2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, expr2tc create_val, unsigned int byte_len) : heap_append_expr_methods(type, heap_append_id, source_heap, start_addr, create_val, byte_len) {} heap_append2t(const heap_append2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 05a2f686..9957fc08 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -173,7 +173,7 @@ std::string heap_load2t::field_names[esbmct::num_type_fields] = std::string heap_update2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "updated_val", "byte_len", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = -{"src_heap", "start_addr", "byte_len", "", ""}; +{"src_heap", "start_addr", "create_val", "byte_len", ""}; std::string heap_contains2t::field_names[esbmct::num_type_fields] = {"heapvar", "start_loc", "byte_len", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index ffdc0de3..43905b33 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -35,7 +35,7 @@ expr_typedefs2(locadd, locadd_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs3(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); -expr_typedefs3(heap_append, heap_append_data); +expr_typedefs4(heap_append, heap_append_data); expr_typedefs3(heap_contains, heap_contains_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); From 460c196782defb9bd7506a997798518d19ae63be Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 27 Jul 2024 14:26:25 +0800 Subject: [PATCH 019/126] add encoding of heap_append and slicing --- src/goto-symex/slice.cpp | 50 ++++++++++++++++++++++++---- src/goto-symex/slice.h | 11 ++++++ src/irep2/irep2_utils.h | 14 ++++++++ src/solvers/smt/smt_conv.cpp | 3 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 10 ++++++ src/util/migrate.cpp | 11 ++++++ 6 files changed, 91 insertions(+), 8 deletions(-) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 35584c5e..fb4773fc 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,12 +11,16 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - // Recursively look if any of the operands has a inner symbol - expr->foreach_operand([this, &res](const expr2tc &e) { - if (!is_nil_expr(e)) - res |= get_symbols(e); - return res; - }); + if (is_slhv_expr(expr)) { + res |= get_slhv_symbols(expr); + } else { + // Recursively look if any of the operands has a inner symbol + expr->foreach_operand([this, &res](const expr2tc &e) { + if (!is_nil_expr(e)) + res |= get_symbols(e); + return res; + }); + } if (!is_symbol2t(expr)) return res; @@ -29,6 +33,38 @@ bool symex_slicet::get_symbols(const expr2tc &expr) return res; } +template +bool symex_slicet::get_slhv_symbols(const expr2tc& expr) +{ + switch (expr->expr_id) { + case expr2t::constant_intheap_id: + case expr2t::constant_intloc_id: + return false; // TODO: right? + case expr2t::points_to_id: + case expr2t::uplus_id: + case expr2t::locadd_id: + case expr2t::heap_contains_id: + case expr2t::heap_load_id: + case expr2t::heap_append_id: + case expr2t::heap_update_id: { + bool res = false; + expr->foreach_operand([this, &res](const expr2tc &e) { + if (!is_nil_expr(e)) + res |= get_symbols(e); + return res; + }); + return res; + } + case expr2t::pointer_with_region_id: { + const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); + return get_symbols(pwr.loc_ptr); + } + default: + log_error("Wrong SLHV expr"); + abort(); + } +} + void symex_slicet::run_on_assert(symex_target_equationt::SSA_stept &SSA_step) { get_symbols(SSA_step.guard); @@ -238,4 +274,4 @@ expr2tc symex_slicet::get_nondet_symbol(const expr2tc &expr) default: return expr2tc(); } -} +} \ No newline at end of file diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index fa78e91d..8b2a82b8 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -157,6 +157,17 @@ class symex_slicet : public slicer template bool get_symbols(const expr2tc &expr); + /** + * Recursively explores the operands of an SLHV expression. + * If a symbol is found, then it is added into the #depends + * member if `Add` is true, otherwise returns true. + * + * @param expr expression to extract every symbol + * @return true if at least one symbol was found + */ + template + bool get_slhv_symbols(const expr2tc& expr); + /** * Remove unneeded assumes from the formula * diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 5fc0eca7..d0f6424b 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -239,6 +239,20 @@ inline bool is_false(const expr2tc &expr) return false; } +inline bool is_slhv_expr(const expr2tc& expr) +{ + return expr->expr_id == expr2t::constant_intheap_id || + expr->expr_id == expr2t::constant_intloc_id || + expr->expr_id == expr2t::pointer_with_region_id || + expr->expr_id == expr2t::points_to_id || + expr->expr_id == expr2t::uplus_id || + expr->expr_id == expr2t::locadd_id || + expr->expr_id == expr2t::heap_contains_id || + expr->expr_id == expr2t::heap_load_id || + expr->expr_id == expr2t::heap_update_id || + expr->expr_id == expr2t::heap_append_id; +} + inline expr2tc gen_true_expr() { static expr2tc c = constant_bool2tc(true); diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index dcef5882..5a0ceb65 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -340,7 +340,8 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::locadd_id: case expr2t::heap_update_id: case expr2t::heap_load_id: - case expr2t::heap_contains_id: { + case expr2t::heap_contains_id: + case expr2t::heap_append_id: { a = convert_slhv_opts(expr, args); break; } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 7baa5892..4aa31277 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -202,6 +202,16 @@ z3_slhv_convt::convert_slhv_opts( assert(args.size() == 2); return mk_locadd(args[0], args[1]); } + case expr2t::heap_append_id: { + const heap_append2t& heap_app = to_heap_append2t(expr); + // TODO : fix width + assert(heap_app.byte_len == 4); + smt_astt h = args[0]; + smt_astt adr = args[1]; + smt_astt val = args[2]; + // new heap state + return mk_uplus(h, mk_pt(adr, val)); + } case expr2t::heap_update_id: { const heap_update2t& heap_upd = to_heap_update2t(expr); // TODO : fix width diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index c60e1f9a..a41486a3 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2646,6 +2646,17 @@ exprt migrate_expr_back(const expr2tc &ref) heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_load; } + case expr2t::heap_append_id: + { + const heap_append2t &ref2 = to_heap_append2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt heap_append("heap_append", thetype); + heap_append.copy_to_operands(migrate_expr_back(ref2.src_heap)); + heap_append.copy_to_operands(migrate_expr_back(ref2.start_addr)); + heap_append.copy_to_operands(migrate_expr_back(ref2.create_val)); + heap_append.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + return heap_append; + } case expr2t::heap_update_id: { const heap_update2t &ref2 = to_heap_update2t(ref); From e754e5ee22b389c5cc094de94a9e25db3a82bfec Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Sun, 28 Jul 2024 16:16:59 +0800 Subject: [PATCH 020/126] update for merge --- benchmark/case_0.c | 4 ++-- src/goto-symex/dynamic_allocation.cpp | 1 - src/util/migrate.cpp | 11 +++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 649a254e..040fb21c 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -3,8 +3,8 @@ int main(){ // int whatever; // int * data = malloc(2*sizeof(int)); - int * data2 = malloc(sizeof(int)); - int i = *(data2); + int * data2 = malloc(2*sizeof(int)); + int i = *(data2 + 1); // free(data2); // int* j = NULL; // int* i = j; diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index a5327327..ca9b8e81 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -114,5 +114,4 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc index_expr = index2tc(size_type2(), alloc_arr_2, obj_expr); expr = index_expr; } - // TODO: add slhv dynamic allocation test replacement } diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index c60e1f9a..486a9822 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2657,6 +2657,17 @@ exprt migrate_expr_back(const expr2tc &ref) heap_update.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_update; } + case expr2t::heap_append_id: + { + const heap_append2t &ref2 = to_heap_append2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt heap_append("heap_append", thetype); + heap_append.copy_to_operands(migrate_expr_back(ref2.src_heap)); + heap_append.copy_to_operands(migrate_expr_back(ref2.start_addr)); + heap_append.copy_to_operands(migrate_expr_back(ref2.create_val)); + heap_append.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + return heap_append; + } case expr2t::heap_contains_id: { const heap_contains2t &ref2 = to_heap_contains2t(ref); From e56a98222dae88ed43217f5697c597dd57aa179f Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Sun, 28 Jul 2024 18:36:04 +0800 Subject: [PATCH 021/126] add heap free --- src/irep2/irep2.h | 3 ++- src/irep2/irep2_expr.cpp | 1 + src/irep2/irep2_expr.h | 22 +++++++++++++++++++ src/irep2/templates/irep2_templates.cpp | 2 ++ .../templates/irep2_templates_expr_data.cpp | 1 + src/util/migrate.cpp | 19 +++++++--------- 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 74dd5539..fd04902f 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -107,6 +107,7 @@ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(pointer_with_region, \ + BOOST_PP_LIST_CONS(heap_free, \ BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ @@ -151,7 +152,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 2148f8e5..96ca0181 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -78,6 +78,7 @@ static const char *expr_names[] = { "uplus", "locadd", "pointer_with_region", + "heap_free", "heap_load", "heap_update", "heap_append", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index ac849c76..14aa07b6 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1002,6 +1002,19 @@ class pointer_with_region_data : public expr2t typedef esbmct::expr2t_traits traits; }; +class heap_free_data : public expr2t { +public: + heap_free_data( + const type2tc &t, + datatype_ops::expr_ids id, + expr2tc pwr + ) : expr2t(t, id), pwr(pwr){} + + expr2tc pwr; + typedef esbmct::field_traits heap_free_data_pwr_field; + typedef esbmct::expr2t_traits traits; +}; + class heap_load_data : public expr2t { public: heap_load_data( @@ -1752,6 +1765,7 @@ irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); irep_typedefs(pointer_with_region, pointer_with_region_data); +irep_typedefs(heap_free, heap_free_data); irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); @@ -3259,6 +3273,14 @@ class pointer_with_region2t : public pointer_with_region_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +class heap_free2t : public heap_free_expr_methods +{ +public: + heap_free2t(const type2tc &type, expr2tc pwr) : heap_free_expr_methods(type, heap_free_id, pwr) {} + + static std::string field_names[esbmct::num_type_fields]; +}; + class heap_load2t : public heap_load_expr_methods { public: diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 9957fc08..51ec1b00 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -168,6 +168,8 @@ std::string locadd2t::field_names[esbmct::num_type_fields] = {"baseaddr", "added_num", "", "", ""}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; +std::string heap_free2t::field_names[esbmct::num_type_fields] = +{"pointer_with_region", "", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 43905b33..7c3f5667 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -33,6 +33,7 @@ expr_typedefs3(points_to, points_to_data); expr_typedefs2(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); +expr_typedefs1(heap_free, heap_free_data); expr_typedefs3(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs4(heap_append, heap_append_data); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 40d9e173..52651c87 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2636,6 +2636,14 @@ exprt migrate_expr_back(const expr2tc &ref) pointer_with_region.copy_to_operands(migrate_expr_back(ref2.region)); return pointer_with_region; } + case expr2t::heap_free_id: + { + const heap_free2t &ref2 = to_heap_free2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt heap_free("heap_free", thetype); + heap_free.copy_to_operands(migrate_expr_back(ref2.pwr)); + return heap_free; + } case expr2t::heap_load_id: { const heap_load2t& ref2 = to_heap_load2t(ref); @@ -2668,17 +2676,6 @@ exprt migrate_expr_back(const expr2tc &ref) heap_update.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_update; } - case expr2t::heap_append_id: - { - const heap_append2t &ref2 = to_heap_append2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt heap_append("heap_append", thetype); - heap_append.copy_to_operands(migrate_expr_back(ref2.src_heap)); - heap_append.copy_to_operands(migrate_expr_back(ref2.start_addr)); - heap_append.copy_to_operands(migrate_expr_back(ref2.create_val)); - heap_append.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); - return heap_append; - } case expr2t::heap_contains_id: { const heap_contains2t &ref2 = to_heap_contains2t(ref); From 481c3a63f04187280e60737addd4b14d2efc485e Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Mon, 29 Jul 2024 12:51:48 +0800 Subject: [PATCH 022/126] add heap delete --- src/irep2/irep2.h | 3 +- src/irep2/irep2_expr.cpp | 1 + src/irep2/irep2_expr.h | 42 +++++++++++++++++++ src/irep2/templates/irep2_templates.cpp | 2 + .../templates/irep2_templates_expr_data.cpp | 1 + src/util/migrate.cpp | 10 +++++ 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index fd04902f..2e4c599e 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -111,6 +111,7 @@ BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ + BOOST_PP_LIST_CONS(heap_delete, \ BOOST_PP_LIST_CONS(heap_contains, \ BOOST_PP_LIST_CONS(isnan, \ BOOST_PP_LIST_CONS(overflow, \ @@ -152,7 +153,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 96ca0181..fcac10ad 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -82,6 +82,7 @@ static const char *expr_names[] = { "heap_load", "heap_update", "heap_append", + "heap_delete", "heap_contains", "isnan", "overflow", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 14aa07b6..558bd995 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1038,6 +1038,7 @@ class heap_load_data : public expr2t { }; + class heap_update_data : public expr2t { public: @@ -1073,6 +1074,7 @@ class heap_update_data : public expr2t }; + class heap_append_data : public expr2t { public: heap_append_data( @@ -1106,6 +1108,36 @@ class heap_append_data : public expr2t { }; + +class heap_delete_data : public expr2t { +public: + heap_delete_data( + const type2tc & t, + datatype_ops::expr_ids id, + expr2tc original_heap, + expr2tc del_addr, + unsigned int byte_len + ) : expr2t(t, id), src_heap(original_heap), del_addr(del_addr), byte_len(byte_len) {} + + expr2tc src_heap; + expr2tc del_addr; + unsigned int byte_len; + + + // Type mangling: + typedef esbmct::field_traits + heap_delete_data_src_heap_field; + typedef esbmct::field_traits + heap_delete_data_del_addr_field; + typedef esbmct::field_traits + heap_delete_data_byte_len_field; + typedef esbmct::expr2t_traits + < + heap_delete_data_src_heap_field, heap_delete_data_del_addr_field, heap_delete_data_byte_len_field + > traits; + +}; + class heap_contains_data : public expr2t { public: heap_contains_data( @@ -1769,6 +1801,7 @@ irep_typedefs(heap_free, heap_free_data); irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); +irep_typedefs(heap_delete, heap_delete_data); irep_typedefs(heap_contains, heap_contains_data); irep_typedefs(isnan, bool_1op); irep_typedefs(overflow, overflow_ops); @@ -3299,6 +3332,8 @@ class heap_update2t : public heap_update_expr_methods static std::string field_names[esbmct::num_type_fields]; }; + + class heap_append2t : public heap_append_expr_methods { public: heap_append2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, expr2tc create_val, unsigned int byte_len) : heap_append_expr_methods(type, heap_append_id, source_heap, start_addr, create_val, byte_len) {} @@ -3307,6 +3342,13 @@ class heap_append2t : public heap_append_expr_methods { static std::string field_names[esbmct::num_type_fields]; }; +class heap_delete2t : public heap_delete_expr_methods { + public: + heap_delete2t(const type2tc &type, expr2tc source_heap, expr2tc del_addr, unsigned int byte_len) : heap_delete_expr_methods(type, heap_delete_id, source_heap, del_addr, byte_len) {} + heap_delete2t(const heap_delete2t &ref) = default; + + static std::string field_names[esbmct::num_type_fields]; +}; class heap_contains2t : public heap_contains_expr_methods { public: diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 51ec1b00..12f644ac 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -176,6 +176,8 @@ std::string heap_update2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "updated_val", "byte_len", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "create_val", "byte_len", ""}; +std::string heap_delete2t::field_names[esbmct::num_type_fields] = +{"src_heap", "del_addr", "byte_len", "", ""}; std::string heap_contains2t::field_names[esbmct::num_type_fields] = {"heapvar", "start_loc", "byte_len", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 7c3f5667..83795c28 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -37,6 +37,7 @@ expr_typedefs1(heap_free, heap_free_data); expr_typedefs3(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs4(heap_append, heap_append_data); +expr_typedefs3(heap_delete, heap_delete_data); expr_typedefs3(heap_contains, heap_contains_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 52651c87..55b0e5a9 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2665,6 +2665,16 @@ exprt migrate_expr_back(const expr2tc &ref) heap_append.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_append; } + case expr2t::heap_delete_id: + { + const heap_delete2t &ref2 = to_heap_delete2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt heap_delete("heap_delete", thetype); + heap_delete.copy_to_operands(migrate_expr_back(ref2.src_heap)); + heap_delete.copy_to_operands(migrate_expr_back(ref2.del_addr)); + heap_delete.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + return heap_delete; + } case expr2t::heap_update_id: { const heap_update2t &ref2 = to_heap_update2t(ref); From 8e148f30a433bb12213340efc1d75d9abff3e6be Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Mon, 29 Jul 2024 19:05:58 +0800 Subject: [PATCH 023/126] add heap delete, change bug check encoding --- benchmark/case_0.c | 4 +- src/goto-symex/builtin_functions.cpp | 65 +++++++-------------------- src/goto-symex/dynamic_allocation.cpp | 2 +- src/pointer-analysis/dereference.cpp | 12 +++-- 4 files changed, 26 insertions(+), 57 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 040fb21c..c12edad1 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -2,10 +2,10 @@ int main(){ // int whatever; - // int * data = malloc(2*sizeof(int)); + int * data = malloc(2*sizeof(int)); int * data2 = malloc(2*sizeof(int)); int i = *(data2 + 1); - // free(data2); + free(data2); // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 909d82c3..b79c92cf 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -481,60 +481,25 @@ void goto_symext::symex_free(const expr2tc &expr) expr2tc falsity = gen_false_expr(); symex_assign(code_assign2tc(valid_index_expr, falsity), true); } else { - bool is_definite_free = true; + expr2tc freed_pointer; + expr2tc freed_heap; for(auto const& item : internal_deref_items) { - expr2tc deref_object = item.object; - assert(is_pointer_with_region2t(deref_object)); - expr2tc simplified_offset = item.offset.simplify(); - log_status("simplified offset: "); - simplified_offset->dump(); - if(is_constant_int2t(simplified_offset)) { - const constant_int2t& const_offset = to_constant_int2t(simplified_offset); - BigInt val = const_offset.value; - int offsetint = val.to_uint64(); - log_status("equal to 0: {}", offsetint == 0); - if(offsetint == 0) { - log_status("free target definite"); - const pointer_with_region2t& pwr = to_pointer_with_region2t(item.object); - expr2tc reg = pwr.region; - expr2tc emp_heap = constant_intheap2tc(get_intheap_type(), true); - symex_assign(code_assign2tc(reg, emp_heap)); - expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); - // clear the alloc size position value - expr2tc updated_heap = heap_update2tc(get_intheap_type(), alloc_size_heap_symbol, pwr.loc_ptr, constant_int2tc(get_int32_type(), BigInt(0)), 4); - symex_assign(code_assign2tc(alloc_size_heap_symbol, updated_heap)); - return; - } + const pointer_with_region2t& pwr = to_pointer_with_region2t(item.object); + if(is_nil_expr(freed_pointer)) { + freed_pointer = pwr.loc_ptr; + freed_heap = pwr.region; + } else { + freed_pointer = if2tc(freed_pointer->type, item.guard, pwr.loc_ptr, freed_pointer); + freed_heap = if2tc(get_intheap_type(), item.guard, pwr.region, freed_heap); } - } - is_definite_free = false; - // Clear the alloc heapsize. - // expr2tc ptr_obj = dereference2tc(get_uint8_type(), code.operand); - if(!is_definite_free) { + + expr2tc emp_heap = constant_intheap2tc(get_intheap_type(), true); + + symex_assign(code_assign2tc(freed_heap, emp_heap)); expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); - expr2tc next_alloc_size_heap = alloc_size_heap_symbol; - for (auto const &item : internal_deref_items) { - // find which internal deref item is the freed one - // if not found, do nothing - expr2tc g = item.guard; - expr2tc deref_object = item.object; - assert(is_pointer_with_region2t(deref_object)); - const pointer_with_region2t& pwr = to_pointer_with_region2t (deref_object); - log_status("loc_ptr: "); - pwr.loc_ptr->dump(); - expr2tc offset = item.offset; - expr2tc eq = equality2tc(offset, gen_ulong(0)); - g = and2tc(eq, g); - expr2tc curr_region = pwr.region; - log_status("curr region: "); - curr_region->dump(); - code_assign2tc(curr_region, if2tc(get_intheap_type(), g, constant_intheap2tc(get_intheap_type(), true), curr_region)); - expr2tc updated_heap = heap_update2tc(get_intheap_type(), alloc_size_heap_symbol, pwr.loc_ptr, constant_int2tc(get_int32_type(), BigInt(0)), 4); - next_alloc_size_heap = if2tc(get_intheap_type(), g, updated_heap, next_alloc_size_heap); - } - symex_assign(code_assign2tc(alloc_size_heap_symbol, next_alloc_size_heap)); + expr2tc heap_deleted = heap_delete2tc(get_intheap_type(), alloc_size_heap_symbol, freed_pointer, 4); + symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); } - } } diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index ca9b8e81..75f57234 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -41,7 +41,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_status("migrate over"); expr2tc heap_contains = heap_contains2tc(get_bool_type(), alloc_size_heap_2, valid_inner.loc_ptr, 1); expr = heap_contains; - + } } else if (is_invalid_pointer2t(expr)) diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 09311e0d..b2064584 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -788,9 +788,14 @@ expr2tc dereferencet::build_reference_to( value = object; // Produce a guard that the dereferenced pointer points at this object. - type2tc ptr_type = pointer_type2tc(object->type); - expr2tc obj_ptr = typecast2tc(ptr_type, object); - pointer_guard = same_object2tc(deref_expr, obj_ptr); + // type2tc ptr_type = pointer_type2tc(object->type); + // expr2tc obj_ptr = typecast2tc(ptr_type, object); + + const pointer_with_region2t& pwr = to_pointer_with_region2t(object); + expr2tc region_heap = pwr.region; + + // pointer_guard = same_object2tc(deref_expr, obj_ptr); + pointer_guard = heap_contains2tc(get_bool_type(), region_heap, deref_expr, 1); log_status("generated pointer guard:"); pointer_guard->dump(); guardt tmp_guard(guard); @@ -2372,7 +2377,6 @@ void dereferencet::valid_check_slhv( std::string foo = is_free(mode) ? "invalid free pointer" : "invalid dereference pointer"; dereference_failure("pointer dereference", foo, tmp_guard); - // TODO: add free return; } } From 581e99e06f3a597cf010427409272ee734d565b5 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 29 Jul 2024 19:41:35 +0800 Subject: [PATCH 024/126] heap_delete encoding --- src/goto-symex/slice.cpp | 3 +- src/solvers/smt/smt_conv.cpp | 3 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 51 ++++++++++++++++++++-------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index fb4773fc..62e9cdbb 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -46,7 +46,8 @@ bool symex_slicet::get_slhv_symbols(const expr2tc& expr) case expr2t::heap_contains_id: case expr2t::heap_load_id: case expr2t::heap_append_id: - case expr2t::heap_update_id: { + case expr2t::heap_update_id: + case expr2t::heap_delete_id: { bool res = false; expr->foreach_operand([this, &res](const expr2tc &e) { if (!is_nil_expr(e)) diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 5a0ceb65..3d52fa2b 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -341,7 +341,8 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::heap_update_id: case expr2t::heap_load_id: case expr2t::heap_contains_id: - case expr2t::heap_append_id: { + case expr2t::heap_append_id: + case expr2t::heap_delete_id: { a = convert_slhv_opts(expr, args); break; } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 4aa31277..ad067fbb 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -89,6 +89,7 @@ smt_astt z3_slhv_convt::mk_nil() { return new_ast(z3_ctx.nil_const(), this->mk_intloc_sort()); } smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { + assert(a->sort == mk_intloc_sort()); return new_ast( z3::points_to( to_solver_smt_ast(a)->a, @@ -97,6 +98,8 @@ smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { + assert(a->sort == mk_intheap_sort()); + assert(b->sort == mk_intheap_sort()); return new_ast( z3::uplus( to_solver_smt_ast(a)->a, @@ -105,6 +108,8 @@ smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { this->mk_intheap_sort()); } smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { + assert(a->sort == mk_intheap_sort()); + assert(b->sort == mk_intheap_sort()); return new_ast( z3::subh( to_solver_smt_ast(a)->a, @@ -113,6 +118,8 @@ smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { this->boolean_sort); } smt_astt z3_slhv_convt::mk_disjh(smt_astt a, smt_astt b) { + assert(a->sort == mk_intheap_sort()); + assert(b->sort == mk_intheap_sort()); return new_ast( z3::disjh( to_solver_smt_ast(a)->a, @@ -121,6 +128,7 @@ smt_astt z3_slhv_convt::mk_disjh(smt_astt a, smt_astt b) { this->boolean_sort); } smt_astt z3_slhv_convt::mk_locadd(smt_astt a, smt_astt b) { + assert(a->sort == mk_intloc_sort() || b->sort == mk_intloc_sort()); return new_ast( z3::locadd( to_solver_smt_ast(a)->a, @@ -180,16 +188,19 @@ z3_slhv_convt::convert_slhv_opts( switch (expr->expr_id) { case expr2t::constant_intheap_id: return mk_emp(); case expr2t::constant_intloc_id: return mk_nil(); - case expr2t::pointer_with_region_id: { + case expr2t::pointer_with_region_id: + { const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); const symbol2t& nsym = to_symbol2t(pwr.loc_ptr); return mk_smt_symbol(nsym.get_symbol_name(), mk_intloc_sort()); } - case expr2t::points_to_id: { + case expr2t::points_to_id: + { assert(args.size() == 2); return mk_pt(args[0], args[1]); } - case expr2t::uplus_id: { + case expr2t::uplus_id: + { assert(args.size() >= 2); smt_astt h = args[0]; for (int i = 1; i < args.size(); i++) { @@ -198,11 +209,13 @@ z3_slhv_convt::convert_slhv_opts( return h; } case expr2t::add_id: - case expr2t::locadd_id: { + case expr2t::locadd_id: + { assert(args.size() == 2); return mk_locadd(args[0], args[1]); } - case expr2t::heap_append_id: { + case expr2t::heap_append_id: + { const heap_append2t& heap_app = to_heap_append2t(expr); // TODO : fix width assert(heap_app.byte_len == 4); @@ -212,48 +225,59 @@ z3_slhv_convt::convert_slhv_opts( // new heap state return mk_uplus(h, mk_pt(adr, val)); } - case expr2t::heap_update_id: { + case expr2t::heap_update_id: + { const heap_update2t& heap_upd = to_heap_update2t(expr); // TODO : fix width assert(heap_upd.byte_len == 4); smt_astt h = args[0]; - smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap")); + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt adr = args[1]; smt_astt val = args[2]; - smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val")); + smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); // current heap state smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(adr, v1), h1)); assert_ast(o_state); // new heap state return mk_uplus(mk_pt(adr, val), h1); } - case expr2t::heap_load_id: { + case expr2t::heap_load_id: + { const heap_load2t& heap_load = to_heap_load2t(expr); // TODO : fix width assert(heap_load.byte_len == 4); // TODO: fix v1 sort - smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")); + smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); //current heap state assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); return v1; } - case expr2t::heap_contains_id: { + case expr2t::heap_contains_id: + { const heap_contains2t& heap_ct = to_heap_contains2t(expr); // TODO : fix width assert(heap_ct.byte_len == 4); - smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val"))); + smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); for (int i = 1; i < heap_ct.byte_len / 4; i++) { sh = mk_uplus( sh, mk_pt( mk_locadd(args[1], mk_smt_int(BigInt(i))), // TODO: fix sort - mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val")) + mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")) ) ); } return mk_subh(sh, args[0]); } + case expr2t::heap_delete_id: + { + const heap_delete2t& heap_del = to_heap_delete2t(expr); + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); + smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + assert_ast(mk_eq(args[0], mk_uplus(h1, mk_pt(args[1], v1)))); + return h1; + } default: { log_status("Invalid SLHV operations!!!"); abort(); @@ -261,7 +285,6 @@ z3_slhv_convt::convert_slhv_opts( } } - void z3_slhv_convt::dump_smt() { const std::string &path = options.get_option("output"); if(path == "-") { From 1e9bbd0b59b95c601f405fde24da3d49eb6f5c26 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 29 Jul 2024 20:56:43 +0800 Subject: [PATCH 025/126] add slicing --- src/goto-symex/slice.cpp | 40 +++------------------------------------- src/goto-symex/slice.h | 19 ++++++++----------- src/irep2/irep2_utils.h | 14 -------------- 3 files changed, 11 insertions(+), 62 deletions(-) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 62e9cdbb..8e68cef6 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,8 +11,8 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - if (is_slhv_expr(expr)) { - res |= get_slhv_symbols(expr); + if (is_pointer_with_region2t(expr)) { + return get_symbols(to_pointer_with_region2t(expr).loc_ptr); } else { // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { @@ -33,39 +33,6 @@ bool symex_slicet::get_symbols(const expr2tc &expr) return res; } -template -bool symex_slicet::get_slhv_symbols(const expr2tc& expr) -{ - switch (expr->expr_id) { - case expr2t::constant_intheap_id: - case expr2t::constant_intloc_id: - return false; // TODO: right? - case expr2t::points_to_id: - case expr2t::uplus_id: - case expr2t::locadd_id: - case expr2t::heap_contains_id: - case expr2t::heap_load_id: - case expr2t::heap_append_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: { - bool res = false; - expr->foreach_operand([this, &res](const expr2tc &e) { - if (!is_nil_expr(e)) - res |= get_symbols(e); - return res; - }); - return res; - } - case expr2t::pointer_with_region_id: { - const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); - return get_symbols(pwr.loc_ptr); - } - default: - log_error("Wrong SLHV expr"); - abort(); - } -} - void symex_slicet::run_on_assert(symex_target_equationt::SSA_stept &SSA_step) { get_symbols(SSA_step.guard); @@ -102,8 +69,7 @@ void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) } } -void symex_slicet::run_on_assignment( - symex_target_equationt::SSA_stept &SSA_step) +void symex_slicet::run_on_assignment(symex_target_equationt::SSA_stept &SSA_step) { assert(is_symbol2t(SSA_step.lhs)); // TODO: create an option to ignore nondet symbols (test case generation) diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index 8b2a82b8..7cc61c99 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -101,6 +101,14 @@ class symex_slicet : public slicer fine_timet algorithm_start = current_time(); for (auto &step : boost::adaptors::reverse(eq)) run_on_step(step); + + log_status("show eq system"); + int ss = 0; + for (auto &step : boost::adaptors::reverse(eq)) { + log_status("step -{} is ignored? {}", ++ss, step.ignore); + step.dump(); + } + fine_timet algorithm_stop = current_time(); log_status( "Slicing time: {}s (removed {} assignments)", @@ -157,17 +165,6 @@ class symex_slicet : public slicer template bool get_symbols(const expr2tc &expr); - /** - * Recursively explores the operands of an SLHV expression. - * If a symbol is found, then it is added into the #depends - * member if `Add` is true, otherwise returns true. - * - * @param expr expression to extract every symbol - * @return true if at least one symbol was found - */ - template - bool get_slhv_symbols(const expr2tc& expr); - /** * Remove unneeded assumes from the formula * diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index d0f6424b..5fc0eca7 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -239,20 +239,6 @@ inline bool is_false(const expr2tc &expr) return false; } -inline bool is_slhv_expr(const expr2tc& expr) -{ - return expr->expr_id == expr2t::constant_intheap_id || - expr->expr_id == expr2t::constant_intloc_id || - expr->expr_id == expr2t::pointer_with_region_id || - expr->expr_id == expr2t::points_to_id || - expr->expr_id == expr2t::uplus_id || - expr->expr_id == expr2t::locadd_id || - expr->expr_id == expr2t::heap_contains_id || - expr->expr_id == expr2t::heap_load_id || - expr->expr_id == expr2t::heap_update_id || - expr->expr_id == expr2t::heap_append_id; -} - inline expr2tc gen_true_expr() { static expr2tc c = constant_bool2tc(true); From 1335839b2ea12ebf73368eb9b6e3943eba673b1f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 31 Jul 2024 14:29:38 +0800 Subject: [PATCH 026/126] add heap_region and adjust some exprs for SLHV --- src/goto-symex/builtin_functions.cpp | 33 ++- src/goto-symex/dynamic_allocation.cpp | 2 +- src/goto-symex/slice.cpp | 4 +- src/goto-symex/symex_assign.cpp | 22 +- src/irep2/irep2.h | 6 +- src/irep2/irep2_expr.cpp | 2 +- src/irep2/irep2_expr.h | 201 +++++++++++------- src/irep2/templates/irep2_templates.cpp | 4 +- .../templates/irep2_templates_expr_data.cpp | 6 +- src/pointer-analysis/dereference.cpp | 185 ++++++++-------- src/pointer-analysis/dereference.h | 2 +- src/solvers/smt/smt_conv.cpp | 1 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 5 + src/util/migrate.cpp | 18 +- 14 files changed, 279 insertions(+), 212 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index b79c92cf..24f44b18 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -292,15 +292,13 @@ expr2tc goto_symext::symex_mem( log_status("Unsiged size: {}", bytes); expr2tc alloc_base_addr = lhs; - expr2tc heaplet; std::vector pt_vec; - uint n = bytes % pt_bytes == 0 ? bytes / pt_bytes : bytes; - for(unsigned i = 0; i < n; i ++) { + uint pt_num = bytes % pt_bytes == 0 ? bytes / pt_bytes : bytes; + for(unsigned i = 0; i < pt_num; i ++) { expr2tc offset = constant_int2tc(int_type2(), BigInt(i)); - expr2tc addr_i = - i == 0 ? alloc_base_addr : - locadd2tc(get_intloc_type(), alloc_base_addr, offset); + expr2tc addr_i = i == 0 ? alloc_base_addr : locadd2tc(alloc_base_addr, offset); + // TODO: fix int_type expr2tc fresh_data_i = sideeffect2tc( get_int8_type(), @@ -310,28 +308,26 @@ expr2tc goto_symext::symex_mem( type2tc(), sideeffect2t::nondet ); - expr2tc pt_i = points_to2tc(get_intheap_type(), addr_i, fresh_data_i, false); + expr2tc pt_i = points_to2tc(addr_i, fresh_data_i, false); pt_vec.push_back(pt_i); } - if (pt_vec.size() > 1) { - heaplet = uplus2tc(get_intheap_type(), pt_vec); - } else { - heaplet = pt_vec[0]; - } + expr2tc heap = pt_vec.size() > 1 ? uplus2tc(pt_vec) : pt_vec[0]; expr2tc origin_base_addr(alloc_base_addr); cur_state->rename(alloc_base_addr); - expr2tc alloc_base_addr_copy(alloc_base_addr); + + expr2tc region_size = constant_int2tc(int_type2(), BigInt(pt_num)); + expr2tc region = heap_region2tc(heap, origin_base_addr, region_size); log_status("symex assign in symex_mem: allocated_heap = heaplet"); - symex_assign(code_assign2tc(allocated_heap, heaplet)); + symex_assign(code_assign2tc(allocated_heap, region)); log_status("create valueset base addr symbol and assign"); expr2tc base_value_symbol = symbol2tc(get_intloc_type(), to_symbol2t(origin_base_addr).get_symbol_name()); expr2tc base_pointer_region_object = - pointer_with_region2tc(get_intloc_type(), base_value_symbol, allocated_heap); + pointer_with_region2tc(base_value_symbol, region); symex_assign( code_assign2tc( origin_base_addr, @@ -341,7 +337,7 @@ expr2tc goto_symext::symex_mem( // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), alloc_base_addr); - track_new_pointer(ptr_obj, get_intheap_type(), bytesize); + track_new_pointer(ptr_obj, get_intheap_type(), region_size); dynamic_memory.emplace_back( allocated_heap, alloc_guard, @@ -390,7 +386,7 @@ void goto_symext::track_new_pointer( // TODO SLHV: add non-constant size later assert(is_constant_int2t(size)); - expr2tc updated_heap = heap_append2tc(allocsize_heap_type, allocsize_symbol, ptr_obj, size, 4); + expr2tc updated_heap = heap_append2tc(allocsize_symbol, ptr_obj, size, 4); symex_assign(code_assign2tc(allocsize_symbol, updated_heap), true); } } @@ -497,10 +493,9 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(freed_heap, emp_heap)); expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); - expr2tc heap_deleted = heap_delete2tc(get_intheap_type(), alloc_size_heap_symbol, freed_pointer, 4); + expr2tc heap_deleted = heap_delete2tc(alloc_size_heap_symbol, freed_pointer, 4); symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); } - } } diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 75f57234..8ef6f6cd 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -39,7 +39,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_status("before migrate"); migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap_2); log_status("migrate over"); - expr2tc heap_contains = heap_contains2tc(get_bool_type(), alloc_size_heap_2, valid_inner.loc_ptr, 1); + expr2tc heap_contains = heap_contains2tc(alloc_size_heap_2, valid_inner.loc_ptr, 1); expr = heap_contains; } diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 8e68cef6..c68d5cc4 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -12,7 +12,9 @@ bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; if (is_pointer_with_region2t(expr)) { - return get_symbols(to_pointer_with_region2t(expr).loc_ptr); + return get_symbols(to_pointer_with_region2t(expr).loc_ptr); + } else if (is_heap_region2t(expr)) { + return get_symbols(to_heap_region2t(expr).region); } else { // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 0559709b..fedad1dd 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -323,6 +323,10 @@ void goto_symext::symex_assign_rec( log_status("symex_assign_heap_load"); symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); } + else if (is_heap_region2t(lhs)) + { + log_status("symex_assign_heap_region"); + } else { log_error("assignment to {} not handled", get_expr_id(lhs)); @@ -865,15 +869,6 @@ void goto_symext::symex_assign_heap_laod( guardt &guard, const bool hidden) { - log_status("lhs : "); - lhs->dump(); - log_status("full lhs : "); - full_lhs->dump(); - log_status("rhs : "); - rhs->dump(); - log_status("guard : "); - guard.dump(); - assert(is_scalar_type(rhs)); const heap_load2t& heap_load = to_heap_load2t(lhs); @@ -884,14 +879,7 @@ void goto_symext::symex_assign_heap_laod( cur_state->rename(rhs); // shall we? expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_addr); - expr2tc updated_heap = - heap_update2tc( - get_intheap_type(), - heap_load.heap, - ptr_obj, - rhs, - heap_load.byte_len - ); + expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); } diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 2e4c599e..14d0522c 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -106,9 +106,9 @@ BOOST_PP_LIST_CONS(points_to, \ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ - BOOST_PP_LIST_CONS(pointer_with_region, \ - BOOST_PP_LIST_CONS(heap_free, \ - BOOST_PP_LIST_CONS(heap_load, \ + BOOST_PP_LIST_CONS(heap_region, \ + BOOST_PP_LIST_CONS(pointer_with_region, \ + BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_delete, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index fcac10ad..fd1ed5d4 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -77,8 +77,8 @@ static const char *expr_names[] = { "points_to", "uplus", "locadd", + "region", "pointer_with_region", - "heap_free", "heap_load", "heap_update", "heap_append", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 558bd995..427c3033 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -907,9 +907,10 @@ class points_to_data : public expr2t datatype_ops::expr_ids id, const expr2tc &addrloc, const expr2tc &content, - bool is_loc) : expr2t(t, id), addr(addrloc), content(content), is_loc_content(is_loc) { - - } + bool is_loc) + : expr2t(t, id), addr(addrloc), content(content), is_loc_content(is_loc) + { + } points_to_data(const points_to_data& ref) = default; @@ -936,11 +937,11 @@ class uplus_data : public expr2t uplus_data( const type2tc &t, datatype_ops::expr_ids id, - std::vector members, - unsigned int m_num) : expr2t(t, id), uplus_members(std::move(members)), member_num(m_num) - { - - } + const std::vector &members, + unsigned int m_num) + : expr2t(t, id), uplus_members(std::move(members)), member_num(m_num) + { + } uplus_data(const uplus_data& ref) = default; @@ -962,11 +963,12 @@ class locadd_data : public expr2t locadd_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc base_addr, - expr2tc added) : expr2t(t, id), base_addr(base_addr), added_num(added) + const expr2tc &base_addr, + const expr2tc &added) + : expr2t(t, id), base_addr(base_addr), added_num(added) { - } + locadd_data(const locadd_data& ref) = default; expr2tc base_addr; expr2tc added_num; @@ -979,6 +981,37 @@ class locadd_data : public expr2t }; +class heap_region_data : public expr2t +{ +public: + heap_region_data( + const type2tc &t, + datatype_ops::expr_ids id, + const expr2tc ®ion, + const expr2tc &start_loc, + const expr2tc &size) + : expr2t(t, id), region(region), start_loc(start_loc), size(size) + { + } + heap_region_data(const heap_region_data& ref) = default; + + expr2tc region; + expr2tc start_loc; + expr2tc size; + + // Type mangling: + typedef esbmct::field_traits + heap_region_region_field; + typedef esbmct::field_traits + heap_region_start_loc_field; + typedef esbmct::field_traits + heap_region_size_field; + typedef esbmct::expr2t_traits< + heap_region_region_field, + heap_region_start_loc_field, + heap_region_size_field> traits; +}; + class pointer_with_region_data : public expr2t { public: @@ -986,14 +1019,14 @@ class pointer_with_region_data : public expr2t const type2tc &t, datatype_ops::expr_ids id, expr2tc loc_ptr, - expr2tc region_heap - ) : expr2t(t, id), loc_ptr(loc_ptr), region(region_heap){ - + expr2tc region_heap) + : expr2t(t, id), loc_ptr(loc_ptr), region(region_heap) + { } + expr2tc loc_ptr; expr2tc region; - // Type mangling: typedef esbmct::field_traits pointer_with_region_loc_ptr_field; @@ -1007,8 +1040,10 @@ class heap_free_data : public expr2t { heap_free_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc pwr - ) : expr2t(t, id), pwr(pwr){} + expr2tc pwr) + : expr2t(t, id), pwr(pwr) + { + } expr2tc pwr; typedef esbmct::field_traits heap_free_data_pwr_field; @@ -1022,8 +1057,10 @@ class heap_load_data : public expr2t { datatype_ops::expr_ids id, expr2tc h, expr2tc start_addr, - unsigned int byte_len - ) : expr2t(t, id), heap(h), start_addr(start_addr), byte_len(byte_len){} + unsigned int byte_len) + : expr2t(t, id), heap(h), start_addr(start_addr), byte_len(byte_len) + { + } expr2tc heap; expr2tc start_addr; @@ -1037,8 +1074,6 @@ class heap_load_data : public expr2t { }; - - class heap_update_data : public expr2t { public: @@ -1048,15 +1083,16 @@ class heap_update_data : public expr2t expr2tc source_val, expr2tc start_addr, expr2tc updated_val, - unsigned int byte_len - ) : expr2t(t, id), src_heap(source_val), start_addr(start_addr), updated_val(updated_val), byte_len(byte_len){} + unsigned int byte_len) + : expr2t(t, id), src_heap(source_val), start_addr(start_addr), updated_val(updated_val), byte_len(byte_len) + { + } expr2tc src_heap; expr2tc start_addr; expr2tc updated_val; unsigned int byte_len; - // Type mangling: typedef esbmct::field_traits heap_update_data_src_heap_field; @@ -1073,8 +1109,6 @@ class heap_update_data : public expr2t }; - - class heap_append_data : public expr2t { public: heap_append_data( @@ -1083,8 +1117,10 @@ class heap_append_data : public expr2t { expr2tc original_heap, expr2tc start_addr, expr2tc create_val, - unsigned int byte_len - ) : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), create_val(create_val), byte_len(byte_len) {} + unsigned int byte_len) + : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), create_val(create_val), byte_len(byte_len) + { + } expr2tc src_heap; expr2tc start_addr; @@ -1108,7 +1144,6 @@ class heap_append_data : public expr2t { }; - class heap_delete_data : public expr2t { public: heap_delete_data( @@ -1116,8 +1151,10 @@ class heap_delete_data : public expr2t { datatype_ops::expr_ids id, expr2tc original_heap, expr2tc del_addr, - unsigned int byte_len - ) : expr2t(t, id), src_heap(original_heap), del_addr(del_addr), byte_len(byte_len) {} + unsigned int byte_len) + : expr2t(t, id), src_heap(original_heap), del_addr(del_addr), byte_len(byte_len) + { + } expr2tc src_heap; expr2tc del_addr; @@ -1145,8 +1182,10 @@ class heap_contains_data : public expr2t { datatype_ops::expr_ids id, expr2tc hvar, expr2tc start_loc, - unsigned int blk_byte_len - ) : expr2t(t, id), heapvar(hvar), start_loc(start_loc), byte_len(blk_byte_len){} + unsigned int blk_byte_len) + : expr2t(t, id), heapvar(hvar), start_loc(start_loc), byte_len(blk_byte_len) + { + } expr2tc heapvar; expr2tc start_loc; @@ -1796,8 +1835,8 @@ irep_typedefs(index, index_data); irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); +irep_typedefs(heap_region, heap_region_data); irep_typedefs(pointer_with_region, pointer_with_region_data); -irep_typedefs(heap_free, heap_free_data); irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); @@ -3262,97 +3301,117 @@ class index2t : public index_expr_methods class points_to2t : public points_to_expr_methods { public: - points_to2t(const type2tc &type, const expr2tc addr, const expr2tc& content, bool is_loc) : points_to_expr_methods(type, points_to_id, addr, content, is_loc) { - + points_to2t(const expr2tc addr, const expr2tc& content, bool is_loc) + : points_to_expr_methods(get_intheap_type(), points_to_id, addr, content, is_loc) + { } points_to2t(const points_to2t &ref) = default; - static std::string field_names[esbmct::num_type_fields]; - }; class uplus2t : public uplus_expr_methods { public: - uplus2t(const type2tc &type, - std::vector uplus_members) : uplus_expr_methods(type, uplus_id, std::move(uplus_members), uplus_members.size()) { - + uplus2t(std::vector uplus_members) + : uplus_expr_methods(get_intheap_type(), uplus_id, std::move(uplus_members), uplus_members.size()) + { } uplus2t(const uplus2t &ref) = default; - static std::string field_names[esbmct::num_type_fields]; - }; class locadd2t : public locadd_expr_methods { public: - locadd2t(const type2tc &type, expr2tc base_addr, expr2tc added) : locadd_expr_methods(type, locadd_id, base_addr, added) {} + locadd2t(const expr2tc &base_addr, const expr2tc &added) + : locadd_expr_methods(get_intloc_type(), locadd_id, base_addr, added) + { + } locadd2t(const locadd2t &ref) = default; - - static std::string field_names[esbmct::num_type_fields]; }; -class pointer_with_region2t : public pointer_with_region_expr_methods +class heap_region2t: public heap_region_expr_methods { public: - pointer_with_region2t(const type2tc &type, expr2tc loc_ptr, expr2tc region_heap): pointer_with_region_expr_methods(type, pointer_with_region_id, loc_ptr, region_heap) {} + heap_region2t(const expr2tc ®ion, const expr2tc &start_loc, const expr2tc &size) + : heap_region_expr_methods(get_intheap_type(), heap_region_id, region, start_loc, size) + { + } + heap_region2t(const heap_region2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; }; -class heap_free2t : public heap_free_expr_methods +class pointer_with_region2t : public pointer_with_region_expr_methods { public: - heap_free2t(const type2tc &type, expr2tc pwr) : heap_free_expr_methods(type, heap_free_id, pwr) {} + pointer_with_region2t(expr2tc loc_ptr, expr2tc region) + : pointer_with_region_expr_methods(get_intloc_type(), pointer_with_region_id, loc_ptr, region) + { + } static std::string field_names[esbmct::num_type_fields]; }; class heap_load2t : public heap_load_expr_methods { - public: - heap_load2t(const type2tc & type, expr2tc heap, expr2tc start_addr, unsigned int byte_len) : heap_load_expr_methods(type, expr2t::heap_load_id, heap, start_addr, byte_len) {} ; - heap_load2t(const heap_load2t& ref) = default; +public: + heap_load2t(const type2tc & type, expr2tc heap, expr2tc start_addr, unsigned int byte_len) + : heap_load_expr_methods(type, expr2t::heap_load_id, heap, start_addr, byte_len) + { + } + heap_load2t(const heap_load2t& ref) = default; - static std::string field_names[esbmct::num_type_fields]; + static std::string field_names[esbmct::num_type_fields]; }; class heap_update2t : public heap_update_expr_methods { - public: - heap_update2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, expr2tc updated_val, unsigned int byte_len) : heap_update_expr_methods(type, heap_update_id, source_heap, start_addr, updated_val, byte_len){} - heap_update2t(const heap_update2t &ref) = default; +public: + heap_update2t(expr2tc source_heap, expr2tc start_addr, expr2tc updated_val, unsigned int byte_len) + : heap_update_expr_methods(get_intheap_type(), heap_update_id, source_heap, start_addr, updated_val, byte_len) + { + } + heap_update2t(const heap_update2t &ref) = default; - static std::string field_names[esbmct::num_type_fields]; + static std::string field_names[esbmct::num_type_fields]; }; +class heap_append2t : public heap_append_expr_methods +{ +public: + heap_append2t(expr2tc source_heap, expr2tc start_addr, expr2tc create_val, unsigned int byte_len) + : heap_append_expr_methods(get_intheap_type(), heap_append_id, source_heap, start_addr, create_val, byte_len) + { + } + heap_append2t(const heap_append2t &ref) = default; - -class heap_append2t : public heap_append_expr_methods { - public: - heap_append2t(const type2tc &type, expr2tc source_heap, expr2tc start_addr, expr2tc create_val, unsigned int byte_len) : heap_append_expr_methods(type, heap_append_id, source_heap, start_addr, create_val, byte_len) {} - heap_append2t(const heap_append2t &ref) = default; - - static std::string field_names[esbmct::num_type_fields]; + static std::string field_names[esbmct::num_type_fields]; }; -class heap_delete2t : public heap_delete_expr_methods { - public: - heap_delete2t(const type2tc &type, expr2tc source_heap, expr2tc del_addr, unsigned int byte_len) : heap_delete_expr_methods(type, heap_delete_id, source_heap, del_addr, byte_len) {} - heap_delete2t(const heap_delete2t &ref) = default; +class heap_delete2t : public heap_delete_expr_methods +{ +public: + heap_delete2t(expr2tc source_heap, expr2tc del_addr, unsigned int byte_len) + : heap_delete_expr_methods(get_intheap_type(), heap_delete_id, source_heap, del_addr, byte_len) + { + } + heap_delete2t(const heap_delete2t &ref) = default; - static std::string field_names[esbmct::num_type_fields]; + static std::string field_names[esbmct::num_type_fields]; }; class heap_contains2t : public heap_contains_expr_methods { public: - heap_contains2t(const type2tc &type, expr2tc hvar, expr2tc start_loc, unsigned int byte_len) : heap_contains_expr_methods(type, heap_contains_id, hvar, start_loc, byte_len) {} + heap_contains2t(expr2tc hvar, expr2tc start_loc, unsigned int byte_len) + : heap_contains_expr_methods(get_bool_type(), heap_contains_id, hvar, start_loc, byte_len) + { + } heap_contains2t(const heap_contains2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 12f644ac..7d3c53e3 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -166,10 +166,10 @@ std::string points_to2t::field_names[esbmct::num_type_fields] = {"addr", "content", "is_loc", "", ""}; std::string locadd2t::field_names[esbmct::num_type_fields] = {"baseaddr", "added_num", "", "", ""}; +std::string heap_region2t::field_names[esbmct::num_type_fields] = +{"region", "start_loc", "size", "", ""}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; -std::string heap_free2t::field_names[esbmct::num_type_fields] = -{"pointer_with_region", "", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 83795c28..b4c5dfe7 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -30,11 +30,11 @@ expr_typedefs3(with, with_data); expr_typedefs2(member, member_data); expr_typedefs2(index, index_data); expr_typedefs3(points_to, points_to_data); -expr_typedefs2(uplus, uplus_data); +expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); +expr_typedefs3(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); -expr_typedefs1(heap_free, heap_free_data); -expr_typedefs3(heap_load, heap_load_data); +expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs4(heap_append, heap_append_data); expr_typedefs3(heap_delete, heap_delete_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index b2064584..dd9b6434 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -792,18 +792,19 @@ expr2tc dereferencet::build_reference_to( // expr2tc obj_ptr = typecast2tc(ptr_type, object); const pointer_with_region2t& pwr = to_pointer_with_region2t(object); - expr2tc region_heap = pwr.region; - - // pointer_guard = same_object2tc(deref_expr, obj_ptr); - pointer_guard = heap_contains2tc(get_bool_type(), region_heap, deref_expr, 1); - log_status("generated pointer guard:"); - pointer_guard->dump(); + const heap_region2t& heap_region = to_heap_region2t(pwr.region); + // TODO: fix sorts + pointer_guard = and2tc( + greaterthanequal2tc(heap_region.start_loc, deref_expr), + lessthan2tc(deref_expr, locadd2tc(heap_region.start_loc, heap_region.size)) + ); + // heap_contains2tc(get_bool_type(), region_heap, deref_expr, 1); guardt tmp_guard(guard); tmp_guard.add(pointer_guard); // Check that the object we're accessing is actually alive and valid for this // mode. - valid_check_slhv(object, tmp_guard, mode); + valid_check(object, tmp_guard, mode); // Don't do anything further if we're freeing things if (is_free(mode)) @@ -2220,83 +2221,6 @@ void dereferencet::valid_check( { const expr2tc &symbol = get_symbol(object); - if (is_constant_string2t(symbol)) - { - // always valid, but can't write - - if (is_write(mode)) - { - dereference_failure( - "pointer dereference", "write access to string constant", guard); - } - } - else if (is_nil_expr(symbol)) - { - // always "valid", shut up - return; - } - else if (is_symbol2t(symbol)) - { - // Hacks, but as dereferencet object isn't persistent, necessary. Fix by - // making dereferencet persistent. - if (has_prefix( - to_symbol2t(symbol).thename.as_string(), "symex::invalid_object")) - { - // This is an invalid object; if we're in read or write mode, that's an error. - if (is_read(mode) || is_write(mode)) - dereference_failure("pointer dereference", "invalid pointer", guard); - return; - } - - const symbolt &sym = *ns.lookup(to_symbol2t(symbol).thename); - if (has_prefix(sym.id.as_string(), "symex_dynamic::")) - { - // Assert that it hasn't (nondeterministically) been invalidated. - expr2tc addrof = address_of2tc(symbol->type, symbol); - expr2tc valid_expr = valid_object2tc(addrof); - expr2tc not_valid_expr = not2tc(valid_expr); - - guardt tmp_guard(guard); - tmp_guard.add(not_valid_expr); - - std::string foo = is_free(mode) ? "invalidated dynamic object freed" - : "invalidated dynamic object"; - dereference_failure("pointer dereference", foo, tmp_guard); - } - else - { - // Not dynamic; if we're in free mode, that's an error. - if (is_free(mode)) - { - dereference_failure( - "pointer dereference", "free() of non-dynamic memory", guard); - return; - } - - // Otherwise, this is a pointer to some kind of lexical variable, with - // either global or function-local scope. Ask symex to determine if - // it's live. - if (!dereference_callback.is_live_variable(symbol)) - { - // Any access where this guard is true -> failure - dereference_failure( - "pointer dereference", - "accessed expired variable pointer `" + - get_pretty_name(to_symbol2t(symbol).thename.as_string()) + "'", - guard); - return; - } - } - } -} - -void dereferencet::valid_check_slhv( - const expr2tc &object, - const guardt &guard, - modet mode) -{ - const expr2tc &symbol = get_symbol(object); - if (is_constant_string2t(symbol)) { // always valid, but can't write @@ -2381,6 +2305,97 @@ void dereferencet::valid_check_slhv( } } +// void dereferencet::valid_check_slhv( +// const expr2tc &object, +// const guardt &guard, +// modet mode) +// { +// const expr2tc &symbol = get_symbol(object); + +// if (is_constant_string2t(symbol)) +// { +// // always valid, but can't write + +// if (is_write(mode)) +// { +// dereference_failure( +// "pointer dereference", "write access to string constant", guard); +// } +// } +// else if (is_nil_expr(symbol)) +// { +// // always "valid", shut up +// return; +// } +// else if (is_symbol2t(symbol)) +// { +// // Hacks, but as dereferencet object isn't persistent, necessary. Fix by +// // making dereferencet persistent. +// if (has_prefix( +// to_symbol2t(symbol).thename.as_string(), "symex::invalid_object")) +// { +// // This is an invalid object; if we're in read or write mode, that's an error. +// if (is_read(mode) || is_write(mode)) +// dereference_failure("pointer dereference", "invalid pointer", guard); +// return; +// } + +// const symbolt &sym = *ns.lookup(to_symbol2t(symbol).thename); +// if (has_prefix(sym.id.as_string(), "symex_dynamic::")) +// { +// // Assert that it hasn't (nondeterministically) been invalidated. +// expr2tc addrof = address_of2tc(symbol->type, symbol); +// expr2tc valid_expr = valid_object2tc(addrof); +// expr2tc not_valid_expr = not2tc(valid_expr); + +// guardt tmp_guard(guard); +// tmp_guard.add(not_valid_expr); + +// std::string foo = is_free(mode) ? "invalidated dynamic object freed" +// : "invalidated dynamic object"; +// dereference_failure("pointer dereference", foo, tmp_guard); +// } +// else +// { +// // Not dynamic; if we're in free mode, that's an error. +// if (is_free(mode)) +// { +// dereference_failure( +// "pointer dereference", "free() of non-dynamic memory", guard); +// return; +// } + +// // Otherwise, this is a pointer to some kind of lexical variable, with +// // either global or function-local scope. Ask symex to determine if +// // it's live. +// if (!dereference_callback.is_live_variable(symbol)) +// { +// // Any access where this guard is true -> failure +// dereference_failure( +// "pointer dereference", +// "accessed expired variable pointer `" + +// get_pretty_name(to_symbol2t(symbol).thename.as_string()) + "'", +// guard); +// return; +// } +// } +// } else if(is_pointer_with_region2t(symbol)) { +// // slhv +// log_status("pointer with region dereference failure here"); +// // assert that the pointer we dereference with a specific length lies in the heap variable +// // TODO: maybe add a special expression type to denote that the pointer_with_region is not valid +// expr2tc not_valid_pointer_with_region = not2tc(valid_object2tc(symbol)); +// log_status("not valid print:"); +// not_valid_pointer_with_region->dump(); +// guardt tmp_guard(guard); +// tmp_guard.add(not_valid_pointer_with_region); +// std::string foo = is_free(mode) ? "invalid free pointer" +// : "invalid dereference pointer"; +// dereference_failure("pointer dereference", foo, tmp_guard); +// return; +// } +// } + void dereferencet::bounds_check( const expr2tc &expr, const expr2tc &offset, @@ -2565,7 +2580,7 @@ void dereferencet::check_pointer_with_region_access( expr2tc region = pointer_reg.region; expr2tc pointer_loc = pointer_reg.loc_ptr; unsigned int byte_len = type->get_width()/8; - expr2tc bound_check = heap_contains2tc(get_bool_type(), region, pointer_loc, byte_len); + expr2tc bound_check = heap_contains2tc(region, pointer_loc, byte_len); if(!options.get_bool_option("no-bounds-check")) { guardt tmp_guard = guard; tmp_guard.add(bound_check); diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 7347e87b..c182eb3f 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -403,7 +403,7 @@ class dereferencet const type2tc &type, const guardt &guard); void valid_check(const expr2tc &expr, const guardt &guard, modet mode); - void valid_check_slhv(const expr2tc &expr, const guardt &guard, modet mode); + // void valid_check_slhv(const expr2tc &expr, const guardt &guard, modet mode); std::vector extract_bytes( const expr2tc &object, unsigned int bytes, diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 3d52fa2b..73d10d68 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -334,6 +334,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) { case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: + case expr2t::heap_region_id: case expr2t::pointer_with_region_id: case expr2t::points_to_id: case expr2t::uplus_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index ad067fbb..56f5bd02 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -188,6 +188,11 @@ z3_slhv_convt::convert_slhv_opts( switch (expr->expr_id) { case expr2t::constant_intheap_id: return mk_emp(); case expr2t::constant_intloc_id: return mk_nil(); + case expr2t::heap_region_id: + { + assert(args.size() == 3); + return convert_ast(to_heap_region2t(expr).region); + } case expr2t::pointer_with_region_id: { const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 55b0e5a9..6cc41718 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2627,6 +2627,16 @@ exprt migrate_expr_back(const expr2tc &ref) locadd.copy_to_operands(migrate_expr_back(ref2.added_num)); return locadd; } + case expr2t::heap_region_id: + { + const heap_region2t &ref2 = to_heap_region2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt hregion("heap_region", thetype); + hregion.copy_to_operands(migrate_expr_back(ref2.region)); + hregion.copy_to_operands(migrate_expr_back(ref2.start_loc)); + hregion.copy_to_operands(migrate_expr_back(ref2.size)); + return hregion; + } case expr2t::pointer_with_region_id: { const pointer_with_region2t &ref2 = to_pointer_with_region2t(ref); @@ -2636,14 +2646,6 @@ exprt migrate_expr_back(const expr2tc &ref) pointer_with_region.copy_to_operands(migrate_expr_back(ref2.region)); return pointer_with_region; } - case expr2t::heap_free_id: - { - const heap_free2t &ref2 = to_heap_free2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt heap_free("heap_free", thetype); - heap_free.copy_to_operands(migrate_expr_back(ref2.pwr)); - return heap_free; - } case expr2t::heap_load_id: { const heap_load2t& ref2 = to_heap_load2t(ref); From 82e49f7c09a4c1fbff0b956a754d2838b34d8f32 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 31 Jul 2024 16:35:51 +0800 Subject: [PATCH 027/126] encoding same_object in SLHV --- src/pointer-analysis/dereference.cpp | 11 ++--------- src/solvers/smt/smt_conv.cpp | 3 ++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 20 +++++++++++++++++++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index dd9b6434..f912aa6e 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -791,14 +791,8 @@ expr2tc dereferencet::build_reference_to( // type2tc ptr_type = pointer_type2tc(object->type); // expr2tc obj_ptr = typecast2tc(ptr_type, object); - const pointer_with_region2t& pwr = to_pointer_with_region2t(object); - const heap_region2t& heap_region = to_heap_region2t(pwr.region); - // TODO: fix sorts - pointer_guard = and2tc( - greaterthanequal2tc(heap_region.start_loc, deref_expr), - lessthan2tc(deref_expr, locadd2tc(heap_region.start_loc, heap_region.size)) - ); - // heap_contains2tc(get_bool_type(), region_heap, deref_expr, 1); + assert(is_pointer_with_region2t(object)); + pointer_guard = same_object2tc(deref_expr, object); guardt tmp_guard(guard); tmp_guard.add(pointer_guard); @@ -1228,7 +1222,6 @@ void dereferencet::build_reference_slhv( log_error("ERROR: currently not support non-scalar type dereference"); abort(); } - } void dereferencet::construct_from_array( diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 73d10d68..6aaa62a2 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -733,8 +733,9 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) if (this->solver_text() != "Z3-slhv") { args[0] = args[0]->project(this, 0); args[1] = args[1]->project(this, 0); + } else { + a = convert_slhv_opts(expr, args); } - a = mk_eq(args[0], args[1]); break; } case expr2t::pointer_offset_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 56f5bd02..56842b07 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -277,12 +277,30 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_delete_id: { - const heap_delete2t& heap_del = to_heap_delete2t(expr); smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); assert_ast(mk_eq(args[0], mk_uplus(h1, mk_pt(args[1], v1)))); return h1; } + case expr2t::same_object_id: + { + const same_object2t& same = to_same_object2t(expr); + assert(is_pointer_with_region2t(same.side_2)); + const pointer_with_region2t& pwr = to_pointer_with_region2t(same.side_2); + const heap_region2t& heap_region = to_heap_region2t(pwr.region); + assert(is_constant_int2t(heap_region.size)); + smt_astt start_loc = convert_ast(heap_region.start_loc); + smt_astt size = convert_ast(heap_region.size); + smt_astt nondet_offset = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + return + mk_and( + mk_eq(args[0], mk_locadd(start_loc, nondet_offset)), + mk_and( + mk_le(mk_smt_int(BigInt(0)), nondet_offset), + mk_lt(nondet_offset, size) + ) + ); + } default: { log_status("Invalid SLHV operations!!!"); abort(); From 739a6054cf7b7d41e5458b5bfa2f7a1ba92b5ab8 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 31 Jul 2024 17:18:41 +0800 Subject: [PATCH 028/126] update --- src/goto-symex/slice.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index 7cc61c99..fa78e91d 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -101,14 +101,6 @@ class symex_slicet : public slicer fine_timet algorithm_start = current_time(); for (auto &step : boost::adaptors::reverse(eq)) run_on_step(step); - - log_status("show eq system"); - int ss = 0; - for (auto &step : boost::adaptors::reverse(eq)) { - log_status("step -{} is ignored? {}", ++ss, step.ignore); - step.dump(); - } - fine_timet algorithm_stop = current_time(); log_status( "Slicing time: {}s (removed {} assignments)", From 708a6a09ca0987a7155b6cb4320fae41afdf34d6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 1 Aug 2024 11:26:50 +0800 Subject: [PATCH 029/126] update slicing and fix build_goto_trace in --multi-property --- src/esbmc/bmc.cpp | 13 ++++++++++++- src/goto-symex/slice.h | 5 ++++- src/solvers/smt/smt_conv.cpp | 4 +++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 2ee08408..4106ae86 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -647,7 +647,7 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); - show_vcc(*eq); + // show_vcc(*eq); // log_status("smt_convt created"); // if (options.get_bool_option("z3-slhv")) { // show_vcc(*eq); @@ -750,6 +750,9 @@ smt_convt::resultt bmct::multi_property_check( &is_fail_fast, &fail_fast_limit, &fail_fast_cnt](const size_t &i) { + + log_status("begin to check claim {}", i); + //"multi-fail-fast n": stop after first n SATs found. if (is_fail_fast && fail_fast_cnt >= fail_fast_limit) return; @@ -787,6 +790,8 @@ smt_convt::resultt bmct::multi_property_check( symex_slicet slicer(options); slicer.run(local_eq.SSA_steps); + show_vcc(local_eq); + // Initialize a solver std::unique_ptr runtime_solver(create_solver("", ns, options)); // Save current instance @@ -806,6 +811,12 @@ smt_convt::resultt bmct::multi_property_check( // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) { + if (runtime_solver->solver_text() == "Z3-slhv") { + final_result = result; + fail_fast_cnt++; + return; + } + bool is_compact_trace = true; if ( options.get_bool_option("no-slice") && diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index fa78e91d..88eb078a 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -99,8 +99,11 @@ class symex_slicet : public slicer { sliced = 0; fine_timet algorithm_start = current_time(); - for (auto &step : boost::adaptors::reverse(eq)) + int cnt = 0; + for (auto &step : boost::adaptors::reverse(eq)) { + if (step.is_assert() && step.ignore) continue; run_on_step(step); + } fine_timet algorithm_stop = current_time(); log_status( "Slicing time: {}s (removed {} assignments)", diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 6aaa62a2..b51323a1 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -325,10 +325,11 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) args[i]->dump(); } log_status(" -------------- convert args finished ------------ "); - } } + expr->dump(); + smt_astt a; switch (expr->expr_id) { @@ -733,6 +734,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) if (this->solver_text() != "Z3-slhv") { args[0] = args[0]->project(this, 0); args[1] = args[1]->project(this, 0); + a = mk_eq(args[0], args[1]); } else { a = convert_slhv_opts(expr, args); } From 4a3c86a42ec8c26dcd48cb1996280443d8c4a0ed Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 1 Aug 2024 15:05:15 +0800 Subject: [PATCH 030/126] update slicing(fix) --- src/esbmc/bmc.cpp | 2 -- src/goto-symex/slice.h | 2 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 4 +--- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 4106ae86..2994655b 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -790,8 +790,6 @@ smt_convt::resultt bmct::multi_property_check( symex_slicet slicer(options); slicer.run(local_eq.SSA_steps); - show_vcc(local_eq); - // Initialize a solver std::unique_ptr runtime_solver(create_solver("", ns, options)); // Save current instance diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index 88eb078a..3eb86d87 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -101,7 +101,7 @@ class symex_slicet : public slicer fine_timet algorithm_start = current_time(); int cnt = 0; for (auto &step : boost::adaptors::reverse(eq)) { - if (step.is_assert() && step.ignore) continue; + if (step.ignore) continue; run_on_step(step); } fine_timet algorithm_stop = current_time(); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 56842b07..f0509099 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -195,9 +195,7 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::pointer_with_region_id: { - const pointer_with_region2t& pwr = to_pointer_with_region2t(expr); - const symbol2t& nsym = to_symbol2t(pwr.loc_ptr); - return mk_smt_symbol(nsym.get_symbol_name(), mk_intloc_sort()); + return convert_ast(to_pointer_with_region2t(expr).loc_ptr); } case expr2t::points_to_id: { From 2100b7f2480e9fc2a3b3838e618b18815313714b Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Thu, 1 Aug 2024 17:26:10 +0800 Subject: [PATCH 031/126] commit for merge --- benchmark/case_0.c | 6 +++--- src/esbmc/bmc.cpp | 2 +- src/goto-symex/builtin_functions.cpp | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index c12edad1..12279bf0 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -2,10 +2,10 @@ int main(){ // int whatever; - int * data = malloc(2*sizeof(int)); + int * data = malloc(sizeof(int)); int * data2 = malloc(2*sizeof(int)); - int i = *(data2 + 1); - free(data2); + free(data); + int i = *(data); // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 2ee08408..d3f4eabd 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -772,7 +772,7 @@ smt_convt::resultt bmct::multi_property_check( // C++20 reached_mul_claims.contains is_verified = reached_mul_claims.count(cmt_loc) ? true : false; } - else + elseconvert { cmt_loc = claim.claim_msg + "\t" + claim.claim_loc; is_verified = reached_claims.count(cmt_loc) ? true : false; diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index b79c92cf..fca48f83 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -494,10 +494,11 @@ void goto_symext::symex_free(const expr2tc &expr) } expr2tc emp_heap = constant_intheap2tc(get_intheap_type(), true); - + log_status("symex free freed_heap emp_heap"); symex_assign(code_assign2tc(freed_heap, emp_heap)); expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); expr2tc heap_deleted = heap_delete2tc(get_intheap_type(), alloc_size_heap_symbol, freed_pointer, 4); + log_status("symex free alloc_size_heap heap_delete"); symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); } From 3a7e9495a5e84765f6870344a2513cc0f4e15950 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 1 Aug 2024 17:38:45 +0800 Subject: [PATCH 032/126] fix typo --- src/esbmc/bmc.cpp | 2 +- src/goto-symex/slice.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 9c4b6203..2994655b 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -775,7 +775,7 @@ smt_convt::resultt bmct::multi_property_check( // C++20 reached_mul_claims.contains is_verified = reached_mul_claims.count(cmt_loc) ? true : false; } - elseconvert + else { cmt_loc = claim.claim_msg + "\t" + claim.claim_loc; is_verified = reached_claims.count(cmt_loc) ? true : false; diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index 3eb86d87..8adc25a8 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -99,7 +99,6 @@ class symex_slicet : public slicer { sliced = 0; fine_timet algorithm_start = current_time(); - int cnt = 0; for (auto &step : boost::adaptors::reverse(eq)) { if (step.ignore) continue; run_on_step(step); From 7d4bd22bdad232373c5bedc02c650c691f998959 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 2 Aug 2024 16:37:22 +0800 Subject: [PATCH 033/126] update heap_region --- src/goto-symex/builtin_functions.cpp | 20 +------------------ src/goto-symex/slice.cpp | 2 -- src/irep2/irep2_expr.h | 15 +++++--------- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/value_set.cpp | 11 +++++++++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 20 +++++++++++++++++-- src/solvers/z3-slhv/z3_slhv_conv.h | 1 + src/util/migrate.cpp | 9 ++++----- 9 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 07f6a3ed..59b54785 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -295,30 +295,12 @@ expr2tc goto_symext::symex_mem( std::vector pt_vec; uint pt_num = bytes % pt_bytes == 0 ? bytes / pt_bytes : bytes; - for(unsigned i = 0; i < pt_num; i ++) { - expr2tc offset = constant_int2tc(int_type2(), BigInt(i)); - expr2tc addr_i = i == 0 ? alloc_base_addr : locadd2tc(alloc_base_addr, offset); - // TODO: fix int_type - expr2tc fresh_data_i = - sideeffect2tc( - get_int8_type(), - expr2tc(), - expr2tc(), - std::vector(), - type2tc(), - sideeffect2t::nondet - ); - expr2tc pt_i = points_to2tc(addr_i, fresh_data_i, false); - pt_vec.push_back(pt_i); - } - - expr2tc heap = pt_vec.size() > 1 ? uplus2tc(pt_vec) : pt_vec[0]; expr2tc origin_base_addr(alloc_base_addr); cur_state->rename(alloc_base_addr); expr2tc region_size = constant_int2tc(int_type2(), BigInt(pt_num)); - expr2tc region = heap_region2tc(heap, origin_base_addr, region_size); + expr2tc region = heap_region2tc(origin_base_addr, region_size); log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(allocated_heap, region)); diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index c68d5cc4..0ec551ef 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -13,8 +13,6 @@ bool symex_slicet::get_symbols(const expr2tc &expr) bool res = false; if (is_pointer_with_region2t(expr)) { return get_symbols(to_pointer_with_region2t(expr).loc_ptr); - } else if (is_heap_region2t(expr)) { - return get_symbols(to_heap_region2t(expr).region); } else { // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 427c3033..6058a5a2 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -987,27 +987,22 @@ class heap_region_data : public expr2t heap_region_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc ®ion, const expr2tc &start_loc, const expr2tc &size) - : expr2t(t, id), region(region), start_loc(start_loc), size(size) + : expr2t(t, id), start_loc(start_loc), size(size) { } heap_region_data(const heap_region_data& ref) = default; - expr2tc region; expr2tc start_loc; expr2tc size; // Type mangling: - typedef esbmct::field_traits - heap_region_region_field; typedef esbmct::field_traits heap_region_start_loc_field; typedef esbmct::field_traits heap_region_size_field; typedef esbmct::expr2t_traits< - heap_region_region_field, heap_region_start_loc_field, heap_region_size_field> traits; }; @@ -1019,8 +1014,8 @@ class pointer_with_region_data : public expr2t const type2tc &t, datatype_ops::expr_ids id, expr2tc loc_ptr, - expr2tc region_heap) - : expr2t(t, id), loc_ptr(loc_ptr), region(region_heap) + expr2tc region) + : expr2t(t, id), loc_ptr(loc_ptr), region(region) { } @@ -3338,8 +3333,8 @@ class locadd2t : public locadd_expr_methods class heap_region2t: public heap_region_expr_methods { public: - heap_region2t(const expr2tc ®ion, const expr2tc &start_loc, const expr2tc &size) - : heap_region_expr_methods(get_intheap_type(), heap_region_id, region, start_loc, size) + heap_region2t(const expr2tc &start_loc, const expr2tc &size) + : heap_region_expr_methods(get_intheap_type(), heap_region_id, start_loc, size) { } heap_region2t(const heap_region2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 7d3c53e3..ac505bc1 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -167,7 +167,7 @@ std::string points_to2t::field_names[esbmct::num_type_fields] = std::string locadd2t::field_names[esbmct::num_type_fields] = {"baseaddr", "added_num", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = -{"region", "start_loc", "size", "", ""}; +{"start_loc", "size", "", "", ""}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index b4c5dfe7..c878b3a6 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -32,7 +32,7 @@ expr_typedefs2(index, index_data); expr_typedefs3(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); -expr_typedefs3(heap_region, heap_region_data); +expr_typedefs2(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index bc0a53f1..ca4017cb 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -563,13 +563,22 @@ void value_sett::get_value_set_rec( } } // SLHV: - if(is_pointer_with_region2t(expr)) { + if(is_pointer_with_region2t(expr)) + { log_status("get value rec: is pointer with region2t"); assert(is_intloc_type(expr)); expr2tc new_loc_object = expr; insert(dest, new_loc_object, BigInt(0)); return; } + // TODO: not used + if (is_heap_region2t(expr)) + { + log_status("get value rec: is heap region"); + expr2tc new_loc_object = expr; + insert(dest, new_loc_object, BigInt(0)); + return; + } if (is_add2t(expr) || is_sub2t(expr)) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index f0509099..f92bd969 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -107,6 +107,13 @@ smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { ), this->mk_intheap_sort()); } +smt_astt z3_slhv_convt::mk_uplus(std::vector pts) { + z3::expr_vector pt_vec(z3_ctx); + for (auto pt : pts) { + pt_vec.push_back(to_solver_smt_ast(pt)->a); + } + return new_ast(z3::uplus(pt_vec), this->mk_intheap_sort()); +} smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { assert(a->sort == mk_intheap_sort()); assert(b->sort == mk_intheap_sort()); @@ -190,8 +197,17 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::constant_intloc_id: return mk_nil(); case expr2t::heap_region_id: { - assert(args.size() == 3); - return convert_ast(to_heap_region2t(expr).region); + assert(args.size() == 2); + const heap_region2t& region = to_heap_region2t(expr); + assert(is_constant_int2t(region.size)); + const int n = to_constant_int2t(region.size).as_ulong(); + std::vector pt_vec; + for (unsigned i = 0; i < n; i++) { + smt_astt loc = i == 0 ? args[0] : mk_locadd(args[0], mk_smt_int(BigInt(i))); + smt_astt v = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + pt_vec.push_back(mk_pt(loc, v)); + } + return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); } case expr2t::pointer_with_region_id: { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index abaef41f..d2b4d172 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -22,6 +22,7 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_nil(); smt_astt mk_pt(smt_astt a, smt_astt b); smt_astt mk_uplus(smt_astt a, smt_astt b); + smt_astt mk_uplus(std::vector pts); smt_astt mk_subh(smt_astt a, smt_astt b); smt_astt mk_disjh(smt_astt a, smt_astt b); smt_astt mk_locadd(smt_astt a, smt_astt b); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 6cc41718..5b220590 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2631,11 +2631,10 @@ exprt migrate_expr_back(const expr2tc &ref) { const heap_region2t &ref2 = to_heap_region2t(ref); typet thetype = migrate_type_back(ref->type); - exprt hregion("heap_region", thetype); - hregion.copy_to_operands(migrate_expr_back(ref2.region)); - hregion.copy_to_operands(migrate_expr_back(ref2.start_loc)); - hregion.copy_to_operands(migrate_expr_back(ref2.size)); - return hregion; + exprt region("heap_region", thetype); + region.copy_to_operands(migrate_expr_back(ref2.start_loc)); + region.copy_to_operands(migrate_expr_back(ref2.size)); + return region; } case expr2t::pointer_with_region_id: { From b83e430a542e850a9f7d5dbb0b60408a7eeb266f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 6 Aug 2024 12:47:27 +0800 Subject: [PATCH 034/126] update regions(at most one time) when dereferencing --- src/esbmc/bmc.cpp | 2 + src/esbmc/esbmc_parseoptions.cpp | 2 + src/goto-symex/builtin_functions.cpp | 75 ++++++++++--------- src/goto-symex/goto_symex.h | 8 ++ src/goto-symex/symex_assign.cpp | 34 +++++++++ src/goto-symex/symex_dereference.cpp | 53 +++++++++++++ src/goto-symex/symex_valid_object.cpp | 3 + src/irep2/irep2_expr.cpp | 27 ++++++- src/irep2/irep2_expr.h | 22 ++++-- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 22 +++++- src/pointer-analysis/dereference.h | 9 +++ src/solvers/z3-slhv/z3_slhv_conv.cpp | 16 +++- 14 files changed, 230 insertions(+), 47 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 2994655b..4106ae86 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -790,6 +790,8 @@ smt_convt::resultt bmct::multi_property_check( symex_slicet slicer(options); slicer.run(local_eq.SSA_steps); + show_vcc(local_eq); + // Initialize a solver std::unique_ptr runtime_solver(create_solver("", ns, options)); // Save current instance diff --git a/src/esbmc/esbmc_parseoptions.cpp b/src/esbmc/esbmc_parseoptions.cpp index 2a65beff..e6fd6df2 100644 --- a/src/esbmc/esbmc_parseoptions.cpp +++ b/src/esbmc/esbmc_parseoptions.cpp @@ -527,6 +527,8 @@ int esbmc_parseoptionst::doit() cmdline.isset("termination") || cmdline.isset("incremental-bmc") || cmdline.isset("falsification") || cmdline.isset("k-induction")) return do_bmc_strategy(options, goto_functions); + + log_status("before starting BMC"); // If no strategy is chosen, just rely on the simplifier // and the flags set through CMD diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 59b54785..b7b99e3b 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -111,7 +111,17 @@ expr2tc goto_symext::symex_mem( const sideeffect2t &code) { log_status("symex_mem start: "); - if (is_nil_expr(lhs)) + lhs->dump(); + code.dump(); + + expr2tc new_lhs = lhs; + if (is_heap_load2t(lhs)) + { + assert(is_pointer_type(new_lhs->type)); + replace_heap_load(new_lhs); + } + + if (is_nil_expr(new_lhs)) return expr2tc(); // ignore // size @@ -245,9 +255,6 @@ expr2tc goto_symext::symex_mem( } else { log_status("create heap symbol for allocation"); - // TODO: fix the right width of pointee - uint32_t pt_bytes = 4; - // value symbolt symbol; symbol.name = "dynamic_heap_"+ i2string(dynamic_counter); @@ -259,48 +266,46 @@ expr2tc goto_symext::symex_mem( symbol.type = typet(typet::t_intheap); // Size in SLHV is byte level - expr2tc bytesize; - if (!is_constant_int2t(size)) { - size = size.simplify(); - } - if (is_constant_int2t(size)) { - bytesize = - constant_int2tc(get_uint32_type(), - BigInt( - to_constant_int2t(size).value.to_uint64() - * type->get_width() / 8 - ) - ); - symbol.type.size(migrate_expr_back(bytesize)); - } else { - log_error("SLHV does not support dynamic array size"); + // expr2tc bytesizes + expr2tc operand = code.operand; + if (!is_constant_int2t(operand)) + operand = operand.simplify(); + if (!is_constant_int2t(operand)) + { + log_error("Do not support dynamic size"); abort(); } + uint total_bytes = to_constant_int2t(operand).value.to_uint64(); + uint pt_bytes = type.get()->get_width() / 8; + uint size = total_bytes / pt_bytes; + if (pt_bytes == 1) + { + pt_bytes = total_bytes; + size = 1; + } + expr2tc region_pt_bytes = constant_int2tc(get_uint64_type(), BigInt(pt_bytes)); + expr2tc region_size = constant_int2tc(get_uint64_type(), BigInt(size)); + symbol.type.dynamic(true); symbol.mode = "C"; log_status("new_context.add(symbol);"); new_context.add(symbol); - type2tc heap_type = get_intheap_type(); - expr2tc allocated_heap = symbol2tc(heap_type, symbol.id); - std::vector pts; - + assert(is_symbol2t(lhs)); + expr2tc allocated_heap = symbol2tc(get_intheap_type(), symbol.id); guardt alloc_guard = cur_state->guard; - - unsigned bytes = to_constant_int2t(bytesize).as_ulong(); - log_status("Unsiged size: {}", bytes); - - expr2tc alloc_base_addr = lhs; - - std::vector pt_vec; - uint pt_num = bytes % pt_bytes == 0 ? bytes / pt_bytes : bytes; - + expr2tc alloc_base_addr = new_lhs; expr2tc origin_base_addr(alloc_base_addr); cur_state->rename(alloc_base_addr); - expr2tc region_size = constant_int2tc(int_type2(), BigInt(pt_num)); - expr2tc region = heap_region2tc(origin_base_addr, region_size); + expr2tc region = + heap_region2tc( + origin_base_addr, + region_pt_bytes, + region_size, + size != 1 + ); log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(allocated_heap, region)); @@ -309,7 +314,7 @@ expr2tc goto_symext::symex_mem( expr2tc base_value_symbol = symbol2tc(get_intloc_type(), to_symbol2t(origin_base_addr).get_symbol_name()); expr2tc base_pointer_region_object = - pointer_with_region2tc(base_value_symbol, region); + pointer_with_region2tc(base_value_symbol, allocated_heap); symex_assign( code_assign2tc( origin_base_addr, diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index ce79f5ce..9712a08c 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -800,6 +800,12 @@ class goto_symext */ void replace_nondet(expr2tc &expr); + /** + * Replace heap_load with a new pointer + * @param expr Expr to search for heap_load. + */ + void replace_heap_load(expr2tc &expr); + /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. @@ -957,6 +963,8 @@ class symex_dereference_statet : public dereference_callbackt void dump_internal_state(const std::list &data) override; bool is_live_variable(const expr2tc &sym) override; + + void update_regions(const expr2tc &expr) override; }; #endif diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index fedad1dd..53f793ad 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -187,13 +187,19 @@ void goto_symext::symex_assign( replace_nondet(lhs); replace_nondet(rhs); + lhs->dump(); + rhs->dump(); + intrinsic_races_check_dereference(lhs); log_status("dereference lhs write"); dereference(lhs, dereferencet::WRITE); log_status("dereference rhs read"); dereference(rhs, dereferencet::READ); + log_status("replace lhs"); replace_dynamic_allocation(lhs); + log_status("replace rhs"); replace_dynamic_allocation(rhs); + log_status("replace done"); // printf expression that has lhs if (is_code_printf2t(rhs)) @@ -251,8 +257,11 @@ void goto_symext::symex_assign( } } + log_status("before symex assign rec"); + guardt g(guard); // NOT the state guard! symex_assign_rec(lhs, original_lhs, rhs, expr2tc(), g, hidden_ssa); + log_status("xxxxxxxxxxxx symex assign: done for this step"); } void goto_symext::symex_assign_rec( @@ -901,3 +910,28 @@ void goto_symext::replace_nondet(expr2tc &expr) }); } } + + +void goto_symext::replace_heap_load(expr2tc &expr) +{ + heap_load2t& heap_load = to_heap_load2t(expr); + + unsigned int &nondet_counter = get_nondet_counter(); + nondet_counter++; + + symbolt symbol; + symbol.name = "nondet_loc_"+ i2string(nondet_counter); + + symbol.id = std::string("symex_dynamic::") + id2string(symbol.name); + symbol.lvalue = true; + symbol.type = typet(typet::t_intloc); + // symbol.type.dynamic(true); + symbol.mode = "C"; + new_context.add(symbol); + + expr2tc ptr = symbol2tc(get_intloc_type(), symbol.name); + + symex_assign(code_assign2tc(ptr, expr)); + + expr = ptr; +} \ No newline at end of file diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 00a78570..743f7773 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -165,6 +166,58 @@ bool symex_dereference_statet::is_live_variable(const expr2tc &symbol) return false; } +void symex_dereference_statet::update_regions(const expr2tc &expr) +{ + assert(is_heap_region2t(expr)); + const heap_region2t& region = to_heap_region2t(expr); + + // update value set + // log_status("update value set"); + value_sett& value_set = goto_symex.cur_state->value_set; + for (auto& value : value_set.values) + { + for (auto& obj : value.second.object_map) + { + if (!is_heap_region2t(value_set.object_numbering[obj.first])) continue; + heap_region2t& obj_reg = + to_heap_region2t(value_set.object_numbering[obj.first]); + // obj_reg.dump(); + if (to_symbol2t(region.start_loc).get_symbol_name() == + to_symbol2t(obj_reg.start_loc).get_symbol_name()) + { + // log_status("found region to be updated"); + value_set.object_numbering[obj.first] = expr; + } + } + } + + // update eq system + log_status("update eq system"); + std::shared_ptr eq = + std::dynamic_pointer_cast(goto_symex.target); + for(auto& ssa_step : eq->SSA_steps) + { + if (!ssa_step.is_assignment()) continue; + if (!is_heap_region2t(ssa_step.rhs)) continue; + heap_region2t& obj_reg = to_heap_region2t(ssa_step.rhs); + + // Symbols in SSA step are level2 symbol. + // Symbols in symex are level1 symbol. + expr2tc l1_rhs = ssa_step.rhs; + goto_symex.cur_state->level2.get_original_name(l1_rhs); + + if (to_symbol2t(region.start_loc).get_symbol_name() == + to_symbol2t(to_heap_region2t(l1_rhs).start_loc).get_symbol_name()) + { + uint byte_len = to_constant_int2t(region.pt_bytes).value.to_uint64(); + if (!obj_reg.update(byte_len)) continue; + ssa_step.rhs = heap_region2tc(obj_reg); + ssa_step.cond = equality2tc(ssa_step.lhs, ssa_step.rhs); + ssa_step.cond->dump(); + } + } +} + void goto_symext::dereference(expr2tc &expr, dereferencet::modet mode) { symex_dereference_statet symex_dereference_state(*this, *cur_state); diff --git a/src/goto-symex/symex_valid_object.cpp b/src/goto-symex/symex_valid_object.cpp index 5380c80c..2ad65996 100644 --- a/src/goto-symex/symex_valid_object.cpp +++ b/src/goto-symex/symex_valid_object.cpp @@ -29,6 +29,7 @@ void goto_symext::replace_dynamic_allocation(expr2tc &expr) if (is_valid_object2t(expr) || is_deallocated_obj2t(expr)) { + log_status("replace dynamic object : valid object or deallocated object"); expr2tc &obj_ref = (is_valid_object2t(expr)) ? to_valid_object2t(expr).value : to_deallocated_obj2t(expr).value; @@ -66,11 +67,13 @@ void goto_symext::replace_dynamic_allocation(expr2tc &expr) } else if (is_dynamic_size2t(expr)) { + log_status("replace dynamic object : dynamic size"); // default behavior default_replace_dynamic_allocation(expr); } else if (is_invalid_pointer2t(expr)) { + log_status("replace dynamic object : invalid pointer"); // default behavior default_replace_dynamic_allocation(expr); } diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index fd1ed5d4..050bbdcd 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -77,7 +77,7 @@ static const char *expr_names[] = { "points_to", "uplus", "locadd", - "region", + "heap_region", "pointer_with_region", "heap_load", "heap_update", @@ -423,6 +423,31 @@ void with2t::assert_consistency() const assert(type == source_value->type); } +bool heap_region2t::update(uint byte_len) +{ + uint old_bytes = to_constant_int2t(pt_bytes).value.to_uint64(); + uint old_size = to_constant_int2t(size).value.to_uint64(); + + assert(old_bytes * old_size % byte_len == 0); + // TODO: allow to split only one time + if (is_split) { + assert(byte_len == old_bytes); + return false; + } + + uint new_bytes = byte_len; + uint new_size; + if (byte_len != old_bytes) + { + new_size = old_bytes * old_size / byte_len; + is_split = true; + pt_bytes = constant_int2tc(get_uint64_type(), BigInt(new_bytes)); + size = constant_int2tc(get_uint64_type(), BigInt(new_size)); + return true; + } + return false; +} + const expr2tc &object_descriptor2t::get_root_object() const { const expr2tc *tmp = &object; diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 6058a5a2..229bf8e9 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -988,23 +988,33 @@ class heap_region_data : public expr2t const type2tc &t, datatype_ops::expr_ids id, const expr2tc &start_loc, - const expr2tc &size) - : expr2t(t, id), start_loc(start_loc), size(size) + const expr2tc &pt_bytes, + const expr2tc &size, + bool is_split) + : expr2t(t, id), start_loc(start_loc), pt_bytes(pt_bytes), size(size), is_split(is_split) { } heap_region_data(const heap_region_data& ref) = default; expr2tc start_loc; + expr2tc pt_bytes; expr2tc size; + bool is_split; // Type mangling: typedef esbmct::field_traits heap_region_start_loc_field; + typedef esbmct::field_traits + heap_region_pt_bytes_field; typedef esbmct::field_traits heap_region_size_field; + typedef esbmct::field_traits + heap_region_is_split_field; typedef esbmct::expr2t_traits< heap_region_start_loc_field, - heap_region_size_field> traits; + heap_region_pt_bytes_field, + heap_region_size_field, + heap_region_is_split_field> traits; }; class pointer_with_region_data : public expr2t @@ -3333,12 +3343,14 @@ class locadd2t : public locadd_expr_methods class heap_region2t: public heap_region_expr_methods { public: - heap_region2t(const expr2tc &start_loc, const expr2tc &size) - : heap_region_expr_methods(get_intheap_type(), heap_region_id, start_loc, size) + heap_region2t(const expr2tc &start_loc, const expr2tc &pt_bytes, const expr2tc &size, bool is_split) + : heap_region_expr_methods(get_intheap_type(), heap_region_id, start_loc, pt_bytes, size, is_split) { } heap_region2t(const heap_region2t &ref) = default; + bool update(uint byte_len); + static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index ac505bc1..4f01eb8b 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -167,7 +167,7 @@ std::string points_to2t::field_names[esbmct::num_type_fields] = std::string locadd2t::field_names[esbmct::num_type_fields] = {"baseaddr", "added_num", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = -{"start_loc", "size", "", "", ""}; +{"start_loc", "pt_bytes", "size", "is_split", ""}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index c878b3a6..55b94a6a 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -32,7 +32,7 @@ expr_typedefs2(index, index_data); expr_typedefs3(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); -expr_typedefs2(heap_region, heap_region_data); +expr_typedefs4(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index f912aa6e..0abf856d 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -145,6 +145,8 @@ const expr2tc &get_heap_symbol(const expr2tc &object) { void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) { + log_status("deref expr:"); + expr->dump(); if (!has_dereference(expr)) return; @@ -368,6 +370,8 @@ expr2tc dereferencet::dereference_expr_nonscalar( modet mode, const expr2tc &base) { + log_status("deref expr nonscalar"); + expr->dump(); if (is_dereference2t(expr)) { /* The first expression we're called with is index2t, member2t or non-scalar @@ -791,7 +795,9 @@ expr2tc dereferencet::build_reference_to( // type2tc ptr_type = pointer_type2tc(object->type); // expr2tc obj_ptr = typecast2tc(ptr_type, object); - assert(is_pointer_with_region2t(object)); + log_status("befor building pointer guard"); + object->dump(); + pointer_guard = same_object2tc(deref_expr, object); guardt tmp_guard(guard); tmp_guard.add(pointer_guard); @@ -1217,6 +1223,20 @@ void dereferencet::build_reference_slhv( pointer_with_region2t& pwr = to_pointer_with_region2t(value); expr2tc heap = pwr.region; expr2tc loc_ptr = pwr.loc_ptr; + + log_status("adjust heap pt_bytes and size"); + value_setst::valuest points_to_set; + dereference_callback.get_value_set(pwr.region, points_to_set); + for (expr2tc reg : points_to_set) + { + assert(is_object_descriptor2t(reg)); + object_descriptor2t& obj = to_object_descriptor2t(reg); + assert(is_heap_region2t(obj.object));to_heap_region2t(obj.object); + if (to_heap_region2t(obj.object).update(byte_len)) + dereference_callback.update_regions(obj.object); + } + log_status("done"); + value = heap_load2tc(type, heap, loc_ptr, byte_len); } else { log_error("ERROR: currently not support non-scalar type dereference"); diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index c182eb3f..1ee70f42 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -152,6 +152,15 @@ class dereference_callbackt * @return True if variable is alive * */ virtual bool is_live_variable(const expr2tc &sym) = 0; + + /** Update regionss in value set and in eq system + * @param region + */ + virtual void update_regions(const expr2tc &expr) + { + log_error("Do not support"); + abort(); + } }; /** Class containing expression dereference logic. diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index f92bd969..25b6e8f6 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -197,10 +197,13 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::constant_intloc_id: return mk_nil(); case expr2t::heap_region_id: { + log_status("couvert heap region"); assert(args.size() == 2); const heap_region2t& region = to_heap_region2t(expr); + region.dump(); assert(is_constant_int2t(region.size)); const int n = to_constant_int2t(region.size).as_ulong(); + std::vector pt_vec; for (unsigned i = 0; i < n; i++) { smt_astt loc = i == 0 ? args[0] : mk_locadd(args[0], mk_smt_int(BigInt(i))); @@ -264,9 +267,14 @@ z3_slhv_convt::convert_slhv_opts( { const heap_load2t& heap_load = to_heap_load2t(expr); // TODO : fix width - assert(heap_load.byte_len == 4); - // TODO: fix v1 sort - smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + // assert(heap_load.byte_len == 4); + smt_sortt sort; + if (is_pointer_type(heap_load.type)) + sort = mk_intloc_sort(); + else + sort = mk_int_sort(); + + smt_astt v1 = mk_fresh(sort, mk_fresh_name("tmp_val::")); //current heap state assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); return v1; @@ -298,6 +306,8 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::same_object_id: { + // TODO: fix same object + return mk_smt_bool(true); const same_object2t& same = to_same_object2t(expr); assert(is_pointer_with_region2t(same.side_2)); const pointer_with_region2t& pwr = to_pointer_with_region2t(same.side_2); From 51f83b730acc5962b3c84c461c7f35e59a9a504c Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 6 Aug 2024 17:20:58 +0800 Subject: [PATCH 035/126] fix: do not adjust emp --- src/pointer-analysis/dereference.cpp | 7 +++---- src/pointer-analysis/value_set.cpp | 21 +++++---------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 0abf856d..dbb38539 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1203,7 +1203,6 @@ void dereferencet::build_reference_rec( } } - void dereferencet::build_reference_slhv( expr2tc &value, const expr2tc &offset, @@ -1216,6 +1215,7 @@ void dereferencet::build_reference_slhv( log_status("to type: "); type->dump(); assert(is_pointer_with_region2t(value)); + value->dump(); int flags = 0; if(is_scalar_type(type)) { int byte_len = type->get_width()/8; @@ -1224,19 +1224,18 @@ void dereferencet::build_reference_slhv( expr2tc heap = pwr.region; expr2tc loc_ptr = pwr.loc_ptr; - log_status("adjust heap pt_bytes and size"); + // log_status("adjust heap pt_bytes and size"); value_setst::valuest points_to_set; dereference_callback.get_value_set(pwr.region, points_to_set); for (expr2tc reg : points_to_set) { assert(is_object_descriptor2t(reg)); object_descriptor2t& obj = to_object_descriptor2t(reg); + if (is_constant_intheap2t(obj.object)) continue; assert(is_heap_region2t(obj.object));to_heap_region2t(obj.object); if (to_heap_region2t(obj.object).update(byte_len)) dereference_callback.update_regions(obj.object); } - log_status("done"); - value = heap_load2tc(type, heap, loc_ptr, byte_len); } else { log_error("ERROR: currently not support non-scalar type dereference"); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index ca4017cb..fc572f36 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -537,13 +537,11 @@ void value_sett::get_value_set_rec( return; } - // Look up this symbol, with the given suffix to distinguish any arrays or // members we've picked out of it at a higher level. valuest::const_iterator v_it = values.find(sym.get_symbol_name() + suffix); log_status("ssssss symbol lookup name: {}", sym.get_symbol_name() + suffix); - if (sym.rlevel == symbol2t::renaming_level::level1_global) assert(sym.level1_num == 0); assert(sym.rlevel != symbol2t::renaming_level::level2_global); @@ -563,20 +561,12 @@ void value_sett::get_value_set_rec( } } // SLHV: - if(is_pointer_with_region2t(expr)) - { - log_status("get value rec: is pointer with region2t"); - assert(is_intloc_type(expr)); - expr2tc new_loc_object = expr; - insert(dest, new_loc_object, BigInt(0)); - return; - } - // TODO: not used - if (is_heap_region2t(expr)) + if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || + is_pointer_with_region2t(expr) || is_heap_region2t(expr)) { - log_status("get value rec: is heap region"); - expr2tc new_loc_object = expr; - insert(dest, new_loc_object, BigInt(0)); + log_status("get value set rec: SLHV"); + expr2tc new_object = expr; + insert(dest, new_object, BigInt(0)); return; } @@ -1191,7 +1181,6 @@ void value_sett::assign( // basic type object_mapt values_rhs; - log_status("get rhs value set"); get_value_set(rhs, values_rhs); assign_rec(lhs, values_rhs, "", add_to_sets); } From 98667aa3699aa84cc10a0bf2aa28950c5044dd35 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 7 Aug 2024 22:54:40 +0800 Subject: [PATCH 036/126] fix update regions --- src/esbmc/bmc.cpp | 2 +- src/goto-symex/builtin_functions.cpp | 59 ++++---- src/goto-symex/dynamic_allocation.cpp | 8 +- src/goto-symex/goto_symex.h | 3 +- src/goto-symex/symex_assign.cpp | 3 - src/goto-symex/symex_dereference.cpp | 71 ++++----- src/goto-symex/symex_goto.cpp | 2 + src/goto-symex/symex_target_equation.cpp | 1 + src/irep2/irep2_expr.h | 19 ++- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 138 +++++++++++------- src/pointer-analysis/dereference.h | 10 +- src/pointer-analysis/value_set.cpp | 21 ++- src/solvers/smt/smt_memspace.cpp | 6 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 13 +- 16 files changed, 219 insertions(+), 141 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 4106ae86..e4d307bb 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -647,7 +647,7 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); - // show_vcc(*eq); + show_vcc(*eq); // log_status("smt_convt created"); // if (options.get_bool_option("z3-slhv")) { // show_vcc(*eq); diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index b7b99e3b..487a7294 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -293,41 +293,38 @@ expr2tc goto_symext::symex_mem( new_context.add(symbol); assert(is_symbol2t(lhs)); - expr2tc allocated_heap = symbol2tc(get_intheap_type(), symbol.id); - guardt alloc_guard = cur_state->guard; - expr2tc alloc_base_addr = new_lhs; - expr2tc origin_base_addr(alloc_base_addr); - cur_state->rename(alloc_base_addr); + expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); + guardt rhs_guard = cur_state->guard; + + unsigned int &nondet_counter = get_nondet_counter(); + nondet_counter++; + std::string rhs_base_id = + "symex_dynamic::heap_region_base::nondet" + std::to_string(nondet_counter); + expr2tc rhs_base_addr = symbol2tc(get_intloc_type(), rhs_base_id); - expr2tc region = + expr2tc rhs_heap_region_flag = symbol2tc(get_intheap_type(), symbol.id); + expr2tc rhs_region = heap_region2tc( - origin_base_addr, + rhs_heap_region_flag, + rhs_base_addr, region_pt_bytes, region_size, - size != 1 + size != 1 ); log_status("symex assign in symex_mem: allocated_heap = heaplet"); - symex_assign(code_assign2tc(allocated_heap, region)); + symex_assign(code_assign2tc(rhs_heap, rhs_region)); log_status("create valueset base addr symbol and assign"); - expr2tc base_value_symbol = - symbol2tc(get_intloc_type(), to_symbol2t(origin_base_addr).get_symbol_name()); - expr2tc base_pointer_region_object = - pointer_with_region2tc(base_value_symbol, allocated_heap); - symex_assign( - code_assign2tc( - origin_base_addr, - typecast2tc(origin_base_addr->type, base_pointer_region_object) - ) - ); + expr2tc pwr = pointer_with_region2tc(rhs_base_addr, rhs_heap); + symex_assign(code_assign2tc(lhs, pwr)); // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly - expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), alloc_base_addr); + expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), pwr); track_new_pointer(ptr_obj, get_intheap_type(), region_size); dynamic_memory.emplace_back( - allocated_heap, - alloc_guard, + rhs_heap, + rhs_guard, !is_malloc, symbol.name.as_string() ); @@ -466,14 +463,18 @@ void goto_symext::symex_free(const expr2tc &expr) } else { expr2tc freed_pointer; expr2tc freed_heap; - for(auto const& item : internal_deref_items) { - const pointer_with_region2t& pwr = to_pointer_with_region2t(item.object); + for(auto const& item : internal_deref_items) + { + assert(is_heap_region2t(item.object)); + const heap_region2t& heap_region = to_heap_region2t(item.object); if(is_nil_expr(freed_pointer)) { - freed_pointer = pwr.loc_ptr; - freed_heap = pwr.region; + freed_pointer = heap_region.start_loc; + freed_heap = heap_region.flag; } else { - freed_pointer = if2tc(freed_pointer->type, item.guard, pwr.loc_ptr, freed_pointer); - freed_heap = if2tc(get_intheap_type(), item.guard, pwr.region, freed_heap); + freed_pointer = + if2tc(freed_pointer->type, item.guard, heap_region.start_loc, freed_pointer); + freed_heap = + if2tc(get_intheap_type(), item.guard, heap_region.flag, freed_heap); } expr2tc emp_heap = constant_intheap2tc(get_intheap_type(), true); @@ -484,6 +485,8 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); } } + + log_status("xxxxxxx symex free done"); } void goto_symext::symex_printf(const expr2tc &lhs, expr2tc &rhs) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 8ef6f6cd..7e8242eb 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -33,15 +33,15 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { log_status("replace valid_object"); const valid_object2t &obj = to_valid_object2t(expr); - assert(is_pointer_with_region2t(obj.value)); - const pointer_with_region2t& valid_inner = to_pointer_with_region2t(obj.value); + obj.dump(); + assert(is_heap_region2t(obj.value)); + const heap_region2t& valid_inner = to_heap_region2t(obj.value); expr2tc alloc_size_heap_2; log_status("before migrate"); migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap_2); log_status("migrate over"); - expr2tc heap_contains = heap_contains2tc(alloc_size_heap_2, valid_inner.loc_ptr, 1); + expr2tc heap_contains = heap_contains2tc(alloc_size_heap_2, valid_inner.start_loc, 1); expr = heap_contains; - } } else if (is_invalid_pointer2t(expr)) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 9712a08c..53d57654 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -964,7 +964,8 @@ class symex_dereference_statet : public dereference_callbackt dump_internal_state(const std::list &data) override; bool is_live_variable(const expr2tc &sym) override; - void update_regions(const expr2tc &expr) override; + void update_regions(const expr2tc ®ion) override; + void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) override; }; #endif diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 53f793ad..8ebfae0b 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -187,9 +187,6 @@ void goto_symext::symex_assign( replace_nondet(lhs); replace_nondet(rhs); - lhs->dump(); - rhs->dump(); - intrinsic_races_check_dereference(lhs); log_status("dereference lhs write"); dereference(lhs, dereferencet::WRITE); diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 743f7773..e5e1eab7 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -166,30 +166,15 @@ bool symex_dereference_statet::is_live_variable(const expr2tc &symbol) return false; } -void symex_dereference_statet::update_regions(const expr2tc &expr) +void symex_dereference_statet::update_regions(const expr2tc ®ion) { - assert(is_heap_region2t(expr)); - const heap_region2t& region = to_heap_region2t(expr); + assert(is_heap_region2t(region)); // update value set - // log_status("update value set"); value_sett& value_set = goto_symex.cur_state->value_set; - for (auto& value : value_set.values) - { - for (auto& obj : value.second.object_map) - { - if (!is_heap_region2t(value_set.object_numbering[obj.first])) continue; - heap_region2t& obj_reg = - to_heap_region2t(value_set.object_numbering[obj.first]); - // obj_reg.dump(); - if (to_symbol2t(region.start_loc).get_symbol_name() == - to_symbol2t(obj_reg.start_loc).get_symbol_name()) - { - // log_status("found region to be updated"); - value_set.object_numbering[obj.first] = expr; - } - } - } + unsigned int n = value_set.object_numbering.size(); + for(unsigned int i = 0; i < n; i++) + update_heap_region_rec(value_set.object_numbering[i], region); // update eq system log_status("update eq system"); @@ -197,25 +182,43 @@ void symex_dereference_statet::update_regions(const expr2tc &expr) std::dynamic_pointer_cast(goto_symex.target); for(auto& ssa_step : eq->SSA_steps) { - if (!ssa_step.is_assignment()) continue; - if (!is_heap_region2t(ssa_step.rhs)) continue; - heap_region2t& obj_reg = to_heap_region2t(ssa_step.rhs); + update_heap_region_rec(ssa_step.guard, region); + update_heap_region_rec(ssa_step.rhs, region); + update_heap_region_rec(ssa_step.cond, region); + } +} - // Symbols in SSA step are level2 symbol. - // Symbols in symex are level1 symbol. - expr2tc l1_rhs = ssa_step.rhs; - goto_symex.cur_state->level2.get_original_name(l1_rhs); +void symex_dereference_statet::update_heap_region_rec( + expr2tc &expr, + const expr2tc ®ion) +{ + if (is_nil_expr(expr)) return; + + if (is_heap_region2t(expr)) + { + uint byte_len = + to_constant_int2t( + to_heap_region2t(region).pt_bytes) + .value.to_uint64(); + + expr2tc old_reg = expr; + goto_symex.cur_state->level2.get_original_name(old_reg); - if (to_symbol2t(region.start_loc).get_symbol_name() == - to_symbol2t(to_heap_region2t(l1_rhs).start_loc).get_symbol_name()) + if (to_symbol2t(to_heap_region2t(region).start_loc).get_symbol_name() == + to_symbol2t(to_heap_region2t(old_reg).start_loc).get_symbol_name()) { - uint byte_len = to_constant_int2t(region.pt_bytes).value.to_uint64(); - if (!obj_reg.update(byte_len)) continue; - ssa_step.rhs = heap_region2tc(obj_reg); - ssa_step.cond = equality2tc(ssa_step.lhs, ssa_step.rhs); - ssa_step.cond->dump(); + heap_region2t& reg = to_heap_region2t(expr); + reg.update(byte_len); + expr = heap_region2tc(reg); } } + else + { + expr->Foreach_operand([this, ®ion](expr2tc& e){ + if (!is_nil_expr(e)) + update_heap_region_rec(e, region); + }); + } } void goto_symext::dereference(expr2tc &expr, dereferencet::modet mode) diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp index 24f98d82..da9fa26e 100644 --- a/src/goto-symex/symex_goto.cpp +++ b/src/goto-symex/symex_goto.cpp @@ -20,6 +20,8 @@ void goto_symext::symex_goto(const expr2tc &old_guard) cur_state->rename(new_guard); do_simplify(new_guard); + new_guard->dump(); + bool new_guard_false = (is_false(new_guard) || cur_state->guard.is_false()); bool new_guard_true = is_true(new_guard); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 8b1c3429..f396262d 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -140,6 +140,7 @@ void symex_target_equationt::convert(smt_convt &smt_conv) log_status("============= begin converting ssa steps"); for (auto &SSA_step : SSA_steps) convert_internal_step(smt_conv, assumpt_ast, assertions, SSA_step); + log_status("convert internal step done"); if (!assertions.empty()) smt_conv.assert_ast(smt_conv.make_n_ary_or(assertions)); diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 229bf8e9..4ecdd2e0 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -987,21 +987,26 @@ class heap_region_data : public expr2t heap_region_data( const type2tc &t, datatype_ops::expr_ids id, + const expr2tc &flag, const expr2tc &start_loc, const expr2tc &pt_bytes, const expr2tc &size, bool is_split) - : expr2t(t, id), start_loc(start_loc), pt_bytes(pt_bytes), size(size), is_split(is_split) + : expr2t(t, id), flag(flag), + start_loc(start_loc), pt_bytes(pt_bytes), size(size), is_split(is_split) { } heap_region_data(const heap_region_data& ref) = default; + expr2tc flag; expr2tc start_loc; expr2tc pt_bytes; expr2tc size; bool is_split; // Type mangling: + typedef esbmct::field_traits + heap_region_flag_field; typedef esbmct::field_traits heap_region_start_loc_field; typedef esbmct::field_traits @@ -1011,6 +1016,7 @@ class heap_region_data : public expr2t typedef esbmct::field_traits heap_region_is_split_field; typedef esbmct::expr2t_traits< + heap_region_flag_field, heap_region_start_loc_field, heap_region_pt_bytes_field, heap_region_size_field, @@ -3343,8 +3349,15 @@ class locadd2t : public locadd_expr_methods class heap_region2t: public heap_region_expr_methods { public: - heap_region2t(const expr2tc &start_loc, const expr2tc &pt_bytes, const expr2tc &size, bool is_split) - : heap_region_expr_methods(get_intheap_type(), heap_region_id, start_loc, pt_bytes, size, is_split) + heap_region2t( + const expr2tc &flag, + const expr2tc &start_loc, + const expr2tc &pt_bytes, + const expr2tc &size, + bool is_split) + : heap_region_expr_methods( + get_intheap_type(), heap_region_id, + flag, start_loc, pt_bytes, size, is_split) { } heap_region2t(const heap_region2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 4f01eb8b..af002605 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -167,7 +167,7 @@ std::string points_to2t::field_names[esbmct::num_type_fields] = std::string locadd2t::field_names[esbmct::num_type_fields] = {"baseaddr", "added_num", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = -{"start_loc", "pt_bytes", "size", "is_split", ""}; +{"flag", "start_loc", "pt_bytes", "size", "is_split"}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 55b94a6a..d568bb37 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -32,7 +32,7 @@ expr_typedefs2(index, index_data); expr_typedefs3(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); -expr_typedefs4(heap_region, heap_region_data); +expr_typedefs5(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index dbb38539..bd1b2118 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -161,7 +161,6 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) case expr2t::address_of_id: dereference_addrof_expr(expr, guard, mode); break; - case expr2t::dereference_id: { log_status("dereference expr: dereference id"); @@ -291,6 +290,8 @@ void dereferencet::dereference_addrof_expr( // this has *no* side effect! address_of2t &addrof = to_address_of2t(expr); + if (is_heap_region2t(addrof.ptr_obj)) return; + if (is_dereference2t(addrof.ptr_obj)) { dereference2t &deref = to_dereference2t(addrof.ptr_obj); @@ -464,6 +465,9 @@ expr2tc dereferencet::dereference( modet mode, const expr2tc &lexical_offset) { + log_status("dereferencing pointer ---------"); + orig_src->dump(); + internal_items.clear(); // Awkwardly, the pointer might not be of pointer type, for example with @@ -472,7 +476,7 @@ expr2tc dereferencet::dereference( // cope with the fact that this expression doesn't point at anything. Of // course, if it does point at something, dereferencing continues. expr2tc src = orig_src; - if (!is_pointer_type(orig_src)) + if (!is_pointer_type(orig_src) && !is_intloc_type(orig_src)) src = typecast2tc(pointer_type2tc(get_empty_type()), src); type2tc type = ns.follow(to_type); @@ -482,9 +486,9 @@ expr2tc dereferencet::dereference( // collect objects dest may point to value_setst::valuest points_to_set; - dereference_callback.get_value_set(src, points_to_set); log_status("---- value set for "); src->dump(); + dereference_callback.get_value_set(src, points_to_set); log_status("---- value set: {} items", points_to_set.size()); for(expr2tc e : points_to_set) { e->dump(); @@ -797,6 +801,7 @@ expr2tc dereferencet::build_reference_to( log_status("befor building pointer guard"); object->dump(); + deref_expr->dump(); pointer_guard = same_object2tc(deref_expr, object); guardt tmp_guard(guard); @@ -806,6 +811,8 @@ expr2tc dereferencet::build_reference_to( // mode. valid_check(object, tmp_guard, mode); + log_status("finish checking"); + // Don't do anything further if we're freeing things if (is_free(mode)) return expr2tc(); @@ -882,9 +889,9 @@ expr2tc dereferencet::build_reference_to( { bounds_check(value, final_offset, type, tmp_guard); } - else if (is_pointer_with_region2t(value)) + else if (is_heap_region2t(value)) { - check_pointer_with_region_access(value, final_offset, type, tmp_guard, mode); + check_heap_region_access(value, final_offset, type, tmp_guard, mode); } else { @@ -1209,34 +1216,39 @@ void dereferencet::build_reference_slhv( const type2tc &type, const guardt &guard, modet mode, - unsigned long alignment -) { + unsigned long alignment) +{ log_status("build reference slhv"); - log_status("to type: "); - type->dump(); - assert(is_pointer_with_region2t(value)); - value->dump(); - int flags = 0; + assert(is_heap_region2t(value)); if(is_scalar_type(type)) { - int byte_len = type->get_width()/8; - assert(byte_len > 0); - pointer_with_region2t& pwr = to_pointer_with_region2t(value); - expr2tc heap = pwr.region; - expr2tc loc_ptr = pwr.loc_ptr; - - // log_status("adjust heap pt_bytes and size"); - value_setst::valuest points_to_set; - dereference_callback.get_value_set(pwr.region, points_to_set); - for (expr2tc reg : points_to_set) - { - assert(is_object_descriptor2t(reg)); - object_descriptor2t& obj = to_object_descriptor2t(reg); - if (is_constant_intheap2t(obj.object)) continue; - assert(is_heap_region2t(obj.object));to_heap_region2t(obj.object); - if (to_heap_region2t(obj.object).update(byte_len)) - dereference_callback.update_regions(obj.object); + if (!is_constant_int2t(offset)) offset.simplify(); + assert(is_constant_int2t(offset)); + int offset_bytes = to_constant_int2t(offset).value.to_uint64(); + + heap_region2t& heap_region = to_heap_region2t(value); + expr2tc heap = heap_region.flag; + + int access_sz = type->get_width() / 8; + assert(access_sz > 0); + // Update its pt bytes + if (heap_region.update(access_sz)) + dereference_callback.update_regions(value); + + expr2tc access_ptr; + if (offset_bytes == 0) + access_ptr = heap_region.start_loc; + else + { + int offset_pt = offset_bytes / 8; + assert(offset_pt % access_sz == 0); + offset_pt /= access_sz; + access_ptr = locadd2tc( + heap_region.start_loc, + gen_long(get_int64_type(), offset_pt) + ); } - value = heap_load2tc(type, heap, loc_ptr, byte_len); + + value = heap_load2tc(type, heap, access_ptr, access_sz); } else { log_error("ERROR: currently not support non-scalar type dereference"); abort(); @@ -2300,16 +2312,14 @@ void dereferencet::valid_check( return; } } - } else if(is_pointer_with_region2t(symbol)) { - // slhv - log_status("pointer with region dereference failure here"); - // assert that the pointer we dereference with a specific length lies in the heap variable - // TODO: maybe add a special expression type to denote that the pointer_with_region is not valid - expr2tc not_valid_pointer_with_region = not2tc(valid_object2tc(symbol)); + } + else if(is_heap_region2t(symbol)) + { + expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); log_status("not valid print:"); - not_valid_pointer_with_region->dump(); + not_valid_heap_region->dump(); guardt tmp_guard(guard); - tmp_guard.add(not_valid_pointer_with_region); + tmp_guard.add(not_valid_heap_region); std::string foo = is_free(mode) ? "invalid free pointer" : "invalid dereference pointer"; dereference_failure("pointer dereference", foo, tmp_guard); @@ -2580,26 +2590,46 @@ void dereferencet::check_data_obj_access( log_status("check data obj access over"); } -void dereferencet::check_pointer_with_region_access( +void dereferencet::check_heap_region_access( const expr2tc &value, const expr2tc &offset, const type2tc &type, const guardt &guard, - modet mode) { - log_status("check pointer with region access"); - assert(is_pointer_with_region2t(value)); - const pointer_with_region2t& pointer_reg = to_pointer_with_region2t(value); - expr2tc region = pointer_reg.region; - expr2tc pointer_loc = pointer_reg.loc_ptr; - unsigned int byte_len = type->get_width()/8; - expr2tc bound_check = heap_contains2tc(region, pointer_loc, byte_len); - if(!options.get_bool_option("no-bounds-check")) { - guardt tmp_guard = guard; - tmp_guard.add(bound_check); - dereference_failure("pointer dereference", "Access of heap out of region", tmp_guard); - } - // TODO: maybe add alignment check - log_status("check pointer with region access over"); + modet mode) +{ + // This check is in byte-level; + log_status("check heap region access"); + assert(is_heap_region2t(value)); + const heap_region2t& heap_region = to_heap_region2t(value); + unsigned int total_bytes = + to_constant_int2t(heap_region.pt_bytes).value.to_uint64() * + to_constant_int2t(heap_region.size).value.to_uint64(); + BigInt data_sz(total_bytes); + BigInt access_sz(type->get_width() / 8); + + // offset / 8 + if (!is_constant_int2t(offset)) offset.simplify(); + assert(is_constant_int2t(offset)); + BigInt offset_sz(to_constant_int2t(offset).value.to_int64() / 8); + + expr2tc data_sz_e = gen_long(offset->type, data_sz); + expr2tc access_sz_e = gen_long(offset->type, access_sz); + expr2tc offset_in_byte = gen_long(offset->type, offset_sz); + + expr2tc add = add2tc(access_sz_e->type, offset_in_byte, access_sz_e); + expr2tc gt = greaterthan2tc(add, data_sz_e); + expr2tc bound_check = gt; + if(!options.get_bool_option("no-bounds-check")) + { + guardt tmp_guard = guard; + tmp_guard.add(bound_check); + dereference_failure( + "pointer dereference", + "Access of heap out of region", + tmp_guard + ); + } + // TODO: maybe add alignment check } void dereferencet::check_alignment( diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 1ee70f42..6ff5dfd1 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -156,7 +156,13 @@ class dereference_callbackt /** Update regionss in value set and in eq system * @param region */ - virtual void update_regions(const expr2tc &expr) + virtual void update_regions(const expr2tc ®ion) + { + log_error("Do not support"); + abort(); + } + + virtual void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) { log_error("Do not support"); abort(); @@ -447,7 +453,7 @@ class dereferencet const type2tc &type, const guardt &guard, modet mode); - void check_pointer_with_region_access( + void check_heap_region_access( const expr2tc &value, const expr2tc &offset, const type2tc &type, diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index fc572f36..cd72f62c 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -562,7 +562,7 @@ void value_sett::get_value_set_rec( } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || - is_pointer_with_region2t(expr) || is_heap_region2t(expr)) + is_heap_region2t(expr)) { log_status("get value set rec: SLHV"); expr2tc new_object = expr; @@ -570,6 +570,17 @@ void value_sett::get_value_set_rec( return; } + if (is_pointer_with_region2t(expr)) + { + get_value_set_rec( + to_pointer_with_region2t(expr).region, + dest, + suffix, + original_type + ); + return; + } + if (is_add2t(expr) || is_sub2t(expr)) { // Consider pointer arithmetic. This takes takes the form of finding the @@ -804,7 +815,8 @@ void value_sett::get_reference_set_rec(const expr2tc &expr, object_mapt &dest) { if ( is_symbol2t(expr) || is_dynamic_object2t(expr) || - is_constant_string2t(expr) || is_constant_array2t(expr)) + is_constant_string2t(expr) || is_constant_array2t(expr) + || is_heap_region2t(expr)) { // Any symbol we refer to, store into the destination object map. // Given that this is a simple symbol, we can be sure that the offset to @@ -1182,6 +1194,11 @@ void value_sett::assign( // basic type object_mapt values_rhs; get_value_set(rhs, values_rhs); + log_status("get values rhs"); + for(auto& p : values_rhs) + { + object_numbering[p.first]->dump(); + } assign_rec(lhs, values_rhs, "", add_to_sets); } diff --git a/src/solvers/smt/smt_memspace.cpp b/src/solvers/smt/smt_memspace.cpp index 9e4f64de..d34459f7 100644 --- a/src/solvers/smt/smt_memspace.cpp +++ b/src/solvers/smt/smt_memspace.cpp @@ -539,6 +539,12 @@ smt_astt smt_convt::convert_addr_of(const expr2tc &expr) return convert_ast(tmp); } + if (is_heap_region2t(obj.ptr_obj)) + { + convert_ast(obj.ptr_obj); + return convert_ast(to_heap_region2t(obj.ptr_obj).start_loc); + } + log_error("Unrecognized address_of operand:\n{}", *expr); abort(); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 25b6e8f6..0385547a 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -197,8 +197,8 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::constant_intloc_id: return mk_nil(); case expr2t::heap_region_id: { - log_status("couvert heap region"); - assert(args.size() == 2); + log_status("convert heap region"); + assert(args.size() == 4); const heap_region2t& region = to_heap_region2t(expr); region.dump(); assert(is_constant_int2t(region.size)); @@ -206,7 +206,7 @@ z3_slhv_convt::convert_slhv_opts( std::vector pt_vec; for (unsigned i = 0; i < n; i++) { - smt_astt loc = i == 0 ? args[0] : mk_locadd(args[0], mk_smt_int(BigInt(i))); + smt_astt loc = i == 0 ? args[1] : mk_locadd(args[1], mk_smt_int(BigInt(i))); smt_astt v = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); pt_vec.push_back(mk_pt(loc, v)); } @@ -234,6 +234,7 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::locadd_id: { assert(args.size() == 2); + log_status("here"); return mk_locadd(args[0], args[1]); } case expr2t::heap_append_id: @@ -307,11 +308,9 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::same_object_id: { // TODO: fix same object - return mk_smt_bool(true); const same_object2t& same = to_same_object2t(expr); - assert(is_pointer_with_region2t(same.side_2)); - const pointer_with_region2t& pwr = to_pointer_with_region2t(same.side_2); - const heap_region2t& heap_region = to_heap_region2t(pwr.region); + assert(is_heap_region2t(same.side_2)); + const heap_region2t& heap_region = to_heap_region2t(same.side_2); assert(is_constant_int2t(heap_region.size)); smt_astt start_loc = convert_ast(heap_region.start_loc); smt_astt size = convert_ast(heap_region.size); From 1b2fe4de7a071351c0f6aa3590800915ae6d2e67 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 8 Aug 2024 12:53:15 +0800 Subject: [PATCH 037/126] replace heap load with its flag --- src/goto-symex/builtin_functions.cpp | 14 +--- src/goto-symex/execution_state.h | 5 +- src/goto-symex/goto_symex.h | 16 ++-- src/goto-symex/slice.cpp | 11 ++- src/goto-symex/symex_assign.cpp | 77 +++++++++---------- src/goto-symex/symex_dereference.cpp | 5 ++ src/irep2/irep2_expr.h | 39 +++++++--- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 7 +- src/pointer-analysis/dereference.h | 6 ++ src/pointer-analysis/value_set.cpp | 24 +++++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 41 +++++----- src/util/migrate.cpp | 5 +- 14 files changed, 152 insertions(+), 102 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 487a7294..e19123db 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -114,14 +114,7 @@ expr2tc goto_symext::symex_mem( lhs->dump(); code.dump(); - expr2tc new_lhs = lhs; - if (is_heap_load2t(lhs)) - { - assert(is_pointer_type(new_lhs->type)); - replace_heap_load(new_lhs); - } - - if (is_nil_expr(new_lhs)) + if (is_nil_expr(lhs)) return expr2tc(); // ignore // size @@ -296,10 +289,7 @@ expr2tc goto_symext::symex_mem( expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); guardt rhs_guard = cur_state->guard; - unsigned int &nondet_counter = get_nondet_counter(); - nondet_counter++; - std::string rhs_base_id = - "symex_dynamic::heap_region_base::nondet" + std::to_string(nondet_counter); + std::string rhs_base_id = to_symbol2t(lhs).get_symbol_name(); expr2tc rhs_base_addr = symbol2tc(get_intloc_type(), rhs_base_id); expr2tc rhs_heap_region_flag = symbol2tc(get_intheap_type(), symbol.id); diff --git a/src/goto-symex/execution_state.h b/src/goto-symex/execution_state.h index 1e6d8815..3e5bd7ad 100644 --- a/src/goto-symex/execution_state.h +++ b/src/goto-symex/execution_state.h @@ -207,7 +207,10 @@ class execution_statet : public goto_symext * @param guard A guard for the assignment, true by default * @param type Assignment type, visible by default */ - void symex_assign(const expr2tc &code, const bool hidden, const guardt &guard) + void symex_assign( + const expr2tc &code, + const bool hidden, + const guardt &guard) override; /** diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 53d57654..b69eb465 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -546,6 +546,7 @@ class goto_symext * @param type Assignment type, visible by default * @param kind The step kind, by default is plain BMC * @param guard A guard for the assignment, true by default + * @param is_replace_heap_load Replace heap_load by its flag */ virtual void symex_assign( const expr2tc &code, @@ -757,13 +758,13 @@ class goto_symext * @param rhs Value to assign to lhs * @param guard Assignment guard. */ - void symex_assign_heap_laod( - const expr2tc &lhs, - const expr2tc &full_lhs, - expr2tc &rhs, - expr2tc &full_rhs, - guardt &guard, - const bool hidden); + // void symex_assign_heap_laod( + // const expr2tc &lhs, + // const expr2tc &full_lhs, + // expr2tc &rhs, + // expr2tc &full_rhs, + // guardt &guard, + // const bool hidden); /** Symbolic implementation of malloc. */ expr2tc symex_malloc(const expr2tc &lhs, const sideeffect2t &code); @@ -966,6 +967,7 @@ class symex_dereference_statet : public dereference_callbackt void update_regions(const expr2tc ®ion) override; void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) override; + unsigned int get_new_nondet_id() override; }; #endif diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 0ec551ef..b5209830 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,9 +11,16 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - if (is_pointer_with_region2t(expr)) { + if (is_pointer_with_region2t(expr)) + { return get_symbols(to_pointer_with_region2t(expr).loc_ptr); - } else { + } + else if (is_heap_load2t(expr)) + { + return get_symbols(to_heap_load2t(expr).flag); + } + else + { // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { if (!is_nil_expr(e)) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 8ebfae0b..ae3a5c49 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -198,6 +198,10 @@ void goto_symext::symex_assign( replace_dynamic_allocation(rhs); log_status("replace done"); + log_status("replace heap_load"); + replace_heap_load(lhs); + replace_heap_load(rhs); + // printf expression that has lhs if (is_code_printf2t(rhs)) { @@ -327,7 +331,7 @@ void goto_symext::symex_assign_rec( else if (is_heap_load2t(lhs)) { log_status("symex_assign_heap_load"); - symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); + // symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_heap_region2t(lhs)) { @@ -867,28 +871,28 @@ void goto_symext::symex_assign_bitfield( return symex_assign_rec(val, full_lhs, new_rhs, full_rhs, guard, hidden); } -void goto_symext::symex_assign_heap_laod( - const expr2tc &lhs, - const expr2tc &full_lhs, - expr2tc &rhs, - expr2tc &full_rhs, - guardt &guard, - const bool hidden) -{ - assert(is_scalar_type(rhs)); +// void goto_symext::symex_assign_heap_laod( +// const expr2tc &lhs, +// const expr2tc &full_lhs, +// expr2tc &rhs, +// expr2tc &full_rhs, +// guardt &guard, +// const bool hidden) +// { +// assert(is_scalar_type(rhs)); - const heap_load2t& heap_load = to_heap_load2t(lhs); - assert(heap_load.byte_len * 8 == rhs->type->get_width()); +// const heap_load2t& heap_load = to_heap_load2t(lhs); +// assert(heap_load.byte_len * 8 == rhs->type->get_width()); - // Pin one set of rhs version numbers: if we assign part of a value to itself, - // it'll change during the assignment - cur_state->rename(rhs); // shall we? +// // Pin one set of rhs version numbers: if we assign part of a value to itself, +// // it'll change during the assignment +// cur_state->rename(rhs); // shall we? - expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_addr); - expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); +// expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_loc); +// expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); - symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); -} +// symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); +// } void goto_symext::replace_nondet(expr2tc &expr) { @@ -911,24 +915,19 @@ void goto_symext::replace_nondet(expr2tc &expr) void goto_symext::replace_heap_load(expr2tc &expr) { - heap_load2t& heap_load = to_heap_load2t(expr); - - unsigned int &nondet_counter = get_nondet_counter(); - nondet_counter++; - - symbolt symbol; - symbol.name = "nondet_loc_"+ i2string(nondet_counter); - - symbol.id = std::string("symex_dynamic::") + id2string(symbol.name); - symbol.lvalue = true; - symbol.type = typet(typet::t_intloc); - // symbol.type.dynamic(true); - symbol.mode = "C"; - new_context.add(symbol); - - expr2tc ptr = symbol2tc(get_intloc_type(), symbol.name); - - symex_assign(code_assign2tc(ptr, expr)); - - expr = ptr; + if (is_heap_load2t(expr)) + { + heap_load2t& heap_load = to_heap_load2t(expr); + // symex_assign(code_assign2tc(heap_load.flag, expr), false, guardt(), false); + guardt g; + symex_assign_rec(heap_load.flag, heap_load.flag, expr, expr, g, false); + expr = heap_load.flag; + } + else + { + expr->Foreach_operand([this](expr2tc &e) { + if (!is_nil_expr(e)) + replace_heap_load(e); + }); + } } \ No newline at end of file diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index e5e1eab7..267921b7 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -221,6 +221,11 @@ void symex_dereference_statet::update_heap_region_rec( } } +unsigned int symex_dereference_statet::get_new_nondet_id() +{ + return ++goto_symex.get_nondet_counter(); +} + void goto_symext::dereference(expr2tc &expr, dereferencet::modet mode) { symex_dereference_statet symex_dereference_state(*this, *cur_state); diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 4ecdd2e0..d4eadd0e 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1066,22 +1066,32 @@ class heap_load_data : public expr2t { heap_load_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc h, - expr2tc start_addr, + const expr2tc &flag, + const expr2tc &heap, + const expr2tc &start_loc, unsigned int byte_len) - : expr2t(t, id), heap(h), start_addr(start_addr), byte_len(byte_len) + : expr2t(t, id), flag(flag), heap(heap), start_loc(start_loc), byte_len(byte_len) { } + expr2tc flag; expr2tc heap; - expr2tc start_addr; + expr2tc start_loc; unsigned int byte_len; - - typedef esbmct::field_traits heap_load_data_heap_field; - typedef esbmct::field_traits heap_load_data_start_addr_field; - typedef esbmct::field_traits heap_load_data_byte_len_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + heap_load_data_flag_field; + typedef esbmct::field_traits + heap_load_data_heap_field; + typedef esbmct::field_traits + heap_load_data_start_loc_field; + typedef esbmct::field_traits + heap_load_data_byte_len_field; + typedef esbmct::expr2t_traits< + heap_load_data_flag_field, + heap_load_data_heap_field, + heap_load_data_start_loc_field, + heap_load_data_byte_len_field> traits; }; @@ -3381,8 +3391,15 @@ class pointer_with_region2t : public pointer_with_region_expr_methods class heap_load2t : public heap_load_expr_methods { public: - heap_load2t(const type2tc & type, expr2tc heap, expr2tc start_addr, unsigned int byte_len) - : heap_load_expr_methods(type, expr2t::heap_load_id, heap, start_addr, byte_len) + heap_load2t( + const type2tc &type, + const expr2tc &flag, + const expr2tc &heap, + const expr2tc &start_loc, + unsigned int byte_len) + : heap_load_expr_methods( + type, expr2t::heap_load_id, + flag, heap, start_loc, byte_len) { } heap_load2t(const heap_load2t& ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index af002605..648689e6 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -171,7 +171,7 @@ std::string heap_region2t::field_names[esbmct::num_type_fields] = std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = -{"src_heap", "start_addr", "byte_len", "", ""}; +{"flag", "src_heap", "start_loc", "byte_len", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "updated_val", "byte_len", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index d568bb37..5cf58bc5 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -34,7 +34,7 @@ expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); expr_typedefs5(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); -expr_typedefs4(heap_load, heap_load_data); +expr_typedefs5(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs4(heap_append, heap_append_data); expr_typedefs3(heap_delete, heap_delete_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index bd1b2118..63028f0b 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1247,8 +1247,13 @@ void dereferencet::build_reference_slhv( gen_long(get_int64_type(), offset_pt) ); } + + std::string flag_id = std::string("symex_dynamic::nondet_") + + ((is_pointer_type(type) || is_intloc_type(type)) ? "loc_" : "val_") + + i2string(dereference_callback.get_new_nondet_id()); + expr2tc flag = symbol2tc(type, flag_id); - value = heap_load2tc(type, heap, access_ptr, access_sz); + value = heap_load2tc(type, flag, heap, access_ptr, access_sz); } else { log_error("ERROR: currently not support non-scalar type dereference"); abort(); diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 6ff5dfd1..0c5cb340 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -167,6 +167,12 @@ class dereference_callbackt log_error("Do not support"); abort(); } + + virtual unsigned int get_new_nondet_id() + { + log_error("Do not support"); + abort(); + } }; /** Class containing expression dereference logic. diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index cd72f62c..ec85ad51 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -214,6 +214,7 @@ void value_sett::get_value_set_rec( { log_status("get value set rec for: "); expr->dump(); + if (is_unknown2t(expr) || is_invalid2t(expr)) { log_status("is unknown expr or invalid expr"); @@ -562,7 +563,7 @@ void value_sett::get_value_set_rec( } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || - is_heap_region2t(expr)) + is_heap_region2t(expr) || is_heap_update2t(expr) || is_heap_append2t(expr)) { log_status("get value set rec: SLHV"); expr2tc new_object = expr; @@ -570,13 +571,28 @@ void value_sett::get_value_set_rec( return; } + if (is_locadd2t(expr)) + { + const locadd2t& locadd = to_locadd2t(expr); + assert(is_intloc_type(locadd.base_addr)); + abort(); + // TODO + } + if (is_pointer_with_region2t(expr)) { get_value_set_rec( to_pointer_with_region2t(expr).region, - dest, - suffix, - original_type + dest, suffix, original_type + ); + return; + } + + if (is_heap_load2t(expr)) + { + get_value_set_rec( + to_heap_load2t(expr).flag, + dest, suffix, original_type ); return; } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 0385547a..c8f88f84 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -269,16 +269,9 @@ z3_slhv_convt::convert_slhv_opts( const heap_load2t& heap_load = to_heap_load2t(expr); // TODO : fix width // assert(heap_load.byte_len == 4); - smt_sortt sort; - if (is_pointer_type(heap_load.type)) - sort = mk_intloc_sort(); - else - sort = mk_int_sort(); - - smt_astt v1 = mk_fresh(sort, mk_fresh_name("tmp_val::")); //current heap state - assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); - return v1; + assert_ast(mk_subh(mk_pt(args[2], args[0]), args[1])); + return args[0]; } case expr2t::heap_contains_id: { @@ -309,20 +302,24 @@ z3_slhv_convt::convert_slhv_opts( { // TODO: fix same object const same_object2t& same = to_same_object2t(expr); - assert(is_heap_region2t(same.side_2)); - const heap_region2t& heap_region = to_heap_region2t(same.side_2); - assert(is_constant_int2t(heap_region.size)); - smt_astt start_loc = convert_ast(heap_region.start_loc); - smt_astt size = convert_ast(heap_region.size); - smt_astt nondet_offset = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - return - mk_and( - mk_eq(args[0], mk_locadd(start_loc, nondet_offset)), + if (is_heap_region2t(same.side_2)) + { + const heap_region2t& heap_region = to_heap_region2t(same.side_2); + assert(is_constant_int2t(heap_region.size)); + smt_astt start_loc = convert_ast(heap_region.start_loc); + smt_astt size = convert_ast(heap_region.size); + smt_astt nondet_offset = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + return mk_and( - mk_le(mk_smt_int(BigInt(0)), nondet_offset), - mk_lt(nondet_offset, size) - ) - ); + mk_eq(args[0], mk_locadd(start_loc, nondet_offset)), + mk_and( + mk_le(mk_smt_int(BigInt(0)), nondet_offset), + mk_lt(nondet_offset, size) + ) + ); + } + else if (is_heap_load2t(same.side_2)) + return mk_eq(args[0], args[1]); } default: { log_status("Invalid SLHV operations!!!"); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 5b220590..67d2ed77 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2632,7 +2632,9 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_region2t &ref2 = to_heap_region2t(ref); typet thetype = migrate_type_back(ref->type); exprt region("heap_region", thetype); + region.copy_to_operands(migrate_expr_back(ref2.flag)); region.copy_to_operands(migrate_expr_back(ref2.start_loc)); + region.copy_to_operands(migrate_expr_back(ref2.pt_bytes)); region.copy_to_operands(migrate_expr_back(ref2.size)); return region; } @@ -2650,8 +2652,9 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_load2t& ref2 = to_heap_load2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_load("heap_load", thetype); + heap_load.copy_to_operands(migrate_expr_back(ref2.flag)); heap_load.copy_to_operands(migrate_expr_back(ref2.heap)); - heap_load.copy_to_operands(migrate_expr_back(ref2.start_addr)); + heap_load.copy_to_operands(migrate_expr_back(ref2.start_loc)); heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_load; } From 20b5a70f5373bff57ec1928e4a0786f8a8037030 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 8 Aug 2024 16:01:18 +0800 Subject: [PATCH 038/126] fix: flag of heap_load should be connected --- src/goto-symex/builtin_functions.cpp | 119 +++++++++++++++++---------- src/goto-symex/goto_symex.h | 23 ++---- src/goto-symex/slice.cpp | 8 +- src/goto-symex/symex_assign.cpp | 68 ++++++--------- src/goto-symex/symex_dereference.cpp | 19 ++++- src/pointer-analysis/dereference.cpp | 6 +- src/pointer-analysis/dereference.h | 2 +- 7 files changed, 133 insertions(+), 112 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index e19123db..ca4dddcd 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -285,11 +285,21 @@ expr2tc goto_symext::symex_mem( log_status("new_context.add(symbol);"); new_context.add(symbol); - assert(is_symbol2t(lhs)); + expr2tc lhs_flag; + if (is_symbol2t(lhs)) + lhs_flag = lhs; + else if (is_heap_load2t(lhs)) + lhs_flag = to_heap_load2t(lhs).flag; + else + { + log_error("Do not support this expr"); + abort(); + } + expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); guardt rhs_guard = cur_state->guard; - std::string rhs_base_id = to_symbol2t(lhs).get_symbol_name(); + std::string rhs_base_id = to_symbol2t(lhs_flag).get_symbol_name(); expr2tc rhs_base_addr = symbol2tc(get_intloc_type(), rhs_base_id); expr2tc rhs_heap_region_flag = symbol2tc(get_intheap_type(), symbol.id); @@ -307,10 +317,11 @@ expr2tc goto_symext::symex_mem( log_status("create valueset base addr symbol and assign"); expr2tc pwr = pointer_with_region2tc(rhs_base_addr, rhs_heap); - symex_assign(code_assign2tc(lhs, pwr)); + symex_assign(code_assign2tc(lhs_flag, pwr)); // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly - expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), pwr); + expr2tc ptr_obj = + pointer_object2tc(get_intloc_type(), to_pointer_with_region2t(pwr).loc_ptr); track_new_pointer(ptr_obj, get_intheap_type(), region_size); dynamic_memory.emplace_back( rhs_heap, @@ -319,6 +330,11 @@ expr2tc goto_symext::symex_mem( symbol.name.as_string() ); + if (is_heap_load2t(lhs)) + { + guardt g; + symex_assign_heap_laod(lhs, lhs, pwr, pwr, g, false); + } return expr2tc(); } } @@ -389,57 +405,74 @@ void goto_symext::symex_free(const expr2tc &expr) log_status("tmp before dereference INTERNAL mode: "); tmp->dump(); dereference(tmp, dereferencet::INTERNAL); + + bool is_old_encoding = !options.get_bool_option("z3-slhv"); // Only add assertions to check pointer offset if pointer check is enabled if (!options.get_bool_option("no-pointer-check")) { // Get all dynamic objects allocated using alloca - std::vector allocad; - for (auto const &item : dynamic_memory) - if (item.auto_deallocd) - allocad.push_back(item); - - for (auto const &item : internal_deref_items) + if (is_old_encoding) { - log_status("internal deref item: "); - item.object->dump(); - log_status("offset: "); - item.offset->dump(); - guardt g = cur_state->guard; - g.add(item.guard); - - // Check if the offset of the object being freed is zero - expr2tc offset = item.offset; - expr2tc eq = equality2tc(offset, gen_ulong(0)); - g.guard_expr(eq); - claim(eq, "Operand of free must have zero pointer offset"); - - // Check if we are not freeing an dynamic object allocated using alloca - for (auto const &a : allocad) + std::vector allocad; + for (auto const &item : dynamic_memory) + if (item.auto_deallocd) + allocad.push_back(item); + + for (auto const &item : internal_deref_items) { - expr2tc alloc_obj = get_base_object(a.obj); - while (is_if2t(alloc_obj)) + log_status("internal deref item: "); + item.object->dump(); + log_status("offset: "); + item.offset->dump(); + guardt g = cur_state->guard; + g.add(item.guard); + + // Check if the offset of the object being freed is zero + expr2tc offset = item.offset; + expr2tc eq = equality2tc(offset, gen_ulong(0)); + g.guard_expr(eq); + claim(eq, "Operand of free must have zero pointer offset"); + + // Check if we are not freeing an dynamic object allocated using alloca + for (auto const &a : allocad) { - const if2t &the_if = to_if2t(alloc_obj); - assert(is_symbol2t(the_if.false_value)); - assert(to_symbol2t(the_if.false_value).thename == "NULL"); - alloc_obj = get_base_object(the_if.true_value); - } - assert(is_symbol2t(alloc_obj)); - const irep_idt &id_alloc_obj = to_symbol2t(alloc_obj).thename; - const irep_idt &id_item_obj = to_symbol2t(item.object).thename; - // Check if the object allocated with alloca is the same - // as given in the free function - if (id_alloc_obj == id_item_obj) - { - expr2tc noteq = notequal2tc(alloc_obj, item.object); - g.guard_expr(noteq); - claim(noteq, "dereference failure: invalid pointer freed"); + expr2tc alloc_obj = get_base_object(a.obj); + while (is_if2t(alloc_obj)) + { + const if2t &the_if = to_if2t(alloc_obj); + assert(is_symbol2t(the_if.false_value)); + assert(to_symbol2t(the_if.false_value).thename == "NULL"); + alloc_obj = get_base_object(the_if.true_value); + } + assert(is_symbol2t(alloc_obj)); + const irep_idt &id_alloc_obj = to_symbol2t(alloc_obj).thename; + const irep_idt &id_item_obj = to_symbol2t(item.object).thename; + // Check if the object allocated with alloca is the same + // as given in the free function + if (id_alloc_obj == id_item_obj) + { + expr2tc noteq = notequal2tc(alloc_obj, item.object); + g.guard_expr(noteq); + claim(noteq, "dereference failure: invalid pointer freed"); + } } } } + else + { + log_status("here"); + for (auto const &item : internal_deref_items) + { + log_status("internal deref item: "); + item.object->dump(); + log_status("offset: "); + item.offset->dump(); + guardt g = cur_state->guard; + g.add(item.guard); + } + } } - bool is_old_encoding = !options.get_bool_option("z3-slhv"); if(is_old_encoding){ // Clear the alloc bit. type2tc sym_type = array_type2tc(get_bool_type(), expr2tc(), true); diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index b69eb465..4686d71e 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -546,7 +546,6 @@ class goto_symext * @param type Assignment type, visible by default * @param kind The step kind, by default is plain BMC * @param guard A guard for the assignment, true by default - * @param is_replace_heap_load Replace heap_load by its flag */ virtual void symex_assign( const expr2tc &code, @@ -758,13 +757,13 @@ class goto_symext * @param rhs Value to assign to lhs * @param guard Assignment guard. */ - // void symex_assign_heap_laod( - // const expr2tc &lhs, - // const expr2tc &full_lhs, - // expr2tc &rhs, - // expr2tc &full_rhs, - // guardt &guard, - // const bool hidden); + void symex_assign_heap_laod( + const expr2tc &lhs, + const expr2tc &full_lhs, + expr2tc &rhs, + expr2tc &full_rhs, + guardt &guard, + const bool hidden); /** Symbolic implementation of malloc. */ expr2tc symex_malloc(const expr2tc &lhs, const sideeffect2t &code); @@ -801,12 +800,6 @@ class goto_symext */ void replace_nondet(expr2tc &expr); - /** - * Replace heap_load with a new pointer - * @param expr Expr to search for heap_load. - */ - void replace_heap_load(expr2tc &expr); - /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. @@ -967,7 +960,7 @@ class symex_dereference_statet : public dereference_callbackt void update_regions(const expr2tc ®ion) override; void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) override; - unsigned int get_new_nondet_id() override; + std::string get_loaded_value_flag(const expr2tc &expr) override; }; #endif diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index b5209830..287a5635 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,14 +11,12 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - if (is_pointer_with_region2t(expr)) - { + if (is_heap_region2t(expr)) + return get_symbols(to_heap_region2t(expr).start_loc); + else if (is_pointer_with_region2t(expr)) return get_symbols(to_pointer_with_region2t(expr).loc_ptr); - } else if (is_heap_load2t(expr)) - { return get_symbols(to_heap_load2t(expr).flag); - } else { // Recursively look if any of the operands has a inner symbol diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index ae3a5c49..1bf16420 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -198,9 +198,9 @@ void goto_symext::symex_assign( replace_dynamic_allocation(rhs); log_status("replace done"); - log_status("replace heap_load"); - replace_heap_load(lhs); - replace_heap_load(rhs); + log_status("after deref and replace : =-===="); + lhs->dump(); + rhs->dump(); // printf expression that has lhs if (is_code_printf2t(rhs)) @@ -258,7 +258,9 @@ void goto_symext::symex_assign( } } - log_status("before symex assign rec"); + log_status("before symex assign rec : =-===="); + lhs->dump(); + rhs->dump(); guardt g(guard); // NOT the state guard! symex_assign_rec(lhs, original_lhs, rhs, expr2tc(), g, hidden_ssa); @@ -331,7 +333,7 @@ void goto_symext::symex_assign_rec( else if (is_heap_load2t(lhs)) { log_status("symex_assign_heap_load"); - // symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); + symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_heap_region2t(lhs)) { @@ -871,28 +873,28 @@ void goto_symext::symex_assign_bitfield( return symex_assign_rec(val, full_lhs, new_rhs, full_rhs, guard, hidden); } -// void goto_symext::symex_assign_heap_laod( -// const expr2tc &lhs, -// const expr2tc &full_lhs, -// expr2tc &rhs, -// expr2tc &full_rhs, -// guardt &guard, -// const bool hidden) -// { -// assert(is_scalar_type(rhs)); +void goto_symext::symex_assign_heap_laod( + const expr2tc &lhs, + const expr2tc &full_lhs, + expr2tc &rhs, + expr2tc &full_rhs, + guardt &guard, + const bool hidden) +{ + assert(is_scalar_type(rhs)); -// const heap_load2t& heap_load = to_heap_load2t(lhs); -// assert(heap_load.byte_len * 8 == rhs->type->get_width()); + const heap_load2t& heap_load = to_heap_load2t(lhs); + // assert(heap_load.byte_len * 8 == rhs->type->get_width()); -// // Pin one set of rhs version numbers: if we assign part of a value to itself, -// // it'll change during the assignment -// cur_state->rename(rhs); // shall we? + // Pin one set of rhs version numbers: if we assign part of a value to itself, + // it'll change during the assignment + cur_state->rename(rhs); // shall we? -// expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_loc); -// expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); + expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_loc); + expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); -// symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); -// } + symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); +} void goto_symext::replace_nondet(expr2tc &expr) { @@ -910,24 +912,4 @@ void goto_symext::replace_nondet(expr2tc &expr) replace_nondet(e); }); } -} - - -void goto_symext::replace_heap_load(expr2tc &expr) -{ - if (is_heap_load2t(expr)) - { - heap_load2t& heap_load = to_heap_load2t(expr); - // symex_assign(code_assign2tc(heap_load.flag, expr), false, guardt(), false); - guardt g; - symex_assign_rec(heap_load.flag, heap_load.flag, expr, expr, g, false); - expr = heap_load.flag; - } - else - { - expr->Foreach_operand([this](expr2tc &e) { - if (!is_nil_expr(e)) - replace_heap_load(e); - }); - } } \ No newline at end of file diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 267921b7..dee429b6 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -221,11 +221,26 @@ void symex_dereference_statet::update_heap_region_rec( } } -unsigned int symex_dereference_statet::get_new_nondet_id() +std::string symex_dereference_statet::get_loaded_value_flag(const expr2tc &expr) { - return ++goto_symex.get_nondet_counter(); + if (is_symbol2t(expr)) + return to_symbol2t(expr).get_symbol_name(); + else if (is_constant_int2t(expr)) + return std::to_string(to_constant_int2t(expr).value.to_int64()); + else if (is_locadd2t(expr)) + { + const locadd2t &locadd = to_locadd2t(expr); + return get_loaded_value_flag(locadd.base_addr) + + get_loaded_value_flag(locadd.added_num); + } + else + { + log_error("Do not support"); + abort(); + } } + void goto_symext::dereference(expr2tc &expr, dereferencet::modet mode) { symex_dereference_statet symex_dereference_state(*this, *cur_state); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 63028f0b..1d88c7ac 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1248,9 +1248,9 @@ void dereferencet::build_reference_slhv( ); } - std::string flag_id = std::string("symex_dynamic::nondet_") + - ((is_pointer_type(type) || is_intloc_type(type)) ? "loc_" : "val_") + - i2string(dereference_callback.get_new_nondet_id()); + std::string flag_id = + std::string("nondet_loaded::") + + dereference_callback.get_loaded_value_flag(access_ptr); expr2tc flag = symbol2tc(type, flag_id); value = heap_load2tc(type, flag, heap, access_ptr, access_sz); diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 0c5cb340..87ce23aa 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -168,7 +168,7 @@ class dereference_callbackt abort(); } - virtual unsigned int get_new_nondet_id() + virtual std::string get_loaded_value_flag(const expr2tc &expr) { log_error("Do not support"); abort(); From 521021d31f14fb3118d7e8cf325409c2f52dabeb Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 12 Aug 2024 15:58:41 +0800 Subject: [PATCH 039/126] update encoding of valid_check --- src/goto-symex/builtin_functions.cpp | 94 ++++++++++-------------- src/pointer-analysis/dereference.cpp | 106 ++++----------------------- src/pointer-analysis/dereference.h | 1 - 3 files changed, 52 insertions(+), 149 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index ca4dddcd..2dd67f99 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -406,73 +406,57 @@ void goto_symext::symex_free(const expr2tc &expr) tmp->dump(); dereference(tmp, dereferencet::INTERNAL); - bool is_old_encoding = !options.get_bool_option("z3-slhv"); // Only add assertions to check pointer offset if pointer check is enabled if (!options.get_bool_option("no-pointer-check")) { // Get all dynamic objects allocated using alloca - if (is_old_encoding) - { - std::vector allocad; - for (auto const &item : dynamic_memory) - if (item.auto_deallocd) - allocad.push_back(item); + std::vector allocad; + for (auto const &item : dynamic_memory) + if (item.auto_deallocd) + allocad.push_back(item); - for (auto const &item : internal_deref_items) + for (auto const &item : internal_deref_items) + { + log_status("internal deref item: "); + item.object->dump(); + log_status("offset: "); + item.offset->dump(); + guardt g = cur_state->guard; + g.add(item.guard); + + // Check if the offset of the object being freed is zero + expr2tc offset = item.offset; + expr2tc eq = equality2tc(offset, gen_ulong(0)); + g.guard_expr(eq); + claim(eq, "Operand of free must have zero pointer offset"); + + // Check if we are not freeing an dynamic object allocated using alloca + for (auto const &a : allocad) { - log_status("internal deref item: "); - item.object->dump(); - log_status("offset: "); - item.offset->dump(); - guardt g = cur_state->guard; - g.add(item.guard); - - // Check if the offset of the object being freed is zero - expr2tc offset = item.offset; - expr2tc eq = equality2tc(offset, gen_ulong(0)); - g.guard_expr(eq); - claim(eq, "Operand of free must have zero pointer offset"); - - // Check if we are not freeing an dynamic object allocated using alloca - for (auto const &a : allocad) + expr2tc alloc_obj = get_base_object(a.obj); + while (is_if2t(alloc_obj)) { - expr2tc alloc_obj = get_base_object(a.obj); - while (is_if2t(alloc_obj)) - { - const if2t &the_if = to_if2t(alloc_obj); - assert(is_symbol2t(the_if.false_value)); - assert(to_symbol2t(the_if.false_value).thename == "NULL"); - alloc_obj = get_base_object(the_if.true_value); - } - assert(is_symbol2t(alloc_obj)); - const irep_idt &id_alloc_obj = to_symbol2t(alloc_obj).thename; - const irep_idt &id_item_obj = to_symbol2t(item.object).thename; - // Check if the object allocated with alloca is the same - // as given in the free function - if (id_alloc_obj == id_item_obj) - { - expr2tc noteq = notequal2tc(alloc_obj, item.object); - g.guard_expr(noteq); - claim(noteq, "dereference failure: invalid pointer freed"); - } + const if2t &the_if = to_if2t(alloc_obj); + assert(is_symbol2t(the_if.false_value)); + assert(to_symbol2t(the_if.false_value).thename == "NULL"); + alloc_obj = get_base_object(the_if.true_value); + } + assert(is_symbol2t(alloc_obj)); + const irep_idt &id_alloc_obj = to_symbol2t(alloc_obj).thename; + const irep_idt &id_item_obj = to_symbol2t(item.object).thename; + // Check if the object allocated with alloca is the same + // as given in the free function + if (id_alloc_obj == id_item_obj) + { + expr2tc noteq = notequal2tc(alloc_obj, item.object); + g.guard_expr(noteq); + claim(noteq, "dereference failure: invalid pointer freed"); } - } - } - else - { - log_status("here"); - for (auto const &item : internal_deref_items) - { - log_status("internal deref item: "); - item.object->dump(); - log_status("offset: "); - item.offset->dump(); - guardt g = cur_state->guard; - g.add(item.guard); } } } + bool is_old_encoding = !options.get_bool_option("z3-slhv"); if(is_old_encoding){ // Clear the alloc bit. type2tc sym_type = array_type2tc(get_bool_type(), expr2tc(), true); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 1d88c7ac..24bed594 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -803,9 +803,18 @@ expr2tc dereferencet::build_reference_to( object->dump(); deref_expr->dump(); - pointer_guard = same_object2tc(deref_expr, object); guardt tmp_guard(guard); - tmp_guard.add(pointer_guard); + if (is_heap_region2t(object)) + { + // pointer_guard = same_object2tc(deref_expr, object); + pointer_guard = equality2tc(deref_expr, to_heap_region2t(object).start_loc); + tmp_guard.add(pointer_guard); + } + else + { + log_error("Not heap region"); + abort(); + } // Check that the object we're accessing is actually alive and valid for this // mode. @@ -2327,102 +2336,13 @@ void dereferencet::valid_check( tmp_guard.add(not_valid_heap_region); std::string foo = is_free(mode) ? "invalid free pointer" : "invalid dereference pointer"; + // deref failure will replace heap region with heap contains + // that indicates the reigon is avaliable. dereference_failure("pointer dereference", foo, tmp_guard); return; } } -// void dereferencet::valid_check_slhv( -// const expr2tc &object, -// const guardt &guard, -// modet mode) -// { -// const expr2tc &symbol = get_symbol(object); - -// if (is_constant_string2t(symbol)) -// { -// // always valid, but can't write - -// if (is_write(mode)) -// { -// dereference_failure( -// "pointer dereference", "write access to string constant", guard); -// } -// } -// else if (is_nil_expr(symbol)) -// { -// // always "valid", shut up -// return; -// } -// else if (is_symbol2t(symbol)) -// { -// // Hacks, but as dereferencet object isn't persistent, necessary. Fix by -// // making dereferencet persistent. -// if (has_prefix( -// to_symbol2t(symbol).thename.as_string(), "symex::invalid_object")) -// { -// // This is an invalid object; if we're in read or write mode, that's an error. -// if (is_read(mode) || is_write(mode)) -// dereference_failure("pointer dereference", "invalid pointer", guard); -// return; -// } - -// const symbolt &sym = *ns.lookup(to_symbol2t(symbol).thename); -// if (has_prefix(sym.id.as_string(), "symex_dynamic::")) -// { -// // Assert that it hasn't (nondeterministically) been invalidated. -// expr2tc addrof = address_of2tc(symbol->type, symbol); -// expr2tc valid_expr = valid_object2tc(addrof); -// expr2tc not_valid_expr = not2tc(valid_expr); - -// guardt tmp_guard(guard); -// tmp_guard.add(not_valid_expr); - -// std::string foo = is_free(mode) ? "invalidated dynamic object freed" -// : "invalidated dynamic object"; -// dereference_failure("pointer dereference", foo, tmp_guard); -// } -// else -// { -// // Not dynamic; if we're in free mode, that's an error. -// if (is_free(mode)) -// { -// dereference_failure( -// "pointer dereference", "free() of non-dynamic memory", guard); -// return; -// } - -// // Otherwise, this is a pointer to some kind of lexical variable, with -// // either global or function-local scope. Ask symex to determine if -// // it's live. -// if (!dereference_callback.is_live_variable(symbol)) -// { -// // Any access where this guard is true -> failure -// dereference_failure( -// "pointer dereference", -// "accessed expired variable pointer `" + -// get_pretty_name(to_symbol2t(symbol).thename.as_string()) + "'", -// guard); -// return; -// } -// } -// } else if(is_pointer_with_region2t(symbol)) { -// // slhv -// log_status("pointer with region dereference failure here"); -// // assert that the pointer we dereference with a specific length lies in the heap variable -// // TODO: maybe add a special expression type to denote that the pointer_with_region is not valid -// expr2tc not_valid_pointer_with_region = not2tc(valid_object2tc(symbol)); -// log_status("not valid print:"); -// not_valid_pointer_with_region->dump(); -// guardt tmp_guard(guard); -// tmp_guard.add(not_valid_pointer_with_region); -// std::string foo = is_free(mode) ? "invalid free pointer" -// : "invalid dereference pointer"; -// dereference_failure("pointer dereference", foo, tmp_guard); -// return; -// } -// } - void dereferencet::bounds_check( const expr2tc &expr, const expr2tc &offset, diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 87ce23aa..e803de47 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -424,7 +424,6 @@ class dereferencet const type2tc &type, const guardt &guard); void valid_check(const expr2tc &expr, const guardt &guard, modet mode); - // void valid_check_slhv(const expr2tc &expr, const guardt &guard, modet mode); std::vector extract_bytes( const expr2tc &object, unsigned int bytes, From 5652b2a5f8446a8df81ad3bc5c3ca5f0dff42bd6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 12 Aug 2024 16:31:09 +0800 Subject: [PATCH 040/126] invalid pointer encoding --- src/goto-symex/builtin_functions.cpp | 12 +++--- src/goto-symex/dynamic_allocation.cpp | 59 ++++++++++++++++----------- src/goto-symex/symex_main.cpp | 4 +- src/pointer-analysis/dereference.cpp | 7 +++- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 2dd67f99..4b83b1db 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -148,8 +148,8 @@ expr2tc goto_symext::symex_mem( unsigned int &dynamic_counter = get_dynamic_counter(); dynamic_counter++; - bool is_old_encoding = !options.get_bool_option("z3-slhv"); - if (is_old_encoding) { + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + if (use_old_encoding) { symbolt symbol; symbol.name = "dynamic_" + i2string(dynamic_counter) + @@ -344,11 +344,11 @@ void goto_symext::track_new_pointer( const type2tc &new_type, const expr2tc &size) { - bool is_old_encoding = !options.get_bool_option("z3-slhv"); + bool use_old_encoding = !options.get_bool_option("z3-slhv"); // Also update all the accounting data. // Mark that object as being dynamic, in the __ESBMC_is_dynamic array - if(is_old_encoding) { + if(use_old_encoding) { type2tc sym_type = array_type2tc(get_bool_type(), expr2tc (), true); expr2tc sym = symbol2tc(sym_type, dyn_info_arr_name); @@ -456,8 +456,8 @@ void goto_symext::symex_free(const expr2tc &expr) } } - bool is_old_encoding = !options.get_bool_option("z3-slhv"); - if(is_old_encoding){ + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + if(use_old_encoding){ // Clear the alloc bit. type2tc sym_type = array_type2tc(get_bool_type(), expr2tc(), true); expr2tc ptr_obj = pointer_object2tc(pointer_type2(), code.operand); diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 7e8242eb..30675361 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -14,11 +14,11 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) default_replace_dynamic_allocation(e); }); + bool use_old_encoding = !options.get_bool_option("z3-slhv"); if (is_valid_object2t(expr)) { /* alloc */ // replace with CPROVER_alloc[POINTER_OBJECT(...)] - bool use_old_encoding = !options.get_bool_option("z3-slhv"); if(use_old_encoding) { const valid_object2t &obj = to_valid_object2t(expr); @@ -51,35 +51,48 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc obj_expr = pointer_object2tc(pointer_type2(), ptr.ptr_obj); - expr2tc alloc_arr_2; - migrate_expr(symbol_expr(*ns.lookup(valid_ptr_arr_name)), alloc_arr_2); + if (use_old_encoding) + { + expr2tc alloc_arr_2; + migrate_expr(symbol_expr(*ns.lookup(valid_ptr_arr_name)), alloc_arr_2); + + expr2tc index_expr = index2tc(get_bool_type(), alloc_arr_2, obj_expr); + expr2tc notindex = not2tc(index_expr); + + // XXXjmorse - currently we don't correctly track the fact that stack + // objects change validity as the program progresses, and the solver is + // free to guess that a stack ptr is invalid, as we never update + // __ESBMC_alloc for stack ptrs. + // So, add the precondition that invalid_ptr only ever applies to dynamic + // objects. - expr2tc index_expr = index2tc(get_bool_type(), alloc_arr_2, obj_expr); - expr2tc notindex = not2tc(index_expr); + expr2tc sym_2; + migrate_expr(symbol_expr(*ns.lookup(dyn_info_arr_name)), sym_2); - // XXXjmorse - currently we don't correctly track the fact that stack - // objects change validity as the program progresses, and the solver is - // free to guess that a stack ptr is invalid, as we never update - // __ESBMC_alloc for stack ptrs. - // So, add the precondition that invalid_ptr only ever applies to dynamic - // objects. + expr2tc ptr_obj = pointer_object2tc(pointer_type2(), ptr.ptr_obj); + expr2tc is_dyn = index2tc(get_bool_type(), sym_2, ptr_obj); - expr2tc sym_2; - migrate_expr(symbol_expr(*ns.lookup(dyn_info_arr_name)), sym_2); + // Catch free pointers: don't allow anything to be pointer object 1, the + // invalid pointer. + type2tc ptr_type = pointer_type2tc(get_empty_type()); + expr2tc invalid_object = symbol2tc(ptr_type, "INVALID"); + expr2tc isinvalid = equality2tc(ptr.ptr_obj, invalid_object); - expr2tc ptr_obj = pointer_object2tc(pointer_type2(), ptr.ptr_obj); - expr2tc is_dyn = index2tc(get_bool_type(), sym_2, ptr_obj); + expr2tc is_not_bad_ptr = and2tc(notindex, is_dyn); + expr2tc is_valid_ptr = or2tc(is_not_bad_ptr, isinvalid); - // Catch free pointers: don't allow anything to be pointer object 1, the - // invalid pointer. - type2tc ptr_type = pointer_type2tc(get_empty_type()); - expr2tc invalid_object = symbol2tc(ptr_type, "INVALID"); - expr2tc isinvalid = equality2tc(ptr.ptr_obj, invalid_object); + expr = is_valid_ptr; + } + else + { + expr2tc alloc_size_heap; + migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - expr2tc is_not_bad_ptr = and2tc(notindex, is_dyn); - expr2tc is_valid_ptr = or2tc(is_not_bad_ptr, isinvalid); + expr2tc heap_contains = heap_contains2tc(alloc_size_heap, obj_expr, 1); + expr2tc not_valid = not2tc(heap_contains); - expr = is_valid_ptr; + expr = not_valid; + } } else if (is_deallocated_obj2t(expr)) { diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 5012edfd..ed5e704c 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1168,8 +1168,8 @@ void goto_symext::add_memory_leak_checks() return is_any ? is_any : gen_false_expr(); }; } - bool is_old_encoding = !options.get_bool_option("z3-slhv"); - if(is_old_encoding) { + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + if(use_old_encoding) { for (auto const &it : dynamic_memory) { // Don't check memory leak if the object is automatically deallocated diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 24bed594..647eb451 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -940,7 +940,12 @@ void dereferencet::deref_invalid_ptr( if (is_free(mode)) { // You're allowed to free NULL. - expr2tc null_ptr = symbol2tc(pointer_type2tc(get_empty_type()), "NULL"); + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + expr2tc null_ptr; + if (use_old_encoding) + null_ptr = symbol2tc(pointer_type2tc(get_empty_type()), "NULL"); + else + null_ptr = gen_intloc_constant(0); expr2tc neq = notequal2tc(null_ptr, deref_expr); expr2tc and_ = and2tc(neq, invalid_pointer_expr); validity_test = and_; From bb3b67da59eef73f411594e03073fb3c2cdd6060 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 14 Aug 2024 12:04:52 +0800 Subject: [PATCH 041/126] fix: check heap region access, constant propagation and encoding of same object --- benchmark/case_0.c | 15 +- benchmark/case_1.c | 25 +-- src/esbmc/bmc.cpp | 2 +- src/goto-symex/builtin_functions.cpp | 31 ++-- src/goto-symex/dynamic_allocation.cpp | 4 +- src/goto-symex/goto_symex.h | 2 + src/goto-symex/goto_symex_state.cpp | 20 ++- src/goto-symex/slice.cpp | 2 - src/goto-symex/symex_dereference.cpp | 16 +- src/irep2/irep2_expr.h | 78 ++++---- src/irep2/templates/irep2_templates.cpp | 8 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 170 +++++++++++++----- src/pointer-analysis/dereference.h | 12 ++ src/pointer-analysis/value_set.cpp | 2 +- src/solvers/smt/smt_conv.cpp | 4 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 78 ++++---- src/solvers/z3-slhv/z3_slhv_conv.h | 1 + src/util/migrate.cpp | 8 +- 19 files changed, 306 insertions(+), 174 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 12279bf0..e71e3e4b 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -2,15 +2,8 @@ int main(){ // int whatever; - int * data = malloc(sizeof(int)); - int * data2 = malloc(2*sizeof(int)); - free(data); - int i = *(data); - // int* j = NULL; - // int* i = j; - // // *(data + 1) = whatever; - // int n = *(data+1); - // if(i > 0) { - // free(data); - // } + int * data = malloc(2 * sizeof(int)); + int * data2 = malloc(2 * sizeof(int)); + free(data2); + int i = *(data2 + 1); } diff --git a/benchmark/case_1.c b/benchmark/case_1.c index 883210c8..6d1a862e 100644 --- a/benchmark/case_1.c +++ b/benchmark/case_1.c @@ -1,15 +1,18 @@ #include -int main(){ +typedef struct { + void *lo; + void *hi; +} TData; - int num = 5; - int *i = (int*) malloc(sizeof(int)); - int *j = (int*)malloc(num*sizeof(int)); - int *p = NULL; - if(i == j) { - free(j); - p = i; - } else { - p = j; - } +int main() { + TData * p1 = malloc(sizeof(TData)); + p1->lo = malloc(12); + p1->hi = malloc(12); + void * p2; + int x; + if (x) p2 = p1->hi; + else p2 = p1->lo; + free(p2); + return 0; } diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index e4d307bb..9a23c51c 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -796,7 +796,7 @@ smt_convt::resultt bmct::multi_property_check( std::unique_ptr runtime_solver(create_solver("", ns, options)); // Save current instance generate_smt_from_equation(*runtime_solver, local_eq); - + log_status( "Solving claim '{}' with solver {}", claim.claim_msg, diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 4b83b1db..1ec4c464 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -120,9 +120,6 @@ expr2tc goto_symext::symex_mem( // size type2tc type = code.alloctype; expr2tc size = code.size; - log_status("alloc size: "); - size->dump(); - // TODO slhv: need to do the constant propagation here bool size_is_one = false; if (is_nil_type(type)) @@ -132,11 +129,10 @@ expr2tc goto_symext::symex_mem( size_is_one = true; else { - cur_state->rename(size); + cur_state->rename(size); // rename will do constant propagation BigInt i; if (is_constant_int2t(size)) { - log_status("is constant"); uint64_t v = to_constant_int2t(size).value.to_uint64(); if (v == 1) size_is_one = true; @@ -260,16 +256,22 @@ expr2tc goto_symext::symex_mem( // Size in SLHV is byte level // expr2tc bytesizes - expr2tc operand = code.operand; - if (!is_constant_int2t(operand)) - operand = operand.simplify(); - if (!is_constant_int2t(operand)) + expr2tc bytes; + if (size_is_one) + bytes = gen_ulong(type->get_width() / 8); + else { - log_error("Do not support dynamic size"); - abort(); + bytes = size; + if (!is_constant_int2t(bytes)) + bytes = bytes.simplify(); + if (!is_constant_int2t(bytes)) + { + log_error("Do not support dynamic size"); + abort(); + } } - uint total_bytes = to_constant_int2t(operand).value.to_uint64(); + uint total_bytes = to_constant_int2t(bytes).value.to_uint64(); uint pt_bytes = type.get()->get_width() / 8; uint size = total_bytes / pt_bytes; if (pt_bytes == 1) @@ -322,7 +324,10 @@ expr2tc goto_symext::symex_mem( // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), to_pointer_with_region2t(pwr).loc_ptr); - track_new_pointer(ptr_obj, get_intheap_type(), region_size); + track_new_pointer( + ptr_obj, + get_intheap_type(), + gen_ulong(total_bytes)); dynamic_memory.emplace_back( rhs_heap, rhs_guard, diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 30675361..423bec19 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -40,7 +40,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_status("before migrate"); migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap_2); log_status("migrate over"); - expr2tc heap_contains = heap_contains2tc(alloc_size_heap_2, valid_inner.start_loc, 1); + expr2tc heap_contains = heap_contains2tc(valid_inner.start_loc, alloc_size_heap_2, 1); expr = heap_contains; } } @@ -88,7 +88,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - expr2tc heap_contains = heap_contains2tc(alloc_size_heap, obj_expr, 1); + expr2tc heap_contains = heap_contains2tc(obj_expr, alloc_size_heap, 1); expr2tc not_valid = not2tc(heap_contains); expr = not_valid; diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 4686d71e..eff701dc 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -961,6 +961,8 @@ class symex_dereference_statet : public dereference_callbackt void update_regions(const expr2tc ®ion) override; void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) override; std::string get_loaded_value_flag(const expr2tc &expr) override; + std::string get_nondet_id(std::string prefix = "") override; + irep_idt get_alooc_size_heap_name() override; }; #endif diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 2e2057fb..e7cf4946 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -66,9 +66,18 @@ void goto_symex_statet::initialize( bool goto_symex_statet::constant_propagation(const expr2tc &expr) const { - if(is_intheap_type(expr)) { - return false; + // SLHV propagation + if (is_heap_region2t(expr) || is_pointer_with_region2t(expr) || + is_constant_intheap2t(expr) || is_constant_intloc2t(expr) || + is_heap_load2t(expr)) + return true; + if (is_locadd2t(expr)) + { + locadd2t locadd = to_locadd2t(expr); + return constant_propagation(locadd.loc) && + constant_propagation(locadd.offset); } + if (is_array_type(expr)) { array_type2t arr = to_array_type(expr->type); @@ -244,6 +253,11 @@ void goto_symex_statet::rename(expr2tc &expr) { // rename all the symbols with their last known value + if (is_pointer_with_region2t(expr) || + is_heap_region2t(expr) || + is_heap_load2t(expr)) + return; // Do not rename pwr + if (is_nil_expr(expr)) return; @@ -316,6 +330,8 @@ void goto_symex_statet::fixup_renamed_type( } if (is_pointer_type(orig_type)) { + if (is_intloc_type(expr)) return; + assert(is_pointer_type(expr)); // Grab pointer types diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 287a5635..b9976c40 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -15,8 +15,6 @@ bool symex_slicet::get_symbols(const expr2tc &expr) return get_symbols(to_heap_region2t(expr).start_loc); else if (is_pointer_with_region2t(expr)) return get_symbols(to_pointer_with_region2t(expr).loc_ptr); - else if (is_heap_load2t(expr)) - return get_symbols(to_heap_load2t(expr).flag); else { // Recursively look if any of the operands has a inner symbol diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index dee429b6..c86eea2a 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -230,9 +230,11 @@ std::string symex_dereference_statet::get_loaded_value_flag(const expr2tc &expr) else if (is_locadd2t(expr)) { const locadd2t &locadd = to_locadd2t(expr); - return get_loaded_value_flag(locadd.base_addr) + - get_loaded_value_flag(locadd.added_num); + return get_loaded_value_flag(locadd.loc) + + get_loaded_value_flag(locadd.offset); } + else if (is_typecast2t(expr)) + return get_loaded_value_flag(to_typecast2t(expr).from); else { log_error("Do not support"); @@ -240,6 +242,16 @@ std::string symex_dereference_statet::get_loaded_value_flag(const expr2tc &expr) } } +std::string symex_dereference_statet::get_nondet_id(std::string prefix) +{ + unsigned int nondet_counter = goto_symex.get_nondet_counter(); + return prefix + std::to_string(++nondet_counter); +} + +irep_idt symex_dereference_statet::get_alooc_size_heap_name() +{ + return goto_symex.alloc_size_heap_name; +} void goto_symext::dereference(expr2tc &expr, dereferencet::modet mode) { diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index d4eadd0e..66ac77c1 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -906,9 +906,8 @@ class points_to_data : public expr2t const type2tc &t, datatype_ops::expr_ids id, const expr2tc &addrloc, - const expr2tc &content, - bool is_loc) - : expr2t(t, id), addr(addrloc), content(content), is_loc_content(is_loc) + const expr2tc &content) + : expr2t(t, id), addr(addrloc), content(content) { } points_to_data(const points_to_data& ref) = default; @@ -916,16 +915,15 @@ class points_to_data : public expr2t expr2tc addr; expr2tc content; - bool is_loc_content; // Type mangling: typedef esbmct::field_traits - addr_field; + points_to_data_addr_field; typedef esbmct::field_traits - content_field; - typedef esbmct::field_traits - is_loc_content_field; - typedef esbmct::expr2t_traits traits; + points_to_data_content_field; + typedef esbmct::expr2t_traits< + points_to_data_addr_field, + points_to_data_content_field> traits; }; @@ -963,21 +961,21 @@ class locadd_data : public expr2t locadd_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &base_addr, - const expr2tc &added) - : expr2t(t, id), base_addr(base_addr), added_num(added) + const expr2tc &loc, + const expr2tc &offset) + : expr2t(t, id), loc(loc), offset(offset) { } locadd_data(const locadd_data& ref) = default; - expr2tc base_addr; - expr2tc added_num; + expr2tc loc; + expr2tc offset; // Type mangling: - typedef esbmct::field_traits - locadd_base_addr_field; - typedef esbmct::field_traits - locadd_added_num_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + locadd_loc_field; + typedef esbmct::field_traits + locadd_offset_field; + typedef esbmct::expr2t_traits traits; }; @@ -1201,30 +1199,29 @@ class heap_contains_data : public expr2t { heap_contains_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc hvar, - expr2tc start_loc, - unsigned int blk_byte_len) - : expr2t(t, id), heapvar(hvar), start_loc(start_loc), byte_len(blk_byte_len) + expr2tc hterm, + expr2tc heap, + unsigned int byte_len) + : expr2t(t, id), hterm(hterm), heap(heap), byte_len(byte_len) { } - expr2tc heapvar; - expr2tc start_loc; + expr2tc hterm; + expr2tc heap; unsigned int byte_len; //Type mangling: - typedef esbmct::field_traits - heap_contains_data_heapvar_field; - typedef esbmct::field_traits - heap_contains_data_start_loc_field; + typedef esbmct::field_traits + heap_contains_data_hterm_field; + typedef esbmct::field_traits + heap_contains_data_heap_field; typedef esbmct::field_traits heap_contains_data_byte_len_field; - typedef esbmct::expr2t_traits - < - heap_contains_data_heapvar_field, heap_contains_data_start_loc_field, heap_contains_data_byte_len_field - > traits; - + typedef esbmct::expr2t_traits< + heap_contains_data_hterm_field, + heap_contains_data_heap_field, + heap_contains_data_byte_len_field> traits; }; class string_ops : public expr2t @@ -3322,8 +3319,8 @@ class index2t : public index_expr_methods class points_to2t : public points_to_expr_methods { public: - points_to2t(const expr2tc addr, const expr2tc& content, bool is_loc) - : points_to_expr_methods(get_intheap_type(), points_to_id, addr, content, is_loc) + points_to2t(const expr2tc &addr, const expr2tc &content) + : points_to_expr_methods(get_intheap_type(), points_to_id, addr, content) { } points_to2t(const points_to2t &ref) = default; @@ -3347,8 +3344,8 @@ class uplus2t : public uplus_expr_methods class locadd2t : public locadd_expr_methods { public: - locadd2t(const expr2tc &base_addr, const expr2tc &added) - : locadd_expr_methods(get_intloc_type(), locadd_id, base_addr, added) + locadd2t(const expr2tc &loc, const expr2tc &offset) + : locadd_expr_methods(get_intloc_type(), locadd_id, loc, offset) { } locadd2t(const locadd2t &ref) = default; @@ -3442,11 +3439,12 @@ class heap_delete2t : public heap_delete_expr_methods static std::string field_names[esbmct::num_type_fields]; }; + class heap_contains2t : public heap_contains_expr_methods { public: - heap_contains2t(expr2tc hvar, expr2tc start_loc, unsigned int byte_len) - : heap_contains_expr_methods(get_bool_type(), heap_contains_id, hvar, start_loc, byte_len) + heap_contains2t(expr2tc hterm, expr2tc heap, unsigned int byte_len) + : heap_contains_expr_methods(get_bool_type(), heap_contains_id, hterm, heap, byte_len) { } heap_contains2t(const heap_contains2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 648689e6..1902b328 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -160,12 +160,12 @@ std::string member2t::field_names[esbmct::num_type_fields] = {"source_value", "member_name", "", "", ""}; std::string index2t::field_names[esbmct::num_type_fields] = {"source_value", "index", "", "", ""}; +std::string points_to2t::field_names[esbmct::num_type_fields] = +{"addr", "content", "", "", ""}; std::string uplus2t::field_names[esbmct::num_type_fields] = {"uplus_members", "uplus_num", "", "", ""}; -std::string points_to2t::field_names[esbmct::num_type_fields] = -{"addr", "content", "is_loc", "", ""}; std::string locadd2t::field_names[esbmct::num_type_fields] = -{"baseaddr", "added_num", "", "", ""}; +{"loc", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = {"flag", "start_loc", "pt_bytes", "size", "is_split"}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = @@ -179,7 +179,7 @@ std::string heap_append2t::field_names[esbmct::num_type_fields] = std::string heap_delete2t::field_names[esbmct::num_type_fields] = {"src_heap", "del_addr", "byte_len", "", ""}; std::string heap_contains2t::field_names[esbmct::num_type_fields] = -{"heapvar", "start_loc", "byte_len", "", ""}; +{"hterm", "heap", "byte_len", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string overflow2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 5cf58bc5..66968ac0 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -29,7 +29,7 @@ expr_typedefs4(byte_update, byte_update_data); expr_typedefs3(with, with_data); expr_typedefs2(member, member_data); expr_typedefs2(index, index_data); -expr_typedefs3(points_to, points_to_data); +expr_typedefs2(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); expr_typedefs5(heap_region, heap_region_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 647eb451..ea4e9260 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -806,8 +806,16 @@ expr2tc dereferencet::build_reference_to( guardt tmp_guard(guard); if (is_heap_region2t(object)) { - // pointer_guard = same_object2tc(deref_expr, object); - pointer_guard = equality2tc(deref_expr, to_heap_region2t(object).start_loc); + heap_region2t& heap_region = to_heap_region2t(value); + int access_sz = type->get_width() / 8; + // Update its pt bytes + if (heap_region.update(access_sz)) + dereference_callback.update_regions(value); + + if (is_free(mode)) + pointer_guard = equality2tc(deref_expr, to_heap_region2t(object).start_loc); + else + pointer_guard = same_object2tc(deref_expr, object); tmp_guard.add(pointer_guard); } else @@ -816,6 +824,9 @@ expr2tc dereferencet::build_reference_to( abort(); } + log_status("generated pointer guard:"); + pointer_guard->dump(); + // Check that the object we're accessing is actually alive and valid for this // mode. valid_check(object, tmp_guard, mode); @@ -839,37 +850,47 @@ expr2tc dereferencet::build_reference_to( // If offset is unknown, or whatever, we have to consider it // nondeterministic, and let the reference builders deal with it. unsigned int alignment = o.alignment; - if (!is_constant_int2t(final_offset)) - { - if(is_pointer_with_region2t(value)) { - log_status("ERROR: non constant offset of pointer with region"); - } - assert(alignment != 0); - /* The expression being dereferenced doesn't need to be just a symbol: it - * might have all kind of things messing with alignment in there. */ - if (!is_symbol2t(deref_expr)) + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + if (use_old_encoding) + { + if (!is_constant_int2t(final_offset)) { - alignment = 1; - } + assert(alignment != 0); - final_offset = - pointer_offset2tc(get_int_type(config.ansi_c.address_width), deref_expr); - } + /* The expression being dereferenced doesn't need to be just a symbol: it + * might have all kind of things messing with alignment in there. */ + if (!is_symbol2t(deref_expr)) + { + alignment = 1; + } - type2tc offset_type = bitsize_type2(); - if (final_offset->type != offset_type) - final_offset = typecast2tc(offset_type, final_offset); + final_offset = + pointer_offset2tc(get_int_type(config.ansi_c.address_width), deref_expr); + } - // Converting final_offset from bytes to bits! - final_offset = - mul2tc(final_offset->type, final_offset, gen_long(final_offset->type, 8)); + type2tc offset_type = bitsize_type2(); + if (final_offset->type != offset_type) + final_offset = typecast2tc(offset_type, final_offset); - // Add any offset introduced lexically at the dereference site, i.e. member - // or index exprs, like foo->bar[3]. If bar is of integer type, we translate - // that to be a dereference of foo + extra_offset, resulting in an integer. - if (!is_nil_expr(lexical_offset)) - final_offset = add2tc(final_offset->type, final_offset, lexical_offset); + // Converting final_offset from bytes to bits! + final_offset = + mul2tc(final_offset->type, final_offset, gen_long(final_offset->type, 8)); + + // Add any offset introduced lexically at the dereference site, i.e. member + // or index exprs, like foo->bar[3]. If bar is of integer type, we translate + // that to be a dereference of foo + extra_offset, resulting in an integer. + if (!is_nil_expr(lexical_offset)) + final_offset = add2tc(final_offset->type, final_offset, lexical_offset); + } + else + { + if (!is_constant_int2t(final_offset)) + { + final_offset = deref_expr; + } + // TODO: add lexical offset + } // If we're in internal mode, collect all of our data into one struct, insert // it into the list of internal data, and then bail. The caller does not want @@ -1233,6 +1254,9 @@ void dereferencet::build_reference_slhv( unsigned long alignment) { log_status("build reference slhv"); + value->dump(); + guard.dump(); + offset->dump(); assert(is_heap_region2t(value)); if(is_scalar_type(type)) { if (!is_constant_int2t(offset)) offset.simplify(); @@ -1243,11 +1267,6 @@ void dereferencet::build_reference_slhv( expr2tc heap = heap_region.flag; int access_sz = type->get_width() / 8; - assert(access_sz > 0); - // Update its pt bytes - if (heap_region.update(access_sz)) - dereference_callback.update_regions(value); - expr2tc access_ptr; if (offset_bytes == 0) access_ptr = heap_region.start_loc; @@ -2262,6 +2281,9 @@ void dereferencet::valid_check( const guardt &guard, modet mode) { + log_status("entering valid check"); + object->dump(); + const expr2tc &symbol = get_symbol(object); if (is_constant_string2t(symbol)) @@ -2334,6 +2356,8 @@ void dereferencet::valid_check( } else if(is_heap_region2t(symbol)) { + log_status("guard : "); + guard.dump(); expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); log_status("not valid print:"); not_valid_heap_region->dump(); @@ -2529,26 +2553,78 @@ void dereferencet::check_heap_region_access( { // This check is in byte-level; log_status("check heap region access"); + guard.dump(); + log_status("offset"); + offset->dump(); assert(is_heap_region2t(value)); const heap_region2t& heap_region = to_heap_region2t(value); - unsigned int total_bytes = - to_constant_int2t(heap_region.pt_bytes).value.to_uint64() * - to_constant_int2t(heap_region.size).value.to_uint64(); - BigInt data_sz(total_bytes); - BigInt access_sz(type->get_width() / 8); - // offset / 8 - if (!is_constant_int2t(offset)) offset.simplify(); - assert(is_constant_int2t(offset)); - BigInt offset_sz(to_constant_int2t(offset).value.to_int64() / 8); + heap_region.pt_bytes->dump(); + heap_region.size->dump(); + + expr2tc offset_e = offset; + if (!is_constant_int2t(offset_e) && is_signedbv_type(offset_e)) + offset_e = offset_e.simplify(); + + std::string sz_id = dereference_callback.get_nondet_id("nondet_region_size::"); + expr2tc sz = symbol2tc(get_uint64_type(), sz_id); + expr2tc sz_pt = points_to2tc(heap_region.start_loc, sz); + expr2tc alloc_size_heap; + migrate_expr( + symbol_expr( + *ns.lookup(dereference_callback.get_alooc_size_heap_name())), + alloc_size_heap); + expr2tc heap_ct = heap_contains2tc(sz_pt, alloc_size_heap, 1); + + expr2tc data_sz = gen_ulong(type->get_width()); + expr2tc offset_check; + if (!is_constant_int2t(offset_e)) + { + // pointer arithmetic + if (is_add2t(offset_e) || is_sub2t(offset_e)) + { + expr2tc side_1 = is_add2t(offset_e) ? + to_add2t(offset_e).side_1 : to_sub2t(offset_e).side_1; + expr2tc side_2 = is_add2t(offset_e) ? + to_add2t(offset_e).side_2 : to_sub2t(offset_e).side_2; + + expr2tc ptr = is_pointer_type(side_1) ? side_1 : side_2; + expr2tc off = is_pointer_type(side_1) ? side_2 : side_1; + + if (!is_signedbv_type(off) && !is_unsignedbv_type(off)) + { + log_error("Do not support"); + abort(); + } + + std::string nondet_off_id = dereference_callback.get_nondet_id("nondet_off::"); + expr2tc off_var = symbol2tc(get_uint64_type(), nondet_off_id); - expr2tc data_sz_e = gen_long(offset->type, data_sz); - expr2tc access_sz_e = gen_long(offset->type, access_sz); - expr2tc offset_in_byte = gen_long(offset->type, offset_sz); + expr2tc target_loc = locadd2tc(heap_region.start_loc, off_var); + expr2tc offset_loc = locadd2tc(ptr, off_var); + expr2tc eq = equality2tc(target_loc, offset_loc); + expr2tc ge = greaterthanequal2tc(off_var, gen_ulong(0)); + expr2tc lt = lessthan2tc(off_var, sz); - expr2tc add = add2tc(access_sz_e->type, offset_in_byte, access_sz_e); - expr2tc gt = greaterthan2tc(add, data_sz_e); - expr2tc bound_check = gt; + offset_check = and2tc(eq, and2tc(ge, lt)); + } + else + { + log_error("Do not support"); + abort(); + } + } + else + { + expr2tc off_var = offset_e; + offset_check = + and2tc( + greaterthanequal2tc(off_var, gen_ulong(0)), + lessthan2tc(off_var, sz) + ); + } + + expr2tc bound_check = not2tc(and2tc(heap_ct, offset_check)); if(!options.get_bool_option("no-bounds-check")) { guardt tmp_guard = guard; diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index e803de47..840ceb52 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -173,6 +173,18 @@ class dereference_callbackt log_error("Do not support"); abort(); } + + virtual std::string get_nondet_id(std::string prefix = "") + { + log_error("Do not support"); + abort(); + } + + virtual irep_idt get_alooc_size_heap_name() + { + log_error("Do not support"); + abort(); + } }; /** Class containing expression dereference logic. diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index ec85ad51..5e76fc7a 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -574,7 +574,7 @@ void value_sett::get_value_set_rec( if (is_locadd2t(expr)) { const locadd2t& locadd = to_locadd2t(expr); - assert(is_intloc_type(locadd.base_addr)); + assert(is_intloc_type(locadd.loc)); abort(); // TODO } diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index b51323a1..29de3cf8 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -467,7 +467,9 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || is_pointer_type(sub.side_2)) { - a = convert_pointer_arith(expr, expr->type); + a = this->solver_text() == "Z3-slhv" ? + convert_slhv_opts(expr, args) : + convert_pointer_arith(expr, expr->type); } else if (int_encoding) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index c8f88f84..168a79ca 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -231,10 +231,10 @@ z3_slhv_convt::convert_slhv_opts( return h; } case expr2t::add_id: + case expr2t::sub_id: case expr2t::locadd_id: { assert(args.size() == 2); - log_status("here"); return mk_locadd(args[0], args[1]); } case expr2t::heap_append_id: @@ -277,19 +277,18 @@ z3_slhv_convt::convert_slhv_opts( { const heap_contains2t& heap_ct = to_heap_contains2t(expr); // TODO : fix width - assert(heap_ct.byte_len == 4); - smt_astt sh = mk_pt(args[1], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); - for (int i = 1; i < heap_ct.byte_len / 4; i++) { - sh = mk_uplus( - sh, - mk_pt( - mk_locadd(args[1], mk_smt_int(BigInt(i))), - // TODO: fix sort - mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")) - ) - ); + // assert(heap_ct.byte_len == 4); + smt_astt sh; + if (is_symbol2t(heap_ct.hterm) || is_pointer_with_region2t(heap_ct.hterm)) + { + sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); + // TODO : support multiple loaded + } + else if (is_points_to2t(heap_ct.hterm)) + { + sh = args[0]; } - return mk_subh(sh, args[0]); + return mk_subh(sh, args[1]); } case expr2t::heap_delete_id: { @@ -300,26 +299,11 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::same_object_id: { - // TODO: fix same object + // Do project for SLHV const same_object2t& same = to_same_object2t(expr); - if (is_heap_region2t(same.side_2)) - { - const heap_region2t& heap_region = to_heap_region2t(same.side_2); - assert(is_constant_int2t(heap_region.size)); - smt_astt start_loc = convert_ast(heap_region.start_loc); - smt_astt size = convert_ast(heap_region.size); - smt_astt nondet_offset = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - return - mk_and( - mk_eq(args[0], mk_locadd(start_loc, nondet_offset)), - mk_and( - mk_le(mk_smt_int(BigInt(0)), nondet_offset), - mk_lt(nondet_offset, size) - ) - ); - } - else if (is_heap_load2t(same.side_2)) - return mk_eq(args[0], args[1]); + smt_astt p1 = this->project(same.side_1); + smt_astt p2 = this->project(same.side_2); + return mk_eq(p1, p2); } default: { log_status("Invalid SLHV operations!!!"); @@ -328,6 +312,36 @@ z3_slhv_convt::convert_slhv_opts( } } +smt_astt z3_slhv_convt::project(const expr2tc &expr) +{ + if (is_pointer_with_region2t(expr)) + return convert_ast(expr); + else if (is_heap_region2t(expr)) + return convert_ast(to_heap_region2t(expr).start_loc); + else if (is_heap_load2t(expr)) + return convert_ast(to_heap_load2t(expr).flag); + else if (is_typecast2t(expr)) + return this->project(to_typecast2t(expr).from); + else if (is_locadd2t(expr) || is_add2t(expr) || is_sub2t(expr)) + { + expr2tc ptr; + if (is_locadd2t(expr)) + ptr = to_locadd2t(expr).loc; + else if (is_add2t(expr)) + ptr = is_pointer_type(to_add2t(expr).side_1) ? + to_add2t(expr).side_1 : to_add2t(expr).side_2; + else if (is_sub2t(expr)) + ptr = is_pointer_type(to_sub2t(expr).side_1) ? + to_sub2t(expr).side_1 : to_sub2t(expr).side_2; + return this->project(ptr); + } + else + { + log_error("Do not support"); + abort(); + } +} + void z3_slhv_convt::dump_smt() { const std::string &path = options.get_option("output"); if(path == "-") { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index d2b4d172..f24cb747 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -41,6 +41,7 @@ class z3_slhv_convt : public z3_convt { smt_sortt convert_slhv_sorts(const type2tc &type) override; smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; + smt_astt project(const expr2tc &expr); void dump_smt() override; diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 67d2ed77..dde32413 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2623,8 +2623,8 @@ exprt migrate_expr_back(const expr2tc &ref) const locadd2t &ref2 = to_locadd2t(ref); typet thetype = migrate_type_back(ref->type); exprt locadd("locadd", thetype); - locadd.copy_to_operands(migrate_expr_back(ref2.base_addr)); - locadd.copy_to_operands(migrate_expr_back(ref2.added_num)); + locadd.copy_to_operands(migrate_expr_back(ref2.loc)); + locadd.copy_to_operands(migrate_expr_back(ref2.offset)); return locadd; } case expr2t::heap_region_id: @@ -2695,8 +2695,8 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_contains2t &ref2 = to_heap_contains2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_contains("heap_contains", thetype); - heap_contains.copy_to_operands(migrate_expr_back(ref2.heapvar)); - heap_contains.copy_to_operands(migrate_expr_back(ref2.start_loc)); + heap_contains.copy_to_operands(migrate_expr_back(ref2.hterm)); + heap_contains.copy_to_operands(migrate_expr_back(ref2.heap)); heap_contains.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_contains; From 48ca98ef7dfb3ff01cdac3b78d62dd26e0017c5e Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 14 Aug 2024 16:14:30 +0800 Subject: [PATCH 042/126] fix: dereferencing emp --- src/goto-symex/builtin_functions.cpp | 2 +- src/goto-symex/goto_symex_state.cpp | 4 +- src/goto-symex/symex_assign.cpp | 2 +- src/goto-symex/symex_main.cpp | 2 +- src/irep2/irep2_expr.cpp | 16 ++++++++ src/irep2/irep2_expr.h | 41 +++++++++++-------- src/irep2/irep2_utils.h | 12 ++++-- src/irep2/templates/irep2_templates.cpp | 6 ++- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 25 +++++++---- src/solvers/smt/smt_conv.cpp | 2 + src/util/migrate.cpp | 2 - 12 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 1ec4c464..5c866e6d 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -489,7 +489,7 @@ void goto_symext::symex_free(const expr2tc &expr) if2tc(get_intheap_type(), item.guard, heap_region.flag, freed_heap); } - expr2tc emp_heap = constant_intheap2tc(get_intheap_type(), true); + expr2tc emp_heap = gen_emp(); log_status("symex free freed_heap emp_heap"); symex_assign(code_assign2tc(freed_heap, emp_heap)); expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index e7cf4946..ed66340a 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -255,7 +255,9 @@ void goto_symex_statet::rename(expr2tc &expr) if (is_pointer_with_region2t(expr) || is_heap_region2t(expr) || - is_heap_load2t(expr)) + is_heap_load2t(expr) || + is_constant_intheap2t(expr) || + is_constant_intloc2t(expr)) return; // Do not rename pwr if (is_nil_expr(expr)) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 1bf16420..7adb0a84 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -160,7 +160,7 @@ void goto_symext::symex_assign( allocsize_heap.type = typet(typet::t_intheap); new_context.add(allocsize_heap); expr2tc new_lhs = symbol2tc(get_intheap_type(), allocsize_heap.id); - expr2tc new_rhs = constant_intheap2tc(get_intheap_type(), true); + expr2tc new_rhs = gen_emp(); symex_assign(code_assign2tc(new_lhs, new_rhs)); } return; diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index ed5e704c..4cd0852f 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1217,7 +1217,7 @@ void goto_symext::add_memory_leak_checks() log_status("memleak encoding"); for (auto const &it : dynamic_memory){ log_status("allocated object {}: ", it.name ); - expr2tc deallocated = equality2tc(it.obj, constant_intheap2tc(get_intheap_type(), true)); + expr2tc deallocated = equality2tc(it.obj, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); cur_state->rename(cond); diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 050bbdcd..46064fba 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -259,6 +259,22 @@ long constant_int2t::as_long() const return value.to_int64(); } +unsigned long constant_intloc2t::as_ulong() const +{ + assert(!value.is_negative()); + return value.to_uint64(); +} + +bool constant_intloc2t::is_nil() const +{ + return this->as_ulong() == 0; +} + +bool constant_intheap2t::is_emp() const +{ + return is_nil_expr(value); +} + bool constant_bool2t::is_true() const { return value; diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 66ac77c1..df62fa9e 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -52,10 +52,9 @@ class constant_int_data : public constant2t class constant_intloc_data : public constant2t { - public: - constant_intloc_data(const type2tc &t, expr2t::expr_ids id, const BigInt &bint) - : constant2t(t, id), value(bint) + constant_intloc_data(const type2tc &t, expr2t::expr_ids id, const BigInt &value) + : constant2t(t, id), value(value) { } constant_intloc_data(const constant_intloc_data &ref) = default; @@ -72,21 +71,23 @@ class constant_intloc_data : public constant2t class constant_intheap_data : public constant2t { - public: - constant_intheap_data(const type2tc &t, expr2t::expr_ids id, const bool e) - : constant2t(t, id), is_emp(e) + constant_intheap_data( + const type2tc &t, + expr2t::expr_ids id, + const expr2tc &value) + : constant2t(t, id), value(value) { } constant_intheap_data(const constant_intheap_data &ref) = default; - bool is_emp; + expr2tc value; // Type mangling: typedef esbmct:: - field_traits - value_field; - typedef esbmct::expr2t_traits traits; + field_traits + constant_intheap_value_field; + typedef esbmct::expr2t_traits traits; }; @@ -1933,23 +1934,29 @@ class constant_int2t : public constant_int_expr_methods class constant_intloc2t : public constant_intloc_expr_methods { - public: - constant_intloc2t(const type2tc &type, const BigInt &input) - : constant_intloc_expr_methods(type, constant_intloc_id, input) +public: + constant_intloc2t(const BigInt &value) + : constant_intloc_expr_methods(get_intloc_type(), constant_intloc_id, value) { } + unsigned long as_ulong() const; + bool is_nil() const; + static std::string field_names[esbmct::num_type_fields]; }; class constant_intheap2t : public constant_intheap_expr_methods { - public: - constant_intheap2t(const type2tc &type, bool is_emp) - : constant_intheap_expr_methods(type, constant_intheap_id, is_emp) +public: + constant_intheap2t(const expr2tc &value) + : constant_intheap_expr_methods( + get_intheap_type(), constant_intheap_id, value) { } - bool get_is_emp() const; + + bool is_emp() const; + static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 5fc0eca7..83d61136 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -271,15 +271,19 @@ inline expr2tc gen_slong(signed long val) return constant_int2tc(get_int_type(config.ansi_c.word_size), BigInt(val)); } +inline expr2tc gen_intloc_constant(unsigned long val) +{ + return constant_intloc2tc(BigInt(val)); +} -inline expr2tc gen_emp() +inline expr2tc gen_nil() { - return constant_intheap2tc(get_intheap_type(), true); + return gen_intloc_constant(0); } -inline expr2tc gen_intloc_constant(unsigned long val) +inline expr2tc gen_emp() { - return constant_intloc2tc(get_intloc_type(), BigInt(val)); + return constant_intheap2tc(expr2tc()); } inline const type2tc &get_array_subtype(const type2tc &type) diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 1902b328..26b6e537 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -42,8 +42,10 @@ std::string cpp_name_type2t::field_names[esbmct::num_type_fields] = std::string constant_int2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; -std::string constant_intloc2t::field_names[esbmct::num_type_fields] = {"value" , "", "", "", ""}; -std::string constant_intheap2t::field_names[esbmct::num_type_fields] = {"is_emp" , "", "", "", ""}; +std::string constant_intloc2t::field_names[esbmct::num_type_fields] = + {"value" , "", "", "", ""}; +std::string constant_intheap2t::field_names[esbmct::num_type_fields] = + {"value" , "", "", "", ""}; std::string constant_fixedbv2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string constant_floatbv2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 66968ac0..407bb053 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -2,7 +2,7 @@ expr_typedefs1(constant_int, constant_int_data); expr_typedefs1(constant_intloc, constant_intloc_data); -expr_typedefs2(constant_intheap, constant_intheap_data); +expr_typedefs1(constant_intheap, constant_intheap_data); expr_typedefs1(constant_fixedbv, constant_fixedbv_data); expr_typedefs1(constant_floatbv, constant_floatbv_data); expr_typedefs1(constant_struct, constant_datatype_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index ea4e9260..9e75dd81 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -665,12 +665,23 @@ expr2tc dereferencet::build_reference_to( const expr2tc &root_object = o.get_root_object(); const expr2tc &object = o.object; - if (is_null_object2t(root_object) && !is_free(mode) && !is_internal(mode)) + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + + if ((is_constant_intheap2t(root_object) || is_null_object2t(root_object)) && + !is_free(mode) && !is_internal(mode)) { - type2tc nullptrtype = pointer_type2tc(type); - expr2tc null_ptr = symbol2tc(nullptrtype, "NULL"); - expr2tc pointer_guard = same_object2tc(deref_expr, null_ptr); + expr2tc pointer_guard; + if (use_old_encoding) + { + type2tc nullptrtype = pointer_type2tc(type); + expr2tc null_ptr = symbol2tc(nullptrtype, "NULL"); + pointer_guard = same_object2tc(deref_expr, null_ptr); + } + else + { + pointer_guard = same_object2tc(deref_expr, gen_nil()); + } guardt tmp_guard(guard); tmp_guard.add(pointer_guard); @@ -681,13 +692,13 @@ expr2tc dereferencet::build_reference_to( // solver will only get confused. return value; } - if (is_null_object2t(root_object) && (is_free(mode) || is_internal(mode))) + if ((is_constant_intheap2t(root_object) || is_null_object2t(root_object)) && + (is_free(mode) || is_internal(mode))) { // Freeing NULL is completely legit according to C return value; } - bool use_old_encoding = !options.get_bool_option("z3-slhv"); if(use_old_encoding) { value = object; @@ -966,7 +977,7 @@ void dereferencet::deref_invalid_ptr( if (use_old_encoding) null_ptr = symbol2tc(pointer_type2tc(get_empty_type()), "NULL"); else - null_ptr = gen_intloc_constant(0); + null_ptr = gen_nil(); expr2tc neq = notequal2tc(null_ptr, deref_expr); expr2tc and_ = and2tc(neq, invalid_pointer_expr); validity_test = and_; diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 29de3cf8..449f3844 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -301,6 +301,8 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::constant_array_id: case expr2t::constant_vector_id: case expr2t::constant_array_of_id: + case expr2t::constant_intloc_id: + case expr2t::constant_intheap_id: case expr2t::index_id: case expr2t::address_of_id: case expr2t::ieee_add_id: diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index dde32413..2db8d601 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2046,8 +2046,6 @@ exprt migrate_expr_back(const expr2tc &ref) const constant_intheap2t &ref2 = to_constant_intheap2t(ref); typet thetype = migrate_type_back(ref->type); constant_exprt theexpr(thetype); - bool is_emp = ref2.is_emp; - theexpr.set("is_emp", is_emp ? irep_idt("true") : irep_idt("false")); return theexpr; } case expr2t::constant_fixedbv_id: From e6c25f3212c0a51fc483534e0e69b1c209dd3779 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 14 Aug 2024 17:48:33 +0800 Subject: [PATCH 043/126] deref nil pointer --- src/goto-symex/goto_symex_state.cpp | 7 +++++++ src/pointer-analysis/dereference.cpp | 9 ++++++--- src/solvers/z3-slhv/z3_slhv_conv.cpp | 9 +++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index ed66340a..ed0dd9f8 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -267,6 +267,13 @@ void goto_symex_statet::rename(expr2tc &expr) if (is_symbol2t(expr)) { + if (to_symbol2t(expr).get_symbol_name() == std::string("NULL") && + (is_intheap_type(expr) || is_intloc_type(expr) || is_pointer_type(expr))) + { + expr = is_intheap_type(expr) ? gen_emp() : gen_nil(); + return; + } + type2tc origtype = expr->type; top().level1.rename(expr); level2.rename(expr); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 9e75dd81..70f43d3f 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -667,10 +667,11 @@ expr2tc dereferencet::build_reference_to( bool use_old_encoding = !options.get_bool_option("z3-slhv"); - if ((is_constant_intheap2t(root_object) || is_null_object2t(root_object)) && + if ((is_constant_intloc2t(object) || + is_constant_intheap2t(object) || + is_null_object2t(root_object)) && !is_free(mode) && !is_internal(mode)) { - expr2tc pointer_guard; if (use_old_encoding) { @@ -692,7 +693,9 @@ expr2tc dereferencet::build_reference_to( // solver will only get confused. return value; } - if ((is_constant_intheap2t(root_object) || is_null_object2t(root_object)) && + if ((is_constant_intloc2t(object) || + is_constant_intheap2t(object) || + is_null_object2t(root_object)) && (is_free(mode) || is_internal(mode))) { // Freeing NULL is completely legit according to C diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 168a79ca..ea8e0a4c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -279,7 +279,9 @@ z3_slhv_convt::convert_slhv_opts( // TODO : fix width // assert(heap_ct.byte_len == 4); smt_astt sh; - if (is_symbol2t(heap_ct.hterm) || is_pointer_with_region2t(heap_ct.hterm)) + if (is_symbol2t(heap_ct.hterm) || + is_pointer_with_region2t(heap_ct.hterm) || + is_pointer_object2t(heap_ct.hterm)) { sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); // TODO : support multiple loaded @@ -314,7 +316,10 @@ z3_slhv_convt::convert_slhv_opts( smt_astt z3_slhv_convt::project(const expr2tc &expr) { - if (is_pointer_with_region2t(expr)) + if (is_constant_intheap2t(expr) || + is_constant_intloc2t(expr)) + return convert_ast(expr); + else if (is_pointer_with_region2t(expr)) return convert_ast(expr); else if (is_heap_region2t(expr)) return convert_ast(to_heap_region2t(expr).start_loc); From d896720dff801a1341400cfd673e5ad5a0478f7f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 15 Aug 2024 16:26:32 +0800 Subject: [PATCH 044/126] fix: merge goto --- src/goto-symex/execution_state.cpp | 5 ++-- src/goto-symex/goto_symex.h | 6 ++++ src/goto-symex/goto_symex_state.cpp | 7 ----- src/goto-symex/symex_assign.cpp | 30 ++++++++++++++++++- src/goto-symex/symex_goto.cpp | 15 +++++++--- src/goto-symex/symex_main.cpp | 19 ++++++++++-- src/goto-symex/symex_other.cpp | 9 ++++++ src/irep2/irep2_expr.cpp | 2 +- src/irep2/irep2_expr.h | 22 ++++++++++---- src/irep2/irep2_utils.h | 4 +-- src/irep2/templates/irep2_templates.cpp | 4 +-- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 10 +++---- src/pointer-analysis/value_set.cpp | 5 ---- src/util/guard.cpp | 7 +++++ src/util/guard.h | 1 + src/util/simplify_expr2.cpp | 20 ++++++++++++- 17 files changed, 129 insertions(+), 39 deletions(-) diff --git a/src/goto-symex/execution_state.cpp b/src/goto-symex/execution_state.cpp index 83d40f2b..069b2c2d 100644 --- a/src/goto-symex/execution_state.cpp +++ b/src/goto-symex/execution_state.cpp @@ -201,8 +201,8 @@ void execution_statet::symex_step(reachability_treet &art) statet &state = get_active_state(); const goto_programt::instructiont &instruction = *state.source.pc; last_insn = &instruction; - // log_status("#### current symex_step instruction:"); - // instruction.dump(); + log_status("#### current symex_step instruction:"); + instruction.dump(); merge_gotos(); if (break_insn != 0 && break_insn == instruction.location_number) @@ -299,6 +299,7 @@ void execution_statet::symex_step(reachability_treet &art) analyze_assign(assign); } state.source.pc++; + log_status("done!!!"); break; default: goto_symext::symex_step(art); diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index eff701dc..ca256418 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -800,6 +800,12 @@ class goto_symext */ void replace_nondet(expr2tc &expr); + /** + * Replace NULL symbols to constant_intheap or constant_intloc + * @param expr Expr to search for NULL symbols. + */ + void replace_null(expr2tc &expr); + /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index ed0dd9f8..ed66340a 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -267,13 +267,6 @@ void goto_symex_statet::rename(expr2tc &expr) if (is_symbol2t(expr)) { - if (to_symbol2t(expr).get_symbol_name() == std::string("NULL") && - (is_intheap_type(expr) || is_intloc_type(expr) || is_pointer_type(expr))) - { - expr = is_intheap_type(expr) ? gen_emp() : gen_nil(); - return; - } - type2tc origtype = expr->type; top().level1.rename(expr); level2.rename(expr); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 7adb0a84..8daf08cf 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -141,6 +141,7 @@ void goto_symext::symex_assign( const code_assign2t &code = to_code_assign2t(code_assign); expr2tc assign_target = code.target; expr2tc assign_source = code.source; + bool use_old_encoding = !options.get_bool_option("z3-slhv"); if(!use_old_encoding) { if(is_symbol2t(assign_target) && @@ -166,7 +167,6 @@ void goto_symext::symex_assign( return; } } - code.dump(); // Sanity check: if the target has zero size, then we've ended up assigning // to/from either a C++ POD class with no fields or an empty C struct or // union. The rest of the model checker isn't rated for dealing with this @@ -184,6 +184,17 @@ void goto_symext::symex_assign( expr2tc original_lhs = code.target; expr2tc lhs = code.target; expr2tc rhs = code.source; + if (options.get_bool_option("z3-slhv")) + { + replace_null(lhs); + replace_null(rhs); + } + + log_status("symex assign lhs : ------------- "); + lhs->dump(); + log_status("symex assign rhs : ------------- "); + rhs->dump(); + replace_nondet(lhs); replace_nondet(rhs); @@ -912,4 +923,21 @@ void goto_symext::replace_nondet(expr2tc &expr) replace_nondet(e); }); } +} + +void goto_symext::replace_null(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + if (is_symbol2t(expr)) + { + if (to_symbol2t(expr).get_symbol_name() != "NULL") return; + expr = is_intheap_type(expr) ? gen_emp() : gen_nil(); + } + else + { + expr->Foreach_operand([this](expr2tc &e) { + if (!is_nil_expr(e)) + replace_null(e); + }); + } } \ No newline at end of file diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp index da9fa26e..91a27df6 100644 --- a/src/goto-symex/symex_goto.cpp +++ b/src/goto-symex/symex_goto.cpp @@ -20,6 +20,7 @@ void goto_symext::symex_goto(const expr2tc &old_guard) cur_state->rename(new_guard); do_simplify(new_guard); + log_status("new guard"); new_guard->dump(); bool new_guard_false = (is_false(new_guard) || cur_state->guard.is_false()); @@ -215,6 +216,10 @@ static inline guardt merge_state_guards( goto_symext::statet::goto_statet &goto_state, goto_symex_statet &state) { + log_status("{} - {} - {}", + !goto_state.guard.is_false(), + !state.guard.is_false(), + state.guard.disjunction_may_simplify(goto_state.guard)); // adjust guard, even using guards from unreachable states. This helps to // shrink the state guard if the incoming edge is from a path that was // truncated by config.unwind, config.depth or an assume-false instruction. @@ -231,8 +236,7 @@ static inline guardt merge_state_guards( (!goto_state.guard.is_false() && !state.guard.is_false()) || state.guard.disjunction_may_simplify(goto_state.guard)) { - state.guard |= goto_state.guard; - return state.guard; + return state.guard | goto_state.guard; } else if (state.guard.is_false() && !goto_state.guard.is_false()) { @@ -265,7 +269,8 @@ void goto_symext::merge_gotos() // Merge guards. Don't write this to `state` yet because we might move // goto_state over it below. - guardt new_guard = merge_state_guards(goto_state, *cur_state); + // guardt new_guard = merge_state_guards(goto_state, *cur_state); + if (!goto_state.guard.is_false()) { @@ -281,7 +286,7 @@ void goto_symext::merge_gotos() std::min(cur_state->num_instructions, goto_state.num_instructions); } - cur_state->guard = std::move(new_guard); + cur_state->guard = merge_state_guards(goto_state, *cur_state); } // clean up to save some memory @@ -302,8 +307,10 @@ void goto_symext::merge_locality(const statet::goto_statet &src) void goto_symext::merge_value_sets(const statet::goto_statet &src) { + log_status("merge value set {}", cur_state->guard.is_false()); if (cur_state->guard.is_false()) { + log_status("just replace"); cur_state->value_set = src.value_set; return; } diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 4cd0852f..881e1bf5 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -180,10 +180,18 @@ void goto_symext::symex_step(reachability_treet &art) { log_status(" ======= goto symex: GOTO"); expr2tc tmp(instruction.guard); + if (options.get_bool_option("z3-slhv")) + replace_null(tmp); replace_nondet(tmp); + tmp->dump(); + dereference(tmp, dereferencet::READ); + log_status("after deref"); + tmp->dump(); replace_dynamic_allocation(tmp); + log_status("after replace dynamic"); + tmp->dump(); symex_goto(tmp); } @@ -211,6 +219,8 @@ void goto_symext::symex_step(reachability_treet &art) goto_symext::symex_assign(assign); } + if (options.get_bool_option("z3-slhv")) + replace_null(thecode); symex_return(thecode); } @@ -333,6 +343,7 @@ void goto_symext::symex_step(reachability_treet &art) case OTHER: log_status(" ======= goto symex: OTHER"); + log_status("guard - {}", !cur_state->guard.is_false()); if (!cur_state->guard.is_false()) symex_other(instruction.code); cur_state->source.pc++; @@ -383,7 +394,7 @@ void goto_symext::symex_step(reachability_treet &art) fmt::underlying(instruction.type)); abort(); } - + log_status("finish this step"); } void goto_symext::symex_assume() @@ -392,7 +403,9 @@ void goto_symext::symex_assume() return; expr2tc cond = cur_state->source.pc->guard; - + + if (options.get_bool_option("z3-slhv")) + replace_null(cond); replace_nondet(cond); dereference(cond, dereferencet::READ); replace_dynamic_allocation(cond); @@ -417,6 +430,8 @@ void goto_symext::symex_assert() const goto_programt::instructiont &instruction = *cur_state->source.pc; expr2tc tmp = instruction.guard; + if (options.get_bool_option("z3-slhv")) + replace_null(tmp); replace_nondet(tmp); intrinsic_races_check_dereference(tmp); diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index de306124..cdaba808 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -7,6 +7,11 @@ void goto_symext::symex_other(const expr2tc code) { expr2tc code2 = code; + if (options.get_bool_option("z3-slhv")) + replace_null(code2); + + code2->dump(); + if (is_code_expression2t(code2)) { // Represents an expression that gets evaluated, but does not have any @@ -50,6 +55,8 @@ void goto_symext::symex_decl(const expr2tc code) assert(is_code_decl2t(code)); code->dump(); expr2tc code2 = code; + if (options.get_bool_option("z3-slhv")) + replace_null(code2); replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::READ); @@ -109,6 +116,8 @@ void goto_symext::symex_dead(const expr2tc code) assert(is_code_dead2t(code)); expr2tc code2 = code; + if (options.get_bool_option("z3-slhv")) + replace_null(code2); replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::INTERNAL); diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 46064fba..01a094bd 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -267,7 +267,7 @@ unsigned long constant_intloc2t::as_ulong() const bool constant_intloc2t::is_nil() const { - return this->as_ulong() == 0; + return is_nil_loc; } bool constant_intheap2t::is_emp() const diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index df62fa9e..5432f06a 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -53,19 +53,29 @@ class constant_int_data : public constant2t class constant_intloc_data : public constant2t { public: - constant_intloc_data(const type2tc &t, expr2t::expr_ids id, const BigInt &value) - : constant2t(t, id), value(value) + constant_intloc_data( + const type2tc &t, + expr2t::expr_ids id, + const BigInt &value, + bool is_nil_loc) + : constant2t(t, id), value(value), is_nil_loc(is_nil_loc) { } constant_intloc_data(const constant_intloc_data &ref) = default; BigInt value; + bool is_nil_loc; // Type mangling: typedef esbmct:: field_traits - value_field; - typedef esbmct::expr2t_traits traits; + constant_intloc_data_value_field; + typedef esbmct:: + field_traits + constant_intloc_data_is_nil_loc_field; + typedef esbmct::expr2t_traits< + constant_intloc_data_value_field, + constant_intloc_data_is_nil_loc_field> traits; }; @@ -1935,8 +1945,8 @@ class constant_int2t : public constant_int_expr_methods class constant_intloc2t : public constant_intloc_expr_methods { public: - constant_intloc2t(const BigInt &value) - : constant_intloc_expr_methods(get_intloc_type(), constant_intloc_id, value) + constant_intloc2t(const BigInt &value, bool is_nil_loc) + : constant_intloc_expr_methods(get_intloc_type(), constant_intloc_id, value, is_nil_loc) { } diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 83d61136..1dd6097a 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -273,12 +273,12 @@ inline expr2tc gen_slong(signed long val) inline expr2tc gen_intloc_constant(unsigned long val) { - return constant_intloc2tc(BigInt(val)); + return constant_intloc2tc(BigInt(val), false); } inline expr2tc gen_nil() { - return gen_intloc_constant(0); + return constant_intloc2tc(BigInt(0), true); } inline expr2tc gen_emp() diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 26b6e537..1095a233 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -43,9 +43,9 @@ std::string cpp_name_type2t::field_names[esbmct::num_type_fields] = std::string constant_int2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string constant_intloc2t::field_names[esbmct::num_type_fields] = - {"value" , "", "", "", ""}; + {"value", "is_nil", "", "", ""}; std::string constant_intheap2t::field_names[esbmct::num_type_fields] = - {"value" , "", "", "", ""}; + {"value", "", "", "", ""}; std::string constant_fixedbv2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string constant_floatbv2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 407bb053..db08406b 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -1,7 +1,7 @@ #include expr_typedefs1(constant_int, constant_int_data); -expr_typedefs1(constant_intloc, constant_intloc_data); +expr_typedefs2(constant_intloc, constant_intloc_data); expr_typedefs1(constant_intheap, constant_intheap_data); expr_typedefs1(constant_fixedbv, constant_fixedbv_data); expr_typedefs1(constant_floatbv, constant_floatbv_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 70f43d3f..ca55e142 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -465,7 +465,7 @@ expr2tc dereferencet::dereference( modet mode, const expr2tc &lexical_offset) { - log_status("dereferencing pointer ---------"); + log_status("--------------- dereferencing pointer ---------"); orig_src->dump(); internal_items.clear(); @@ -521,6 +521,9 @@ expr2tc dereferencet::dereference( if (is_nil_expr(new_value)) continue; + + log_status("after building reference to : not nill"); + new_value->dump(); assert(!is_nil_expr(pointer_guard)); @@ -826,10 +829,7 @@ expr2tc dereferencet::build_reference_to( if (heap_region.update(access_sz)) dereference_callback.update_regions(value); - if (is_free(mode)) - pointer_guard = equality2tc(deref_expr, to_heap_region2t(object).start_loc); - else - pointer_guard = same_object2tc(deref_expr, object); + pointer_guard = same_object2tc(deref_expr, object); tmp_guard.add(pointer_guard); } else diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 5e76fc7a..7c9c7d3d 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -1210,11 +1210,6 @@ void value_sett::assign( // basic type object_mapt values_rhs; get_value_set(rhs, values_rhs); - log_status("get values rhs"); - for(auto& p : values_rhs) - { - object_numbering[p.first]->dump(); - } assign_rec(lhs, values_rhs, "", add_to_sets); } diff --git a/src/util/guard.cpp b/src/util/guard.cpp index 06e7b327..961abdd6 100644 --- a/src/util/guard.cpp +++ b/src/util/guard.cpp @@ -206,6 +206,13 @@ guardt &operator|=(guardt &g1, const guardt &g2) return g1; } +guardt operator|(const guardt &g1, const guardt &g2) +{ + guardt new_g = g1; + new_g |= g2; + return new_g; +} + void guardt::dump() const { for (auto const &it : guard_list) diff --git a/src/util/guard.h b/src/util/guard.h index fd822693..755ebaf7 100644 --- a/src/util/guard.h +++ b/src/util/guard.h @@ -29,6 +29,7 @@ class guardt friend guardt &operator-=(guardt &g1, const guardt &g2); friend guardt &operator|=(guardt &g1, const guardt &g2); + friend guardt operator|(const guardt &g1, const guardt &g2); friend bool operator==(const guardt &g1, const guardt &g2); void dump() const; diff --git a/src/util/simplify_expr2.cpp b/src/util/simplify_expr2.cpp index 1b92bff3..2e80881f 100644 --- a/src/util/simplify_expr2.cpp +++ b/src/util/simplify_expr2.cpp @@ -1602,7 +1602,8 @@ expr2tc bitcast2t::do_simplify() const expr2tc typecast2t::do_simplify() const { // Follow approach of old irep, i.e., copy it - if (type == from->type) + if (type == from->type || + (is_intloc_type(from->type) && is_pointer_type(type))) { // Typecast to same type means this can be eliminated entirely return from; @@ -1858,6 +1859,23 @@ static expr2tc simplify_relations( const expr2tc &side_1, const expr2tc &side_2) { + // SLHV constant simply + + if (is_constant_intloc2t(side_1) && is_constant_intloc2t(side_2)) + { + if (to_constant_intloc2t(side_1).as_ulong() != to_constant_intloc2t(side_2).as_ulong()) + return gen_true_expr(); + else + return gen_false_expr(); // Fix + } + if (is_constant_intheap2t(side_1) && is_constant_intheap2t(side_2)) + { + if (to_constant_intheap2t(side_1).is_emp() && to_constant_intheap2t(side_2).is_emp()) + return gen_false_expr(); + else + return gen_true_expr(); // Fix + } + if (!is_number_type(type)) return expr2tc(); From d7ae1d6515925447598d72e7cfb81605814ada30 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Thu, 15 Aug 2024 18:22:29 +0800 Subject: [PATCH 045/126] for merge --- benchmark/case_0.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index e71e3e4b..62007687 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -1,9 +1,41 @@ #include + +// typedef struct { +// int data; +// int* next; +// } node_t; +typedef struct { + void* lo; + void* hi; +} TData; int main(){ + // node_t node; + // node.data = 10; + // node.next = malloc(sizeof(int)); + // node_t* t = (node_t*)malloc(sizeof(node_t)); + // t->data = 10; // int whatever; - int * data = malloc(2 * sizeof(int)); - int * data2 = malloc(2 * sizeof(int)); - free(data2); - int i = *(data2 + 1); + // int * data = malloc(sizeof(int)); + // int * data2 = malloc(2*sizeof(int)); + // free(data); + // int i = *(data); + // int* j = NULL; + // int* i = j; + // // *(data + 1) = whatever; + // int n = *(data+1); + // if(i > 0) { + // free(data); + // } + TData *p1 = malloc(sizeof(TData)); + p1->lo = malloc(12); + p1->hi = malloc(12); + void *p2; + int x; + if(x) { + p2 = p1->hi; + } else { + p2 = p1->lo; + } + free(p2); } From cc48b7ef864b29c5a10ba06c5c1758adcbe61130 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 15 Aug 2024 22:52:28 +0800 Subject: [PATCH 046/126] fix: splitting region --- src/esbmc/bmc.cpp | 8 +++++-- src/goto-symex/builtin_functions.cpp | 2 +- src/goto-symex/goto_symex.h | 2 +- src/goto-symex/goto_symex_state.cpp | 22 +++++++++++++----- src/goto-symex/goto_symex_state.h | 2 ++ src/goto-symex/symex_assign.cpp | 31 ++++++++++++++++--------- src/goto-symex/symex_goto.cpp | 4 ---- src/goto-symex/symex_main.cpp | 6 ----- src/irep2/irep2_utils.h | 15 ++++++++++++ src/pointer-analysis/dereference.cpp | 34 +++++++++++++++++++++------- src/solvers/smt/smt_conv.cpp | 1 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 9 ++++---- src/util/type.cpp | 1 + 13 files changed, 93 insertions(+), 44 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 9a23c51c..9b26bd68 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -168,7 +168,6 @@ void bmct::generate_smt_from_equation( smt_convt::resultt bmct::run_decision_procedure(smt_convt &smt_conv, symex_target_equationt &eq) { - log_status("run decision procedure"); generate_smt_from_equation(smt_conv, eq); if ( @@ -785,10 +784,13 @@ smt_convt::resultt bmct::multi_property_check( reached_mul_claims.emplace(cmt_loc); if (is_verified && !options.get_bool_option("keep-verified-claims")) return; + + if (i != 5) return; // Slice symex_slicet slicer(options); - slicer.run(local_eq.SSA_steps); + if (!options.get_bool_option("no-slice")) + slicer.run(local_eq.SSA_steps); show_vcc(local_eq); @@ -807,6 +809,8 @@ smt_convt::resultt bmct::multi_property_check( fine_timet sat_stop = current_time(); log_status( "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); + + log_status("Result : {}", (result == smt_convt::P_SATISFIABLE)); // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 5c866e6d..42832c7b 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -338,7 +338,7 @@ expr2tc goto_symext::symex_mem( if (is_heap_load2t(lhs)) { guardt g; - symex_assign_heap_laod(lhs, lhs, pwr, pwr, g, false); + symex_assign_heap_load(lhs, lhs, pwr, pwr, g, false); } return expr2tc(); } diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index ca256418..d35657ca 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -757,7 +757,7 @@ class goto_symext * @param rhs Value to assign to lhs * @param guard Assignment guard. */ - void symex_assign_heap_laod( + void symex_assign_heap_load( const expr2tc &lhs, const expr2tc &full_lhs, expr2tc &rhs, diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index ed66340a..ad669403 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -253,12 +253,12 @@ void goto_symex_statet::rename(expr2tc &expr) { // rename all the symbols with their last known value - if (is_pointer_with_region2t(expr) || - is_heap_region2t(expr) || - is_heap_load2t(expr) || - is_constant_intheap2t(expr) || - is_constant_intloc2t(expr)) - return; // Do not rename pwr + if (is_slhv_expr(expr)) + { + return; + rename_slhv_expr(expr); + return; + } if (is_nil_expr(expr)) return; @@ -284,6 +284,16 @@ void goto_symex_statet::rename(expr2tc &expr) } } +void goto_symex_statet::rename_slhv_expr(expr2tc &expr) +{ + if (is_constant_intheap2t(expr) || + is_constant_intloc2t(expr) || + is_heap_region2t(expr) || + is_pointer_with_region2t(expr)) + return; + expr->Foreach_operand([this](expr2tc &e) { rename(e); }); +} + void goto_symex_statet::rename_address(expr2tc &expr) { // rename all the symbols with their last known value diff --git a/src/goto-symex/goto_symex_state.h b/src/goto-symex/goto_symex_state.h index 5f794654..c43ef1f1 100644 --- a/src/goto-symex/goto_symex_state.h +++ b/src/goto-symex/goto_symex_state.h @@ -346,6 +346,8 @@ class goto_symex_statet */ void rename(expr2tc &expr); + void rename_slhv_expr(expr2tc &expr); + void rename_type(expr2tc &expr); /** diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 8daf08cf..1fe620d7 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -344,7 +344,7 @@ void goto_symext::symex_assign_rec( else if (is_heap_load2t(lhs)) { log_status("symex_assign_heap_load"); - symex_assign_heap_laod(lhs, full_lhs, rhs, full_rhs, guard, hidden); + symex_assign_heap_load(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_heap_region2t(lhs)) { @@ -365,6 +365,11 @@ void goto_symext::symex_assign_symbol( guardt &guard, const bool hidden) { + log_status("lhs:"); + lhs->dump(); + log_status("rhs:"); + rhs->dump(); + // put assignment guard in rhs if (!guard.is_true()) rhs = if2tc(rhs->type, guard.as_expr(), rhs, lhs); @@ -379,11 +384,13 @@ void goto_symext::symex_assign_symbol( } expr2tc renamed_lhs = lhs; - log_status("ranamed lhs: "); + cur_state->rename_type(renamed_lhs); + + log_status("renamed lhs:"); renamed_lhs->dump(); - log_status("renamed rhs: "); + log_status("renamed rhs:"); rhs->dump(); - cur_state->rename_type(renamed_lhs); + cur_state->assignment(renamed_lhs, rhs); // Special case when the lhs is an array access, we need to get the @@ -884,7 +891,7 @@ void goto_symext::symex_assign_bitfield( return symex_assign_rec(val, full_lhs, new_rhs, full_rhs, guard, hidden); } -void goto_symext::symex_assign_heap_laod( +void goto_symext::symex_assign_heap_load( const expr2tc &lhs, const expr2tc &full_lhs, expr2tc &rhs, @@ -897,14 +904,16 @@ void goto_symext::symex_assign_heap_laod( const heap_load2t& heap_load = to_heap_load2t(lhs); // assert(heap_load.byte_len * 8 == rhs->type->get_width()); - // Pin one set of rhs version numbers: if we assign part of a value to itself, - // it'll change during the assignment - cur_state->rename(rhs); // shall we? + symex_assign_rec(heap_load.flag, heap_load.flag, rhs, full_rhs, guard, hidden); - expr2tc ptr_obj = pointer_object2tc(get_intloc_type(), heap_load.start_loc); - expr2tc updated_heap = heap_update2tc(heap_load.heap, ptr_obj, rhs, heap_load.byte_len); + expr2tc updated_heap = + heap_update2tc( + heap_load.heap, + heap_load.start_loc, + heap_load.flag, + heap_load.byte_len); - symex_assign(code_assign2tc(heap_load.heap, updated_heap), true); + symex_assign_rec(heap_load.heap, heap_load.heap, updated_heap, updated_heap, guard, hidden); } void goto_symext::replace_nondet(expr2tc &expr) diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp index 91a27df6..3e5644b8 100644 --- a/src/goto-symex/symex_goto.cpp +++ b/src/goto-symex/symex_goto.cpp @@ -216,10 +216,6 @@ static inline guardt merge_state_guards( goto_symext::statet::goto_statet &goto_state, goto_symex_statet &state) { - log_status("{} - {} - {}", - !goto_state.guard.is_false(), - !state.guard.is_false(), - state.guard.disjunction_may_simplify(goto_state.guard)); // adjust guard, even using guards from unreachable states. This helps to // shrink the state guard if the incoming edge is from a path that was // truncated by config.unwind, config.depth or an assume-false instruction. diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 881e1bf5..2a304bb3 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -184,14 +184,8 @@ void goto_symext::symex_step(reachability_treet &art) replace_null(tmp); replace_nondet(tmp); - tmp->dump(); - dereference(tmp, dereferencet::READ); - log_status("after deref"); - tmp->dump(); replace_dynamic_allocation(tmp); - log_status("after replace dynamic"); - tmp->dump(); symex_goto(tmp); } diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 1dd6097a..89a4fd7e 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -189,6 +189,21 @@ inline bool is_comp_expr(const expr2tc &expr) expr->expr_id == expr2t::notequal_id; } +inline bool is_slhv_expr(const expr2tc &expr) +{ + return is_constant_intheap2t(expr) || + is_constant_intloc2t(expr) || + is_points_to2t(expr) || + is_locadd2t(expr) || + is_pointer_with_region2t(expr) || + is_heap_append2t(expr) || + is_heap_contains2t(expr) || + is_heap_delete2t(expr) || + is_heap_load2t(expr) || + is_heap_region2t(expr) || + is_heap_update2t(expr); +} + /** Test if expr is true. First checks whether the expr is a constant bool, and * then whether it's true-valued. If these are both true, return true, * otherwise return false. diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index ca55e142..c3e0e1f9 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -819,15 +819,20 @@ expr2tc dereferencet::build_reference_to( log_status("befor building pointer guard"); object->dump(); deref_expr->dump(); + type->dump(); guardt tmp_guard(guard); if (is_heap_region2t(object)) { heap_region2t& heap_region = to_heap_region2t(value); - int access_sz = type->get_width() / 8; - // Update its pt bytes - if (heap_region.update(access_sz)) - dereference_callback.update_regions(value); + + if (!is_free(mode) && !is_internal(mode)) + { + int access_sz = type_byte_size(type).to_uint64(); + // Update its pt bytes + if (heap_region.update(access_sz)) + dereference_callback.update_regions(value); + } pointer_guard = same_object2tc(deref_expr, object); tmp_guard.add(pointer_guard); @@ -1280,7 +1285,7 @@ void dereferencet::build_reference_slhv( heap_region2t& heap_region = to_heap_region2t(value); expr2tc heap = heap_region.flag; - int access_sz = type->get_width() / 8; + int access_sz = type_byte_size(type).to_uint64(); expr2tc access_ptr; if (offset_bytes == 0) access_ptr = heap_region.start_loc; @@ -1296,9 +1301,22 @@ void dereferencet::build_reference_slhv( } std::string flag_id = - std::string("nondet_loaded::") + - dereference_callback.get_loaded_value_flag(access_ptr); - expr2tc flag = symbol2tc(type, flag_id); + dereference_callback.get_loaded_value_flag(access_ptr) + + std::string("::loaded::"); + + symbolt symbol; + symbol.name = flag_id; + symbol.id = "heap_load::" + id2string(symbol.name); + symbol.lvalue = true; + symbol.type = + (is_pointer_type(type) || is_intloc_type(type)) ? + typet(typet::t_intloc) : typet(typet::t_integer); + + symbol.mode = "C"; + log_status("new_context.add(symbol);"); + new_context.add(symbol); + + expr2tc flag = symbol2tc(type, symbol.id); value = heap_load2tc(type, flag, heap, access_ptr, access_sz); } else { diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 449f3844..87595003 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -248,6 +248,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) smt_cachet::const_iterator cache_result = smt_cache.find(expr); if (cache_result != smt_cache.end()) { log_status("found!!!!!!!!"); + cache_result->ast->dump(); return (cache_result->ast); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index ea8e0a4c..182d2a3b 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -316,8 +316,7 @@ z3_slhv_convt::convert_slhv_opts( smt_astt z3_slhv_convt::project(const expr2tc &expr) { - if (is_constant_intheap2t(expr) || - is_constant_intloc2t(expr)) + if (is_constant_intheap2t(expr) || is_constant_intloc2t(expr)) return convert_ast(expr); else if (is_pointer_with_region2t(expr)) return convert_ast(expr); @@ -333,16 +332,16 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) if (is_locadd2t(expr)) ptr = to_locadd2t(expr).loc; else if (is_add2t(expr)) - ptr = is_pointer_type(to_add2t(expr).side_1) ? + ptr = (is_pointer_type(to_add2t(expr).side_1) || is_intloc_type(to_add2t(expr).side_1))? to_add2t(expr).side_1 : to_add2t(expr).side_2; else if (is_sub2t(expr)) - ptr = is_pointer_type(to_sub2t(expr).side_1) ? + ptr = (is_pointer_type(to_sub2t(expr).side_1) || is_intloc_type(to_sub2t(expr).side_1))? to_sub2t(expr).side_1 : to_sub2t(expr).side_2; return this->project(ptr); } else { - log_error("Do not support"); + expr->dump(); abort(); } } diff --git a/src/util/type.cpp b/src/util/type.cpp index 15e559b2..60178c7a 100644 --- a/src/util/type.cpp +++ b/src/util/type.cpp @@ -19,6 +19,7 @@ bool is_array_like(const typet &type) return type.is_vector() || type.is_array() || type.is_incomplete_array(); } +irep_idt typet::t_integer = dstring("integer"); irep_idt typet::t_signedbv = dstring("signedbv"); irep_idt typet::t_unsignedbv = dstring("unsignedbv"); irep_idt typet::t_complex = dstring("complex"); From b35cc69442f2a96a73c80117c8bec6aebc3ee600 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 16 Aug 2024 10:56:13 +0800 Subject: [PATCH 047/126] fix rename --- src/esbmc/bmc.cpp | 2 -- src/goto-symex/builtin_functions.cpp | 2 ++ src/goto-symex/goto_symex_state.cpp | 43 +++++++++++++++------------- src/goto-symex/goto_symex_state.h | 2 -- src/pointer-analysis/dereference.cpp | 5 ++-- src/solvers/smt/smt_conv.cpp | 1 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 15 ++++++---- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 9b26bd68..6ba86f0b 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -784,8 +784,6 @@ smt_convt::resultt bmct::multi_property_check( reached_mul_claims.emplace(cmt_loc); if (is_verified && !options.get_bool_option("keep-verified-claims")) return; - - if (i != 5) return; // Slice symex_slicet slicer(options); diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 42832c7b..224b8622 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -318,6 +318,7 @@ expr2tc goto_symext::symex_mem( symex_assign(code_assign2tc(rhs_heap, rhs_region)); log_status("create valueset base addr symbol and assign"); + cur_state->rename(rhs_base_addr); expr2tc pwr = pointer_with_region2tc(rhs_base_addr, rhs_heap); symex_assign(code_assign2tc(lhs_flag, pwr)); @@ -328,6 +329,7 @@ expr2tc goto_symext::symex_mem( ptr_obj, get_intheap_type(), gen_ulong(total_bytes)); + cur_state->rename(rhs_heap); dynamic_memory.emplace_back( rhs_heap, rhs_guard, diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index ad669403..72a90070 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -67,9 +67,9 @@ void goto_symex_statet::initialize( bool goto_symex_statet::constant_propagation(const expr2tc &expr) const { // SLHV propagation - if (is_heap_region2t(expr) || is_pointer_with_region2t(expr) || - is_constant_intheap2t(expr) || is_constant_intloc2t(expr) || - is_heap_load2t(expr)) + if (is_pointer_with_region2t(expr) || + is_constant_intheap2t(expr) || + is_constant_intloc2t(expr)) return true; if (is_locadd2t(expr)) { @@ -252,14 +252,6 @@ void goto_symex_statet::rename_type(expr2tc &expr) void goto_symex_statet::rename(expr2tc &expr) { // rename all the symbols with their last known value - - if (is_slhv_expr(expr)) - { - return; - rename_slhv_expr(expr); - return; - } - if (is_nil_expr(expr)) return; @@ -282,16 +274,27 @@ void goto_symex_statet::rename(expr2tc &expr) // do this recursively expr->Foreach_operand([this](expr2tc &e) { rename(e); }); } -} -void goto_symex_statet::rename_slhv_expr(expr2tc &expr) -{ - if (is_constant_intheap2t(expr) || - is_constant_intloc2t(expr) || - is_heap_region2t(expr) || - is_pointer_with_region2t(expr)) - return; - expr->Foreach_operand([this](expr2tc &e) { rename(e); }); + if (is_pointer_with_region2t(expr)) + { + pointer_with_region2t &pwr = to_pointer_with_region2t(expr); + if (is_pointer_with_region2t(pwr.loc_ptr)) + pwr.loc_ptr = to_pointer_with_region2t(pwr.loc_ptr).loc_ptr; + } + + if (is_heap_region2t(expr)) + { + heap_region2t &hr = to_heap_region2t(expr); + if (is_pointer_with_region2t(hr.start_loc)) + hr.start_loc = to_pointer_with_region2t(hr.start_loc).loc_ptr; + } + + if (is_heap_load2t(expr)) + { + heap_load2t &hl = to_heap_load2t(expr); + if (is_pointer_with_region2t(hl.flag)) + hl.flag = to_pointer_with_region2t(hl.flag).loc_ptr; + } } void goto_symex_statet::rename_address(expr2tc &expr) diff --git a/src/goto-symex/goto_symex_state.h b/src/goto-symex/goto_symex_state.h index c43ef1f1..5f794654 100644 --- a/src/goto-symex/goto_symex_state.h +++ b/src/goto-symex/goto_symex_state.h @@ -346,8 +346,6 @@ class goto_symex_statet */ void rename(expr2tc &expr); - void rename_slhv_expr(expr2tc &expr); - void rename_type(expr2tc &expr); /** diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index c3e0e1f9..c1acfec8 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1291,9 +1291,8 @@ void dereferencet::build_reference_slhv( access_ptr = heap_region.start_loc; else { - int offset_pt = offset_bytes / 8; - assert(offset_pt % access_sz == 0); - offset_pt /= access_sz; + assert(offset_bytes % access_sz == 0); + int offset_pt = offset_bytes / access_sz; access_ptr = locadd2tc( heap_region.start_loc, gen_long(get_int64_type(), offset_pt) diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 87595003..a2d56bfb 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -331,6 +331,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) } } + log_status("begin convert expr"); expr->dump(); smt_astt a; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 182d2a3b..c6fd2c23 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -316,7 +316,9 @@ z3_slhv_convt::convert_slhv_opts( smt_astt z3_slhv_convt::project(const expr2tc &expr) { - if (is_constant_intheap2t(expr) || is_constant_intloc2t(expr)) + if (is_symbol2t(expr) || + is_constant_intheap2t(expr) || + is_constant_intloc2t(expr)) return convert_ast(expr); else if (is_pointer_with_region2t(expr)) return convert_ast(expr); @@ -339,11 +341,12 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) to_sub2t(expr).side_1 : to_sub2t(expr).side_2; return this->project(ptr); } - else - { - expr->dump(); - abort(); - } +else +{ + log_error("Do not support project"); + expr->dump(); + abort(); +} } void z3_slhv_convt::dump_smt() { From 0d7f6350c69950d67179ecb466152797c3987d29 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 16 Aug 2024 11:09:00 +0800 Subject: [PATCH 048/126] change output stdout --- src/util/message.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/message.h b/src/util/message.h index 5cf0d7db..977aa364 100644 --- a/src/util/message.h +++ b/src/util/message.h @@ -75,7 +75,7 @@ struct messaget (void)file; (void)line; } - } state = {VerbosityLevel::Status, {}, stderr}; + } state = {VerbosityLevel::Status, {}, stdout}; }; #define log_error(fmt, ...) \ From fbd6603689b860069898e4788694f208e5d84659 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 19 Aug 2024 19:07:55 +0800 Subject: [PATCH 049/126] turn all form of pointer arithmetic to locadd --- benchmark/case_0.c | 34 +---- src/goto-symex/builtin_functions.cpp | 54 ++++---- src/goto-symex/goto_symex.h | 6 + src/goto-symex/goto_symex_state.cpp | 7 - src/goto-symex/symex_assign.cpp | 68 +++++++++- src/goto-symex/symex_target_equation.cpp | 125 ------------------ src/goto-symex/symex_target_equation.h | 8 -- src/irep2/irep2_expr.cpp | 29 ++++ src/irep2/irep2_expr.h | 22 ++- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 22 +-- src/pointer-analysis/value_set.cpp | 26 +++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 12 +- src/util/migrate.cpp | 2 - 15 files changed, 172 insertions(+), 247 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index 62007687..ebc269a0 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -1,25 +1,10 @@ #include - -// typedef struct { -// int data; -// int* next; -// } node_t; -typedef struct { - void* lo; - void* hi; -} TData; int main(){ - // node_t node; - // node.data = 10; - // node.next = malloc(sizeof(int)); - // node_t* t = (node_t*)malloc(sizeof(node_t)); - // t->data = 10; - // int whatever; - // int * data = malloc(sizeof(int)); - // int * data2 = malloc(2*sizeof(int)); - // free(data); - // int i = *(data); + int * data = malloc(sizeof(int)); + int * data2 = malloc(2*sizeof(int)); + free(data2); + int i = *(data + 1); // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; @@ -27,15 +12,4 @@ int main(){ // if(i > 0) { // free(data); // } - TData *p1 = malloc(sizeof(TData)); - p1->lo = malloc(12); - p1->hi = malloc(12); - void *p2; - int x; - if(x) { - p2 = p1->hi; - } else { - p2 = p1->lo; - } - free(p2); } diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 224b8622..463284fa 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -284,52 +284,45 @@ expr2tc goto_symext::symex_mem( symbol.type.dynamic(true); symbol.mode = "C"; - log_status("new_context.add(symbol);"); new_context.add(symbol); - expr2tc lhs_flag; - if (is_symbol2t(lhs)) - lhs_flag = lhs; - else if (is_heap_load2t(lhs)) - lhs_flag = to_heap_load2t(lhs).flag; - else - { - log_error("Do not support this expr"); - abort(); - } - expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); guardt rhs_guard = cur_state->guard; - std::string rhs_base_id = to_symbol2t(lhs_flag).get_symbol_name(); - expr2tc rhs_base_addr = symbol2tc(get_intloc_type(), rhs_base_id); + // set a location for new heap region + symbolt heap_region_loc; + heap_region_loc.name = "heap_region_loc_"+ i2string(dynamic_counter); + + heap_region_loc.id = std::string("symex_dynamic::") + id2string(heap_region_loc.name); + heap_region_loc.lvalue = true; + + heap_region_loc.type = typet(typet::t_intheap); + + heap_region_loc.mode = "C"; + new_context.add(heap_region_loc); + + expr2tc rhs_base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); + cur_state->rename(rhs_base_loc); - expr2tc rhs_heap_region_flag = symbol2tc(get_intheap_type(), symbol.id); expr2tc rhs_region = heap_region2tc( - rhs_heap_region_flag, - rhs_base_addr, + rhs_heap, + rhs_base_loc, region_pt_bytes, region_size, size != 1 ); - + log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); - log_status("create valueset base addr symbol and assign"); - cur_state->rename(rhs_base_addr); - expr2tc pwr = pointer_with_region2tc(rhs_base_addr, rhs_heap); - symex_assign(code_assign2tc(lhs_flag, pwr)); - - // TODO: modify the pointer object here, maybe to wrap the intloc symbol directly - expr2tc ptr_obj = - pointer_object2tc(get_intloc_type(), to_pointer_with_region2t(pwr).loc_ptr); + // link pointer variable and heap variable + expr2tc pwr = pointer_with_region2tc(rhs_base_loc, rhs_heap); track_new_pointer( - ptr_obj, + rhs_base_loc, get_intheap_type(), gen_ulong(total_bytes)); - cur_state->rename(rhs_heap); + dynamic_memory.emplace_back( rhs_heap, rhs_guard, @@ -337,11 +330,16 @@ expr2tc goto_symext::symex_mem( symbol.name.as_string() ); + log_status("create valueset base loc symbol and assign"); if (is_heap_load2t(lhs)) { guardt g; symex_assign_heap_load(lhs, lhs, pwr, pwr, g, false); } + else + { + symex_assign(code_assign2tc(lhs, pwr)); + } return expr2tc(); } } diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index d35657ca..393eef74 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -806,6 +806,12 @@ class goto_symext */ void replace_null(expr2tc &expr); + /** + * Replace member, indexof ... by locadd + * @param expr Expr to a location. + */ + void replace_by_locadd(expr2tc &expr); + /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 72a90070..0745d260 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -288,13 +288,6 @@ void goto_symex_statet::rename(expr2tc &expr) if (is_pointer_with_region2t(hr.start_loc)) hr.start_loc = to_pointer_with_region2t(hr.start_loc).loc_ptr; } - - if (is_heap_load2t(expr)) - { - heap_load2t &hl = to_heap_load2t(expr); - if (is_pointer_with_region2t(hl.flag)) - hl.flag = to_pointer_with_region2t(hl.flag).loc_ptr; - } } void goto_symex_statet::rename_address(expr2tc &expr) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 1fe620d7..57e07958 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -186,8 +186,13 @@ void goto_symext::symex_assign( expr2tc rhs = code.source; if (options.get_bool_option("z3-slhv")) { + // Use SLHV empty pointer and empty heap replace_null(lhs); replace_null(rhs); + + // Turn every form of pointer arithmetic to locadd + replace_by_locadd(lhs); + replace_by_locadd(rhs); } log_status("symex assign lhs : ------------- "); @@ -902,15 +907,12 @@ void goto_symext::symex_assign_heap_load( assert(is_scalar_type(rhs)); const heap_load2t& heap_load = to_heap_load2t(lhs); - // assert(heap_load.byte_len * 8 == rhs->type->get_width()); - - symex_assign_rec(heap_load.flag, heap_load.flag, rhs, full_rhs, guard, hidden); expr2tc updated_heap = heap_update2tc( heap_load.heap, heap_load.start_loc, - heap_load.flag, + rhs, heap_load.byte_len); symex_assign_rec(heap_load.heap, heap_load.heap, updated_heap, updated_heap, guard, hidden); @@ -949,4 +951,62 @@ void goto_symext::replace_null(expr2tc &expr) replace_null(e); }); } +} + +void goto_symext::replace_by_locadd(expr2tc &expr) +{ + if (is_nil_expr(expr) || is_symbol2t(expr)) return; + if (is_member2t(expr)) + { + member2t& member = to_member2t(expr); + + type2tc deref_type = member.type; + expr2tc deref_loc; + + if (is_dereference2t(member.source_value)) + { + dereference2t& deref = to_dereference2t(member.source_value); + expr2tc loc_ptr = deref.value; + replace_by_locadd(loc_ptr); + + struct_type2t& ty = to_struct_type(deref.type); + unsigned int index = ty.get_component_number(member.member); + + if (index != 0) + deref_loc = locadd2tc(loc_ptr, gen_ulong(index)); + else + deref_loc = loc_ptr; + } + else + { + // TODO + log_error("Do not support this member expr"); + abort(); + } + + expr = dereference2tc(deref_type, deref_loc); + } + else if (is_add2t(expr) || is_sub2t(expr)) + { + expr2tc side_1 = is_add2t(expr) ? to_add2t(expr).side_1 : to_sub2t(expr).side_1; + expr2tc side_2 = is_add2t(expr) ? to_add2t(expr).side_2 : to_sub2t(expr).side_2; + + replace_by_locadd(side_1); + replace_by_locadd(side_2); + + if (is_pointer_type(side_2) || is_intloc_type(side_2)) + std::swap(side_1, side_2); + + if (is_sub2t(expr)) + side_2 = neg2tc(side_2->type, side_2); + + expr = locadd2tc(side_1, side_2); + } + else + { + expr->Foreach_operand([this](expr2tc &e) { + if (!is_nil_expr(e)) + replace_by_locadd(e); + }); + } } \ No newline at end of file diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index f396262d..13f9d08d 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -147,21 +147,6 @@ void symex_target_equationt::convert(smt_convt &smt_conv) log_status("final convert result ============= "); } -// void symex_target_equationt::convert2slhv(z3_slhv_convt& slhv_convt) { -// smt_convt::ast_vec assertions; -// smt_astt assumpt_ast = slhv_convt.convert_ast_slhv(gen_true_expr()); -// for (auto &SSA_step : SSA_steps) -// convert_internal_step_slhv(slhv_convt, assumpt_ast, assertions, SSA_step); - -// if (!assertions.empty()) -// slhv_convt.assert_ast(slhv_convt.make_n_ary_or(assertions)); -// log_status("final convert result ============= "); - -// slhv_convt.dump_smt(); -// log_status("================================== "); - -// } - void symex_target_equationt::convert_internal_step( smt_convt &smt_conv, smt_astt &assumpt_ast, @@ -271,116 +256,6 @@ void symex_target_equationt::convert_internal_step( log_status("-------------- over -----------------"); } - -// void symex_target_equationt::convert_internal_step_slhv( -// z3_slhv_convt& slhv_convt, -// smt_astt& assumpt_ast, -// smt_convt::ast_vec& assertions, -// SSA_stept &step -// ) { - -// log_status("------ convert internal step slhv ------ "); -// static unsigned output_count = 0; // Temporary hack; should become scoped. -// smt_astt true_val = slhv_convt.convert_ast_slhv(gen_true_expr()); -// smt_astt false_val = slhv_convt.convert_ast_slhv(gen_false_expr()); - -// if (step.ignore) -// { -// // std::ostringstream oss; -// // step.output(ns, oss); -// // log_status("{}", oss.str()); -// // log_status("convert internal step ignored ------ "); - -// // log_status("-------------- over -----------------"); -// step.cond_ast = true_val; -// step.guard_ast = false_val; -// return; -// } - -// log_status(" ------------------ dump step ------------------- "); -// step.dump(); - -// if (ssa_trace) -// { -// log_status("-------------- ssa trace -----------------"); -// std::ostringstream oss; -// step.output(ns, oss); -// log_status("{}", oss.str()); -// log_status("-------------- ssa trace end-----------------"); -// } -// log_status("------------- convert step guard ast: "); -// step.guard_ast = slhv_convt.convert_ast_slhv(step.guard); - -// if (step.is_assume() || step.is_assert()) -// { -// log_status("----- step is_assume || step is_assert"); -// expr2tc tmp(step.cond); -// step.cond_ast = slhv_convt.convert_ast_slhv(tmp); -// if (ssa_smt_trace) -// { -// step.cond_ast->dump(); -// } -// } -// else if (step.is_assignment()) -// { -// log_status(" ----- step is_assignment"); -// smt_astt assign = slhv_convt.convert_assign_slhv(step.cond); -// if (ssa_smt_trace) -// { -// assign->dump(); -// } - -// log_status("-------------- assignment over -----------------"); -// } -// else if (step.is_output()) -// { -// log_status(" ----- step is_output"); -// // for (std::list::const_iterator o_it = step.output_args.begin(); -// // o_it != step.output_args.end(); -// // o_it++) -// // { -// // const expr2tc &tmp = *o_it; -// // if (is_constant_expr(tmp) || is_constant_string2t(tmp)) -// // step.converted_output_args.push_back(tmp); -// // else -// // { -// // expr2tc sym = -// // symbol2tc(tmp->type, "symex::output::" + i2string(output_count++)); -// // expr2tc eq = equality2tc(sym, tmp); -// // smt_astt assign = smt_conv.convert_assign(eq); -// // if (ssa_smt_trace) -// // assign->dump(); -// // step.converted_output_args.push_back(sym); -// // } -// // } -// } -// else if (step.is_renumber()) -// { -// log_status(" ----- step is_renumber"); -// // smt_conv.renumber_symbol_address(step.guard, step.lhs, step.rhs); -// } -// else if (!step.is_skip()) -// { -// assert(0 && "Unexpected SSA step type in conversion"); -// } - -// if (step.is_assert()) -// { -// log_status(" ----- step is_assert"); -// step.cond_ast = slhv_convt.imply_ast(assumpt_ast, step.cond_ast); -// assertions.push_back(slhv_convt.invert_ast(step.cond_ast)); -// slhv_convt.invert_ast(step.cond_ast)->dump(); -// } -// else if (step.is_assume()) -// { -// log_status(" ----- step is_assume"); -// assumpt_ast = slhv_convt.mk_and(assumpt_ast, step.cond_ast); -// step.cond_ast->dump(); -// } - -// log_status("-------------- over -----------------"); -// } - void symex_target_equationt::output(std::ostream &out) const { for (const auto &SSA_step : SSA_steps) diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index 98724b2c..d6a669aa 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -73,20 +73,12 @@ class symex_target_equationt : public symex_targett const sourcet &source) override; virtual void convert(smt_convt &smt_conv); - // void convert2slhv(z3_slhv_convt& slhv_convt); void convert_internal_step( smt_convt &smt_conv, smt_astt &assumpt_ast, smt_convt::ast_vec &assertions, SSA_stept &s); - - // void convert_internal_step_slhv( - // z3_slhv_convt& slhv_convt, - // smt_astt& assumpt_ast, - // smt_convt::ast_vec& assertions, - // SSA_stept &s - // ); void reconstruct_symbolic_expression(expr2tc &expr, bool keep_local_variables) const override; diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 01a094bd..8de2adae 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -464,6 +464,35 @@ bool heap_region2t::update(uint byte_len) return false; } +std::string locadd2t::offset_as_string() const +{ + if (is_symbol2t(offset)) + return to_symbol2t(offset).get_symbol_name(); + else if (is_neg2t(offset)) + { + neg2t off = to_neg2t(offset); + expr2tc val = off.value.simplify(); + if (!is_constant_int2t(val)) + { + log_error("Doe no support for offset_as_string of neg"); + abort(); + } + return std::string("-") + + std::to_string(to_constant_int2t(val).value.to_int64()); + } + else + { + expr2tc off = offset; + if (!is_constant_int2t(off)) off = off.simplify(); + if (!is_constant_int2t(off)) + { + log_error("Doe no support for offset_as_string"); + abort(); + } + return std::to_string(to_constant_int2t(off).value.to_int64()); + } +} + const expr2tc &object_descriptor2t::get_root_object() const { const expr2tc *tmp = &object; diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 5432f06a..076c8abc 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -935,7 +935,6 @@ class points_to_data : public expr2t typedef esbmct::expr2t_traits< points_to_data_addr_field, points_to_data_content_field> traits; - }; @@ -963,7 +962,6 @@ class uplus_data : public expr2t typedef esbmct::field_traits member_num_field; typedef esbmct::expr2t_traits traits; - }; class locadd_data : public expr2t @@ -987,7 +985,6 @@ class locadd_data : public expr2t typedef esbmct::field_traits locadd_offset_field; typedef esbmct::expr2t_traits traits; - }; class heap_region_data : public expr2t @@ -1066,7 +1063,9 @@ class heap_free_data : public expr2t { } expr2tc pwr; - typedef esbmct::field_traits heap_free_data_pwr_field; + + typedef esbmct::field_traits + heap_free_data_pwr_field; typedef esbmct::expr2t_traits traits; }; @@ -1075,21 +1074,17 @@ class heap_load_data : public expr2t { heap_load_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &flag, const expr2tc &heap, const expr2tc &start_loc, unsigned int byte_len) - : expr2t(t, id), flag(flag), heap(heap), start_loc(start_loc), byte_len(byte_len) + : expr2t(t, id), heap(heap), start_loc(start_loc), byte_len(byte_len) { } - expr2tc flag; expr2tc heap; expr2tc start_loc; unsigned int byte_len; - typedef esbmct::field_traits - heap_load_data_flag_field; typedef esbmct::field_traits heap_load_data_heap_field; typedef esbmct::field_traits @@ -1097,11 +1092,9 @@ class heap_load_data : public expr2t { typedef esbmct::field_traits heap_load_data_byte_len_field; typedef esbmct::expr2t_traits< - heap_load_data_flag_field, heap_load_data_heap_field, heap_load_data_start_loc_field, heap_load_data_byte_len_field> traits; - }; class heap_update_data : public expr2t @@ -3367,6 +3360,8 @@ class locadd2t : public locadd_expr_methods } locadd2t(const locadd2t &ref) = default; + std::string offset_as_string() const; + static std::string field_names[esbmct::num_type_fields]; }; @@ -3406,14 +3401,13 @@ class heap_load2t : public heap_load_expr_methods { public: heap_load2t( - const type2tc &type, - const expr2tc &flag, + const type2tc &type, const expr2tc &heap, const expr2tc &start_loc, unsigned int byte_len) : heap_load_expr_methods( type, expr2t::heap_load_id, - flag, heap, start_loc, byte_len) + heap, start_loc, byte_len) { } heap_load2t(const heap_load2t& ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 1095a233..0b23396c 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -173,7 +173,7 @@ std::string heap_region2t::field_names[esbmct::num_type_fields] = std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = -{"flag", "src_heap", "start_loc", "byte_len", ""}; +{"src_heap", "start_loc", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = {"src_heap", "start_addr", "updated_val", "byte_len", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index db08406b..62b3c10a 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -34,7 +34,7 @@ expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); expr_typedefs5(heap_region, heap_region_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); -expr_typedefs5(heap_load, heap_load_data); +expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs4(heap_append, heap_append_data); expr_typedefs3(heap_delete, heap_delete_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index c1acfec8..bf4267ae 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -178,7 +178,6 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) expr = result; break; } - case expr2t::index_id: case expr2t::member_id: { @@ -485,7 +484,6 @@ expr2tc dereferencet::dereference( // collect objects dest may point to value_setst::valuest points_to_set; - log_status("---- value set for "); src->dump(); dereference_callback.get_value_set(src, points_to_set); @@ -1298,26 +1296,8 @@ void dereferencet::build_reference_slhv( gen_long(get_int64_type(), offset_pt) ); } - - std::string flag_id = - dereference_callback.get_loaded_value_flag(access_ptr) - + std::string("::loaded::"); - - symbolt symbol; - symbol.name = flag_id; - symbol.id = "heap_load::" + id2string(symbol.name); - symbol.lvalue = true; - symbol.type = - (is_pointer_type(type) || is_intloc_type(type)) ? - typet(typet::t_intloc) : typet(typet::t_integer); - - symbol.mode = "C"; - log_status("new_context.add(symbol);"); - new_context.add(symbol); - - expr2tc flag = symbol2tc(type, symbol.id); - value = heap_load2tc(type, flag, heap, access_ptr, access_sz); + value = heap_load2tc(type, heap, access_ptr, access_sz); } else { log_error("ERROR: currently not support non-scalar type dereference"); abort(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 7c9c7d3d..3fb7c7f5 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -203,6 +203,13 @@ void value_sett::get_value_set(const expr2tc &expr, object_mapt &dest) const // Then, start fetching values. get_value_set_rec(new_expr, dest, "", new_expr->type); + + // Convert values into expressions to return. + log_status("result value set:"); + for (object_mapt::const_iterator it = dest.begin(); + it != dest.end(); + it++) + to_expr(it)->dump(); } void value_sett::get_value_set_rec( @@ -574,9 +581,20 @@ void value_sett::get_value_set_rec( if (is_locadd2t(expr)) { const locadd2t& locadd = to_locadd2t(expr); - assert(is_intloc_type(locadd.loc)); - abort(); - // TODO + expr2tc base_ptr = locadd.loc; + expr2tc off = locadd.offset; + + if ((!is_pointer_type(base_ptr) && !is_intloc_type(base_ptr)) || + is_pointer_type(off) || is_intloc_type(off)) + { + log_error("Wrong locadd expr"); + abort(); + } + + // Do not need to update offset in SLHV + log_status("here"); + get_value_set_rec(base_ptr, dest, suffix, original_type); + return; } if (is_pointer_with_region2t(expr)) @@ -591,7 +609,7 @@ void value_sett::get_value_set_rec( if (is_heap_load2t(expr)) { get_value_set_rec( - to_heap_load2t(expr).flag, + to_heap_load2t(expr).start_loc, dest, suffix, original_type ); return; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index c6fd2c23..2929c969 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -270,7 +270,15 @@ z3_slhv_convt::convert_slhv_opts( // TODO : fix width // assert(heap_load.byte_len == 4); //current heap state - assert_ast(mk_subh(mk_pt(args[2], args[0]), args[1])); + + smt_astt v1; + + if (is_pointer_type(heap_load.type) || is_intloc_type(heap_load.type)) + v1 = mk_fresh(mk_intloc_sort(), mk_fresh_name("tmp_loc::")); + else + v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); + + assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); return args[0]; } case expr2t::heap_contains_id: @@ -325,7 +333,7 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) else if (is_heap_region2t(expr)) return convert_ast(to_heap_region2t(expr).start_loc); else if (is_heap_load2t(expr)) - return convert_ast(to_heap_load2t(expr).flag); + return project(to_heap_load2t(expr).start_loc); else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); else if (is_locadd2t(expr) || is_add2t(expr) || is_sub2t(expr)) diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 2db8d601..719bd722 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2042,7 +2042,6 @@ exprt migrate_expr_back(const expr2tc &ref) } case expr2t::constant_intheap_id: { - const constant_intheap2t &ref2 = to_constant_intheap2t(ref); typet thetype = migrate_type_back(ref->type); constant_exprt theexpr(thetype); @@ -2650,7 +2649,6 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_load2t& ref2 = to_heap_load2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_load("heap_load", thetype); - heap_load.copy_to_operands(migrate_expr_back(ref2.flag)); heap_load.copy_to_operands(migrate_expr_back(ref2.heap)); heap_load.copy_to_operands(migrate_expr_back(ref2.start_loc)); heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); From 1a199d20a67d4c83196a8a92f055a15a5cd8db10 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 20 Aug 2024 10:10:06 +0800 Subject: [PATCH 050/126] fix encoding of heap_load --- benchmark/case_0.c | 2 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index ebc269a0..adaefcfb 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -3,7 +3,7 @@ int main(){ int * data = malloc(sizeof(int)); int * data2 = malloc(2*sizeof(int)); - free(data2); + free(data); int i = *(data + 1); // int* j = NULL; // int* i = j; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 2929c969..4993d0cb 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -279,7 +279,7 @@ z3_slhv_convt::convert_slhv_opts( v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); - return args[0]; + return v1; } case expr2t::heap_contains_id: { From 15e97252b86db002ce37990016fb6cc12914d8bb Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 23 Aug 2024 00:25:51 +0800 Subject: [PATCH 051/126] add locationof and fieldof, replacing pwr and heap_load --- src/goto-symex/builtin_functions.cpp | 102 ++--- src/goto-symex/dynamic_allocation.cpp | 8 +- src/goto-symex/execution_state.cpp | 4 +- src/goto-symex/goto_symex.h | 14 +- src/goto-symex/goto_symex_state.cpp | 40 +- src/goto-symex/slice.cpp | 2 +- src/goto-symex/symex_assign.cpp | 89 +--- src/goto-symex/symex_dereference.cpp | 98 ++--- src/goto-symex/symex_goto.cpp | 12 +- src/irep2/irep2.h | 6 +- src/irep2/irep2_expr.cpp | 110 ++--- src/irep2/irep2_expr.h | 394 +++++++++--------- src/irep2/irep2_type.cpp | 32 ++ src/irep2/irep2_type.h | 47 ++- src/irep2/irep2_utils.h | 2 +- src/irep2/templates/irep2_templates.cpp | 28 +- .../templates/irep2_templates_expr_data.cpp | 10 +- src/irep2/templates/irep2_templates_type.cpp | 2 +- src/pointer-analysis/dereference.cpp | 86 ++-- src/pointer-analysis/dereference.h | 14 +- src/pointer-analysis/value_set.cpp | 112 +++-- src/solvers/smt/smt_conv.cpp | 6 +- src/solvers/smt/smt_memspace.cpp | 6 - src/solvers/z3-slhv/z3_slhv_conv.cpp | 174 +++++--- src/util/c_types.cpp | 7 +- src/util/c_types.h | 2 +- src/util/migrate.cpp | 99 +++-- 27 files changed, 830 insertions(+), 676 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 463284fa..53bfcd19 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -122,6 +122,11 @@ expr2tc goto_symext::symex_mem( expr2tc size = code.size; bool size_is_one = false; + log_status("alloctype : "); + type->dump(); + log_status("size : "); + size->dump(); + if (is_nil_type(type)) type = char_type2(); @@ -254,39 +259,45 @@ expr2tc goto_symext::symex_mem( symbol.type = typet(typet::t_intheap); - // Size in SLHV is byte level - // expr2tc bytesizes - expr2tc bytes; + type2tc heap_type; if (size_is_one) - bytes = gen_ulong(type->get_width() / 8); + { + heap_type = get_intheap_type(type_byte_size(type).to_uint64()); + to_intheap_type(heap_type).is_aligned = true; + } else { - bytes = size; + expr2tc bytes = size; if (!is_constant_int2t(bytes)) - bytes = bytes.simplify(); - if (!is_constant_int2t(bytes)) + bytes = bytes->simplify(); + if (is_constant_int2t(bytes)) + { + heap_type = get_intheap_type(to_constant_int2t(bytes).value.to_uint64()); + } + else { log_error("Do not support dynamic size"); abort(); } } - - uint total_bytes = to_constant_int2t(bytes).value.to_uint64(); - uint pt_bytes = type.get()->get_width() / 8; - uint size = total_bytes / pt_bytes; - if (pt_bytes == 1) - { - pt_bytes = total_bytes; - size = 1; - } - expr2tc region_pt_bytes = constant_int2tc(get_uint64_type(), BigInt(pt_bytes)); - expr2tc region_size = constant_int2tc(get_uint64_type(), BigInt(size)); + to_intheap_type(heap_type).is_region = true; + + // uint total_bytes = to_constant_int2t(bytes).value.to_uint64(); + // uint pt_bytes = type.get()->get_width() / 8; + // uint size = total_bytes / pt_bytes; + // if (pt_bytes == 1) + // { + // pt_bytes = total_bytes; + // size = 1; + // } + // expr2tc region_pt_bytes = constant_int2tc(get_uint64_type(), BigInt(pt_bytes)); + // expr2tc region_size = constant_int2tc(get_uint64_type(), BigInt(size)); symbol.type.dynamic(true); symbol.mode = "C"; new_context.add(symbol); - expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); + expr2tc rhs_heap = symbol2tc(heap_type, symbol.id); guardt rhs_guard = cur_state->guard; // set a location for new heap region @@ -302,26 +313,18 @@ expr2tc goto_symext::symex_mem( new_context.add(heap_region_loc); expr2tc rhs_base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); - cur_state->rename(rhs_base_loc); - - expr2tc rhs_region = - heap_region2tc( - rhs_heap, - rhs_base_loc, - region_pt_bytes, - region_size, - size != 1 - ); + + expr2tc rhs_region = heap_region2tc(heap_type, rhs_heap, rhs_base_loc); log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); - // link pointer variable and heap variable - expr2tc pwr = pointer_with_region2tc(rhs_base_loc, rhs_heap); - track_new_pointer( - rhs_base_loc, - get_intheap_type(), - gen_ulong(total_bytes)); + // // link pointer variable and heap variable + // expr2tc pwr = pointer_with_region2tc(rhs_base_loc, rhs_heap); + // track_new_pointer( + // rhs_base_loc, + // get_intheap_type(), + // gen_ulong(total_bytes)); dynamic_memory.emplace_back( rhs_heap, @@ -331,15 +334,17 @@ expr2tc goto_symext::symex_mem( ); log_status("create valueset base loc symbol and assign"); - if (is_heap_load2t(lhs)) - { - guardt g; - symex_assign_heap_load(lhs, lhs, pwr, pwr, g, false); - } - else - { - symex_assign(code_assign2tc(lhs, pwr)); - } + symex_assign(code_assign2tc(lhs, locationof2tc(rhs_region))); + + // if (is_heap_load2t(lhs)) + // { + // guardt g; + // symex_assign_heap_load(lhs, lhs, pwr, pwr, g, false); + // } + // else + // { + // symex_assign(code_assign2tc(lhs, pwr)); + // } return expr2tc(); } } @@ -381,7 +386,8 @@ void goto_symext::track_new_pointer( // TODO SLHV: add non-constant size later assert(is_constant_int2t(size)); - expr2tc updated_heap = heap_append2tc(allocsize_symbol, ptr_obj, size, 4); + expr2tc updated_heap = + heap_append2tc(allocsize_symbol, points_to2tc(ptr_obj, size)); symex_assign(code_assign2tc(allocsize_symbol, updated_heap), true); } } @@ -480,11 +486,11 @@ void goto_symext::symex_free(const expr2tc &expr) assert(is_heap_region2t(item.object)); const heap_region2t& heap_region = to_heap_region2t(item.object); if(is_nil_expr(freed_pointer)) { - freed_pointer = heap_region.start_loc; + freed_pointer = heap_region.source_location; freed_heap = heap_region.flag; } else { freed_pointer = - if2tc(freed_pointer->type, item.guard, heap_region.start_loc, freed_pointer); + if2tc(freed_pointer->type, item.guard, heap_region.source_location, freed_pointer); freed_heap = if2tc(get_intheap_type(), item.guard, heap_region.flag, freed_heap); } @@ -493,7 +499,7 @@ void goto_symext::symex_free(const expr2tc &expr) log_status("symex free freed_heap emp_heap"); symex_assign(code_assign2tc(freed_heap, emp_heap)); expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); - expr2tc heap_deleted = heap_delete2tc(alloc_size_heap_symbol, freed_pointer, 4); + expr2tc heap_deleted = heap_delete2tc(alloc_size_heap_symbol, freed_pointer); symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); } } diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 423bec19..13dafd5d 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -40,8 +40,8 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_status("before migrate"); migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap_2); log_status("migrate over"); - expr2tc heap_contains = heap_contains2tc(valid_inner.start_loc, alloc_size_heap_2, 1); - expr = heap_contains; + expr2tc heap_contain = heap_contain2tc(valid_inner.source_location, alloc_size_heap_2); + expr = heap_contain; } } else if (is_invalid_pointer2t(expr)) @@ -88,8 +88,8 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - expr2tc heap_contains = heap_contains2tc(obj_expr, alloc_size_heap, 1); - expr2tc not_valid = not2tc(heap_contains); + expr2tc heap_contain = heap_contain2tc(obj_expr, alloc_size_heap); + expr2tc not_valid = not2tc(heap_contain); expr = not_valid; } diff --git a/src/goto-symex/execution_state.cpp b/src/goto-symex/execution_state.cpp index 069b2c2d..88e2f6eb 100644 --- a/src/goto-symex/execution_state.cpp +++ b/src/goto-symex/execution_state.cpp @@ -201,8 +201,8 @@ void execution_statet::symex_step(reachability_treet &art) statet &state = get_active_state(); const goto_programt::instructiont &instruction = *state.source.pc; last_insn = &instruction; - log_status("#### current symex_step instruction:"); - instruction.dump(); + // log_status("#### current symex_step instruction:"); + // instruction.dump(); merge_gotos(); if (break_insn != 0 && break_insn == instruction.location_number) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 393eef74..785a7a9f 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -750,14 +750,13 @@ class goto_symext /** * This method is used when we need to assign a value - * to a heap_load, which is obatained via load `byte_len` - * bytes in a heap(SLHV). - * @param lhs Heap(points-to) to assign to + * to a field of a heap region + * @param lhs field of a region * @param full_lhs The original assignment symbol * @param rhs Value to assign to lhs * @param guard Assignment guard. */ - void symex_assign_heap_load( + void symex_assign_fieldof( const expr2tc &lhs, const expr2tc &full_lhs, expr2tc &rhs, @@ -970,11 +969,10 @@ class symex_dereference_statet : public dereference_callbackt dump_internal_state(const std::list &data) override; bool is_live_variable(const expr2tc &sym) override; - void update_regions(const expr2tc ®ion) override; - void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) override; - std::string get_loaded_value_flag(const expr2tc &expr) override; + void update_heap_type(const expr2tc &flag) override; + void update_heap_type_rec(expr2tc &expr, const symbol2t &flag) override; std::string get_nondet_id(std::string prefix = "") override; - irep_idt get_alooc_size_heap_name() override; + irep_idt get_alloc_size_heap_name() override; }; #endif diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 0745d260..a5196abc 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -67,17 +67,23 @@ void goto_symex_statet::initialize( bool goto_symex_statet::constant_propagation(const expr2tc &expr) const { // SLHV propagation - if (is_pointer_with_region2t(expr) || - is_constant_intheap2t(expr) || - is_constant_intloc2t(expr)) + if (is_constant_intheap2t(expr) || + is_constant_intloc2t(expr) || + is_heap_region2t(expr)) return true; + if (is_locadd2t(expr)) { locadd2t locadd = to_locadd2t(expr); - return constant_propagation(locadd.loc) && + return constant_propagation(locadd.location) && constant_propagation(locadd.offset); } + if (is_locationof2t(expr)) + { + return constant_propagation(to_locationof2t(expr).heap_term); + } + if (is_array_type(expr)) { array_type2t arr = to_array_type(expr->type); @@ -269,25 +275,23 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } + else if (is_heap_region2t(expr)) + { + // Don't replace flag with heap region + // Get the newest symbol + heap_region2t &heap_region = to_heap_region2t(expr); + + // rename location + rename(heap_region.source_location); + + // use the newest l2 symbol + level2.get_ident_name(heap_region.flag); + } else { // do this recursively expr->Foreach_operand([this](expr2tc &e) { rename(e); }); } - - if (is_pointer_with_region2t(expr)) - { - pointer_with_region2t &pwr = to_pointer_with_region2t(expr); - if (is_pointer_with_region2t(pwr.loc_ptr)) - pwr.loc_ptr = to_pointer_with_region2t(pwr.loc_ptr).loc_ptr; - } - - if (is_heap_region2t(expr)) - { - heap_region2t &hr = to_heap_region2t(expr); - if (is_pointer_with_region2t(hr.start_loc)) - hr.start_loc = to_pointer_with_region2t(hr.start_loc).loc_ptr; - } } void goto_symex_statet::rename_address(expr2tc &expr) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index b9976c40..8f210861 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -12,7 +12,7 @@ bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; if (is_heap_region2t(expr)) - return get_symbols(to_heap_region2t(expr).start_loc); + return get_symbols(to_heap_region2t(expr).source_location); else if (is_pointer_with_region2t(expr)) return get_symbols(to_pointer_with_region2t(expr).loc_ptr); else diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 57e07958..491a3d37 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -186,13 +186,8 @@ void goto_symext::symex_assign( expr2tc rhs = code.source; if (options.get_bool_option("z3-slhv")) { - // Use SLHV empty pointer and empty heap replace_null(lhs); replace_null(rhs); - - // Turn every form of pointer arithmetic to locadd - replace_by_locadd(lhs); - replace_by_locadd(rhs); } log_status("symex assign lhs : ------------- "); @@ -346,10 +341,10 @@ void goto_symext::symex_assign_rec( log_status("symex_assign_bitfield"); symex_assign_bitfield(lhs, full_lhs, rhs, full_rhs, guard, hidden); } - else if (is_heap_load2t(lhs)) + else if (is_fieldof2t(lhs)) { - log_status("symex_assign_heap_load"); - symex_assign_heap_load(lhs, full_lhs, rhs, full_rhs, guard, hidden); + log_status("symex_assign_fieldof"); + symex_assign_fieldof(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_heap_region2t(lhs)) { @@ -896,7 +891,7 @@ void goto_symext::symex_assign_bitfield( return symex_assign_rec(val, full_lhs, new_rhs, full_rhs, guard, hidden); } -void goto_symext::symex_assign_heap_load( +void goto_symext::symex_assign_fieldof( const expr2tc &lhs, const expr2tc &full_lhs, expr2tc &rhs, @@ -906,16 +901,18 @@ void goto_symext::symex_assign_heap_load( { assert(is_scalar_type(rhs)); - const heap_load2t& heap_load = to_heap_load2t(lhs); + const fieldof2t& fieldof = to_fieldof2t(lhs); + const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); - expr2tc updated_heap = - heap_update2tc( - heap_load.heap, - heap_load.start_loc, - rhs, - heap_load.byte_len); + expr2tc update_heap = + heap_update2tc(heap_region.type, fieldof.heap_region, fieldof.field, rhs); - symex_assign_rec(heap_load.heap, heap_load.heap, updated_heap, updated_heap, guard, hidden); + symex_assign_rec( + heap_region.flag, + fieldof.heap_region, + update_heap, + update_heap, + guard, hidden); } void goto_symext::replace_nondet(expr2tc &expr) @@ -951,62 +948,4 @@ void goto_symext::replace_null(expr2tc &expr) replace_null(e); }); } -} - -void goto_symext::replace_by_locadd(expr2tc &expr) -{ - if (is_nil_expr(expr) || is_symbol2t(expr)) return; - if (is_member2t(expr)) - { - member2t& member = to_member2t(expr); - - type2tc deref_type = member.type; - expr2tc deref_loc; - - if (is_dereference2t(member.source_value)) - { - dereference2t& deref = to_dereference2t(member.source_value); - expr2tc loc_ptr = deref.value; - replace_by_locadd(loc_ptr); - - struct_type2t& ty = to_struct_type(deref.type); - unsigned int index = ty.get_component_number(member.member); - - if (index != 0) - deref_loc = locadd2tc(loc_ptr, gen_ulong(index)); - else - deref_loc = loc_ptr; - } - else - { - // TODO - log_error("Do not support this member expr"); - abort(); - } - - expr = dereference2tc(deref_type, deref_loc); - } - else if (is_add2t(expr) || is_sub2t(expr)) - { - expr2tc side_1 = is_add2t(expr) ? to_add2t(expr).side_1 : to_sub2t(expr).side_1; - expr2tc side_2 = is_add2t(expr) ? to_add2t(expr).side_2 : to_sub2t(expr).side_2; - - replace_by_locadd(side_1); - replace_by_locadd(side_2); - - if (is_pointer_type(side_2) || is_intloc_type(side_2)) - std::swap(side_1, side_2); - - if (is_sub2t(expr)) - side_2 = neg2tc(side_2->type, side_2); - - expr = locadd2tc(side_1, side_2); - } - else - { - expr->Foreach_operand([this](expr2tc &e) { - if (!is_nil_expr(e)) - replace_by_locadd(e); - }); - } } \ No newline at end of file diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index c86eea2a..042314a4 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -166,89 +166,93 @@ bool symex_dereference_statet::is_live_variable(const expr2tc &symbol) return false; } -void symex_dereference_statet::update_regions(const expr2tc ®ion) +void symex_dereference_statet::update_heap_type(const expr2tc &flag) { - assert(is_heap_region2t(region)); - + if (!is_symbol2t(flag)) + { + log_error("Wrong flag!!!!"); + abort(); + } + + log_status("begin update heap type"); + flag->dump(); + + // Each heap region has a unique L0 name + expr2tc l0_flag = flag; + goto_symex.cur_state->get_original_name(l0_flag); + const symbol2t l0_sym = to_symbol2t(l0_flag); + + l0_flag->dump(); + // update value set value_sett& value_set = goto_symex.cur_state->value_set; unsigned int n = value_set.object_numbering.size(); for(unsigned int i = 0; i < n; i++) - update_heap_region_rec(value_set.object_numbering[i], region); + update_heap_type_rec(value_set.object_numbering[i], l0_sym); + + + log_status("finishing update value set"); // update eq system - log_status("update eq system"); std::shared_ptr eq = std::dynamic_pointer_cast(goto_symex.target); for(auto& ssa_step : eq->SSA_steps) { - update_heap_region_rec(ssa_step.guard, region); - update_heap_region_rec(ssa_step.rhs, region); - update_heap_region_rec(ssa_step.cond, region); + update_heap_type_rec(ssa_step.guard, l0_sym); + update_heap_type_rec(ssa_step.rhs, l0_sym); + update_heap_type_rec(ssa_step.cond, l0_sym); } + + log_status("finishing replace"); } -void symex_dereference_statet::update_heap_region_rec( - expr2tc &expr, - const expr2tc ®ion) +void symex_dereference_statet::update_heap_type_rec( + expr2tc &expr, const symbol2t &flag) { if (is_nil_expr(expr)) return; + log_status("update type of :"); + expr->dump(); + if (is_symbol2t(expr)) + { + // update heap variable + expr2tc l0_sym = expr; + goto_symex.cur_state->get_original_name(l0_sym); - if (is_heap_region2t(expr)) + if (flag.get_symbol_name() == to_symbol2t(l0_sym).get_symbol_name()) + expr->type = flag.type; + } + else if (is_heap_region2t(expr)) { - uint byte_len = - to_constant_int2t( - to_heap_region2t(region).pt_bytes) - .value.to_uint64(); + heap_region2t &heap_region = to_heap_region2t(expr); + + expr2tc l0_flag = heap_region.flag; + goto_symex.cur_state->get_original_name(l0_flag); - expr2tc old_reg = expr; - goto_symex.cur_state->level2.get_original_name(old_reg); + l0_flag->dump(); - if (to_symbol2t(to_heap_region2t(region).start_loc).get_symbol_name() == - to_symbol2t(to_heap_region2t(old_reg).start_loc).get_symbol_name()) + if (flag.get_symbol_name() == + to_symbol2t(l0_flag).get_symbol_name()) { - heap_region2t& reg = to_heap_region2t(expr); - reg.update(byte_len); - expr = heap_region2tc(reg); + heap_region.type = flag.type; + update_heap_type_rec(heap_region.flag, flag); } } else { - expr->Foreach_operand([this, ®ion](expr2tc& e){ + expr->Foreach_operand([this, &flag](expr2tc& e){ if (!is_nil_expr(e)) - update_heap_region_rec(e, region); + update_heap_type_rec(e, flag); }); } } -std::string symex_dereference_statet::get_loaded_value_flag(const expr2tc &expr) -{ - if (is_symbol2t(expr)) - return to_symbol2t(expr).get_symbol_name(); - else if (is_constant_int2t(expr)) - return std::to_string(to_constant_int2t(expr).value.to_int64()); - else if (is_locadd2t(expr)) - { - const locadd2t &locadd = to_locadd2t(expr); - return get_loaded_value_flag(locadd.loc) + - get_loaded_value_flag(locadd.offset); - } - else if (is_typecast2t(expr)) - return get_loaded_value_flag(to_typecast2t(expr).from); - else - { - log_error("Do not support"); - abort(); - } -} - std::string symex_dereference_statet::get_nondet_id(std::string prefix) { unsigned int nondet_counter = goto_symex.get_nondet_counter(); return prefix + std::to_string(++nondet_counter); } -irep_idt symex_dereference_statet::get_alooc_size_heap_name() +irep_idt symex_dereference_statet::get_alloc_size_heap_name() { return goto_symex.alloc_size_heap_name; } diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp index 3e5644b8..30ac5b1e 100644 --- a/src/goto-symex/symex_goto.cpp +++ b/src/goto-symex/symex_goto.cpp @@ -232,7 +232,9 @@ static inline guardt merge_state_guards( (!goto_state.guard.is_false() && !state.guard.is_false()) || state.guard.disjunction_may_simplify(goto_state.guard)) { - return state.guard | goto_state.guard; + // return state.guard | goto_state.guard; + state.guard |= goto_state.guard; + return state.guard; } else if (state.guard.is_false() && !goto_state.guard.is_false()) { @@ -265,8 +267,7 @@ void goto_symext::merge_gotos() // Merge guards. Don't write this to `state` yet because we might move // goto_state over it below. - // guardt new_guard = merge_state_guards(goto_state, *cur_state); - + guardt new_guard = merge_state_guards(goto_state, *cur_state); if (!goto_state.guard.is_false()) { @@ -282,7 +283,8 @@ void goto_symext::merge_gotos() std::min(cur_state->num_instructions, goto_state.num_instructions); } - cur_state->guard = merge_state_guards(goto_state, *cur_state); + cur_state->guard = std::move(new_guard); + // cur_state->guard = merge_state_guards(goto_state, *cur_state); } // clean up to save some memory @@ -303,10 +305,8 @@ void goto_symext::merge_locality(const statet::goto_statet &src) void goto_symext::merge_value_sets(const statet::goto_statet &src) { - log_status("merge value set {}", cur_state->guard.is_false()); if (cur_state->guard.is_false()) { - log_status("just replace"); cur_state->value_set = src.value_set; return; } diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 14d0522c..e43aeacf 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -107,12 +107,14 @@ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(heap_region, \ + BOOST_PP_LIST_CONS(locationof, \ + BOOST_PP_LIST_CONS(fieldof, \ BOOST_PP_LIST_CONS(pointer_with_region, \ BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_delete, \ - BOOST_PP_LIST_CONS(heap_contains, \ + BOOST_PP_LIST_CONS(heap_contain, \ BOOST_PP_LIST_CONS(isnan, \ BOOST_PP_LIST_CONS(overflow, \ BOOST_PP_LIST_CONS(overflow_cast, \ @@ -153,7 +155,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 8de2adae..00dc8fc7 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -78,12 +78,14 @@ static const char *expr_names[] = { "uplus", "locadd", "heap_region", + "locationof", + "fieldof", "pointer_with_region", "heap_load", "heap_update", "heap_append", "heap_delete", - "heap_contains", + "heap_contain", "isnan", "overflow", "overflow_cast", @@ -439,59 +441,59 @@ void with2t::assert_consistency() const assert(type == source_value->type); } -bool heap_region2t::update(uint byte_len) -{ - uint old_bytes = to_constant_int2t(pt_bytes).value.to_uint64(); - uint old_size = to_constant_int2t(size).value.to_uint64(); - - assert(old_bytes * old_size % byte_len == 0); - // TODO: allow to split only one time - if (is_split) { - assert(byte_len == old_bytes); - return false; - } - - uint new_bytes = byte_len; - uint new_size; - if (byte_len != old_bytes) - { - new_size = old_bytes * old_size / byte_len; - is_split = true; - pt_bytes = constant_int2tc(get_uint64_type(), BigInt(new_bytes)); - size = constant_int2tc(get_uint64_type(), BigInt(new_size)); - return true; - } - return false; -} - -std::string locadd2t::offset_as_string() const -{ - if (is_symbol2t(offset)) - return to_symbol2t(offset).get_symbol_name(); - else if (is_neg2t(offset)) - { - neg2t off = to_neg2t(offset); - expr2tc val = off.value.simplify(); - if (!is_constant_int2t(val)) - { - log_error("Doe no support for offset_as_string of neg"); - abort(); - } - return std::string("-") - + std::to_string(to_constant_int2t(val).value.to_int64()); - } - else - { - expr2tc off = offset; - if (!is_constant_int2t(off)) off = off.simplify(); - if (!is_constant_int2t(off)) - { - log_error("Doe no support for offset_as_string"); - abort(); - } - return std::to_string(to_constant_int2t(off).value.to_int64()); - } -} +// bool heap_region2t::update(uint byte_len) +// { +// uint old_bytes = to_constant_int2t(field_bytes).value.to_uint64(); +// uint old_size = to_constant_int2t(size).value.to_uint64(); + +// assert(old_bytes * old_size % byte_len == 0); +// // TODO: allow to split only one time +// if (is_aligned) { +// assert(byte_len == old_bytes); +// return false; +// } + +// uint new_bytes = byte_len; +// uint new_size; +// if (byte_len != old_bytes) +// { +// new_size = old_bytes * old_size / byte_len; +// is_aligned = true; +// field_bytes = constant_int2tc(get_uint64_type(), BigInt(new_bytes)); +// size = constant_int2tc(get_uint64_type(), BigInt(new_size)); +// return true; +// } +// return false; +// } + +// std::string locadd2t::offset_as_string() const +// { +// if (is_symbol2t(offset)) +// return to_symbol2t(offset).get_symbol_name(); +// else if (is_neg2t(offset)) +// { +// neg2t off = to_neg2t(offset); +// expr2tc val = off.value.simplify(); +// if (!is_constant_int2t(val)) +// { +// log_error("Doe no support for offset_as_string of neg"); +// abort(); +// } +// return std::string("-") +// + std::to_string(to_constant_int2t(val).value.to_int64()); +// } +// else +// { +// expr2tc off = offset; +// if (!is_constant_int2t(off)) off = off.simplify(); +// if (!is_constant_int2t(off)) +// { +// log_error("Doe no support for offset_as_string"); +// abort(); +// } +// return std::to_string(to_constant_int2t(off).value.to_int64()); +// } +// } const expr2tc &object_descriptor2t::get_root_object() const { diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 076c8abc..bf2a5457 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -910,58 +910,51 @@ class index_data : public datatype_ops typedef esbmct::expr2t_traits traits; }; + +/* ================================ SLHV ================================ */ + class points_to_data : public expr2t { public: points_to_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &addrloc, - const expr2tc &content) - : expr2t(t, id), addr(addrloc), content(content) + const expr2tc &l, + const expr2tc &c) + : expr2t(t, id), location(l), content(c) { } points_to_data(const points_to_data& ref) = default; - - expr2tc addr; + expr2tc location; expr2tc content; // Type mangling: - typedef esbmct::field_traits - points_to_data_addr_field; + typedef esbmct::field_traits + location_field; typedef esbmct::field_traits - points_to_data_content_field; - typedef esbmct::expr2t_traits< - points_to_data_addr_field, - points_to_data_content_field> traits; + content_field; + typedef esbmct::expr2t_traits traits; }; - class uplus_data : public expr2t { public: - uplus_data( const type2tc &t, datatype_ops::expr_ids id, - const std::vector &members, - unsigned int m_num) - : expr2t(t, id), uplus_members(std::move(members)), member_num(m_num) + const std::vector &ht) + : expr2t(t, id), heap_terms(ht) { } uplus_data(const uplus_data& ref) = default; - - std::vector uplus_members; - unsigned int member_num; + std::vector heap_terms; // Type mangling: - typedef esbmct::field_traits, uplus_data, &uplus_data::uplus_members> - uplus_members_field; - typedef esbmct::field_traits - member_num_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits, uplus_data, &uplus_data::heap_terms> + heap_terms_field; + typedef esbmct::expr2t_traits traits; }; class locadd_data : public expr2t @@ -970,21 +963,22 @@ class locadd_data : public expr2t locadd_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &loc, - const expr2tc &offset) - : expr2t(t, id), loc(loc), offset(offset) + const expr2tc &l, + const expr2tc &o) + : expr2t(t, id), location(l), offset(o) { } locadd_data(const locadd_data& ref) = default; - expr2tc loc; + + expr2tc location; expr2tc offset; // Type mangling: - typedef esbmct::field_traits - locadd_loc_field; + typedef esbmct::field_traits + location_field; typedef esbmct::field_traits - locadd_offset_field; - typedef esbmct::expr2t_traits traits; + offset_field; + typedef esbmct::expr2t_traits traits; }; class heap_region_data : public expr2t @@ -993,40 +987,66 @@ class heap_region_data : public expr2t heap_region_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &flag, - const expr2tc &start_loc, - const expr2tc &pt_bytes, - const expr2tc &size, - bool is_split) - : expr2t(t, id), flag(flag), - start_loc(start_loc), pt_bytes(pt_bytes), size(size), is_split(is_split) + const expr2tc &f, + const expr2tc &sl) + : expr2t(t, id), flag(f), source_location(sl) { } heap_region_data(const heap_region_data& ref) = default; expr2tc flag; - expr2tc start_loc; - expr2tc pt_bytes; - expr2tc size; - bool is_split; + expr2tc source_location; // Type mangling: typedef esbmct::field_traits - heap_region_flag_field; - typedef esbmct::field_traits - heap_region_start_loc_field; - typedef esbmct::field_traits - heap_region_pt_bytes_field; - typedef esbmct::field_traits - heap_region_size_field; - typedef esbmct::field_traits - heap_region_is_split_field; - typedef esbmct::expr2t_traits< - heap_region_flag_field, - heap_region_start_loc_field, - heap_region_pt_bytes_field, - heap_region_size_field, - heap_region_is_split_field> traits; + flag_field; + typedef esbmct::field_traits + source_location_field; + typedef esbmct::expr2t_traits traits; +}; + +class locationof_data : public expr2t +{ +public: + locationof_data( + const type2tc &t, + datatype_ops::expr_ids id, + const expr2tc &ht) + : expr2t(t, id), heap_term(ht) + { + } + locationof_data(const locationof_data& ref) = default; + + expr2tc heap_term; + + // Type mangling: + typedef esbmct::field_traits + heap_term_field; + typedef esbmct::expr2t_traits traits; +}; + +class fieldof_data : public expr2t +{ +public: + fieldof_data( + const type2tc &t, + datatype_ops::expr_ids id, + const expr2tc &hr, + const expr2tc &f) + : expr2t(t, id), heap_region(hr), field(f) + { + } + fieldof_data(const fieldof_data &ref) = default; + + expr2tc heap_region; + expr2tc field; + + // Type mangling: + typedef esbmct::field_traits + heap_region_field; + typedef esbmct::field_traits + field_field; + typedef esbmct::expr2t_traits traits; }; class pointer_with_region_data : public expr2t @@ -1052,39 +1072,27 @@ class pointer_with_region_data : public expr2t typedef esbmct::expr2t_traits traits; }; -class heap_free_data : public expr2t { -public: - heap_free_data( - const type2tc &t, - datatype_ops::expr_ids id, - expr2tc pwr) - : expr2t(t, id), pwr(pwr) - { - } - - expr2tc pwr; - - typedef esbmct::field_traits - heap_free_data_pwr_field; - typedef esbmct::expr2t_traits traits; -}; - class heap_load_data : public expr2t { public: heap_load_data( const type2tc &t, datatype_ops::expr_ids id, + const expr2tc &flag, const expr2tc &heap, const expr2tc &start_loc, unsigned int byte_len) - : expr2t(t, id), heap(heap), start_loc(start_loc), byte_len(byte_len) + : expr2t(t, id), flag(flag), heap(heap), start_loc(start_loc), byte_len(byte_len) { } + expr2tc flag; expr2tc heap; expr2tc start_loc; unsigned int byte_len; + // Type mangling: + typedef esbmct::field_traits + heap_load_data_flag_field; typedef esbmct::field_traits heap_load_data_heap_field; typedef esbmct::field_traits @@ -1092,6 +1100,7 @@ class heap_load_data : public expr2t { typedef esbmct::field_traits heap_load_data_byte_len_field; typedef esbmct::expr2t_traits< + heap_load_data_flag_field, heap_load_data_heap_field, heap_load_data_start_loc_field, heap_load_data_byte_len_field> traits; @@ -1103,33 +1112,25 @@ class heap_update_data : public expr2t heap_update_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc source_val, - expr2tc start_addr, - expr2tc updated_val, - unsigned int byte_len) - : expr2t(t, id), src_heap(source_val), start_addr(start_addr), updated_val(updated_val), byte_len(byte_len) + const expr2tc &sh, + const expr2tc &uf, + const expr2tc &uv) + : expr2t(t, id), source_heap(sh), update_field(uf), update_value(uv) { } - expr2tc src_heap; - expr2tc start_addr; - expr2tc updated_val; - unsigned int byte_len; + expr2tc source_heap; + expr2tc update_field; + expr2tc update_value; // Type mangling: - typedef esbmct::field_traits - heap_update_data_src_heap_field; - typedef esbmct::field_traits - heap_update_data_start_addr_field; - typedef esbmct::field_traits - heap_update_data_updated_val_field; - typedef esbmct::field_traits - heap_update_data_byte_len_field; - typedef esbmct::expr2t_traits - < - heap_update_data_src_heap_field, heap_update_data_start_addr_field, heap_update_data_updated_val_field, heap_update_data_byte_len_field - > traits; - + typedef esbmct::field_traits + source_heap_field; + typedef esbmct::field_traits + update_field_field; + typedef esbmct::field_traits + update_value_field; + typedef esbmct::expr2t_traits traits; }; class heap_append_data : public expr2t { @@ -1137,34 +1138,21 @@ class heap_append_data : public expr2t { heap_append_data( const type2tc & t, datatype_ops::expr_ids id, - expr2tc original_heap, - expr2tc start_addr, - expr2tc create_val, - unsigned int byte_len) - : expr2t(t, id), src_heap(original_heap), start_addr(start_addr), create_val(create_val), byte_len(byte_len) + const expr2tc &sh, + const expr2tc &ht) + : expr2t(t, id), source_heap(sh), heap_term(ht) { } - expr2tc src_heap; - expr2tc start_addr; - expr2tc create_val; - unsigned int byte_len; - - - // Type mangling: - typedef esbmct::field_traits - heap_append_data_src_heap_field; - typedef esbmct::field_traits - heap_append_data_start_addr_field; - typedef esbmct::field_traits - heap_append_data_create_val_field; - typedef esbmct::field_traits - heap_append_data_byte_len_field; - typedef esbmct::expr2t_traits - < - heap_append_data_src_heap_field, heap_append_data_start_addr_field, heap_append_data_create_val_field, heap_append_data_byte_len_field - > traits; + expr2tc source_heap; + expr2tc heap_term; + // Type mangling: + typedef esbmct::field_traits + source_heap_field; + typedef esbmct::field_traits + heap_term_field; + typedef esbmct::expr2t_traits traits; }; class heap_delete_data : public expr2t { @@ -1172,30 +1160,21 @@ class heap_delete_data : public expr2t { heap_delete_data( const type2tc & t, datatype_ops::expr_ids id, - expr2tc original_heap, - expr2tc del_addr, - unsigned int byte_len) - : expr2t(t, id), src_heap(original_heap), del_addr(del_addr), byte_len(byte_len) + const expr2tc &sh, + const expr2tc &l) + : expr2t(t, id), source_heap(sh), location(l) { } - expr2tc src_heap; - expr2tc del_addr; - unsigned int byte_len; - - - // Type mangling: - typedef esbmct::field_traits - heap_delete_data_src_heap_field; - typedef esbmct::field_traits - heap_delete_data_del_addr_field; - typedef esbmct::field_traits - heap_delete_data_byte_len_field; - typedef esbmct::expr2t_traits - < - heap_delete_data_src_heap_field, heap_delete_data_del_addr_field, heap_delete_data_byte_len_field - > traits; + expr2tc source_heap; + expr2tc location; + // Type mangling: + typedef esbmct::field_traits + source_heap_field; + typedef esbmct::field_traits + location_field; + typedef esbmct::expr2t_traits traits; }; class heap_contains_data : public expr2t { @@ -1203,31 +1182,25 @@ class heap_contains_data : public expr2t { heap_contains_data( const type2tc &t, datatype_ops::expr_ids id, - expr2tc hterm, - expr2tc heap, - unsigned int byte_len) - : expr2t(t, id), hterm(hterm), heap(heap), byte_len(byte_len) + const expr2tc &l, + const expr2tc &h) + : expr2t(t, id), location(l), heap(h) { } - expr2tc hterm; + expr2tc location; expr2tc heap; - unsigned int byte_len; //Type mangling: - typedef esbmct::field_traits - heap_contains_data_hterm_field; + typedef esbmct::field_traits + location_field; typedef esbmct::field_traits - heap_contains_data_heap_field; - typedef esbmct::field_traits - heap_contains_data_byte_len_field; - - typedef esbmct::expr2t_traits< - heap_contains_data_hterm_field, - heap_contains_data_heap_field, - heap_contains_data_byte_len_field> traits; + heap_field; + typedef esbmct::expr2t_traits traits; }; +/* ================================ SLHV ================================ */ + class string_ops : public expr2t { public: @@ -1858,12 +1831,14 @@ irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); irep_typedefs(heap_region, heap_region_data); +irep_typedefs(locationof, locationof_data); +irep_typedefs(fieldof, fieldof_data); irep_typedefs(pointer_with_region, pointer_with_region_data); irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); irep_typedefs(heap_delete, heap_delete_data); -irep_typedefs(heap_contains, heap_contains_data); +irep_typedefs(heap_contain, heap_contains_data); irep_typedefs(isnan, bool_1op); irep_typedefs(overflow, overflow_ops); irep_typedefs(overflow_cast, overflow_cast_data); @@ -3326,11 +3301,13 @@ class index2t : public index_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +/* ================================ SLHV ================================ */ + class points_to2t : public points_to_expr_methods { public: - points_to2t(const expr2tc &addr, const expr2tc &content) - : points_to_expr_methods(get_intheap_type(), points_to_id, addr, content) + points_to2t(const expr2tc &location, const expr2tc &content) + : points_to_expr_methods(get_intheap_type(), points_to_id, location, content) { } points_to2t(const points_to2t &ref) = default; @@ -3338,12 +3315,11 @@ class points_to2t : public points_to_expr_methods static std::string field_names[esbmct::num_type_fields]; }; - class uplus2t : public uplus_expr_methods { public: - uplus2t(std::vector uplus_members) - : uplus_expr_methods(get_intheap_type(), uplus_id, std::move(uplus_members), uplus_members.size()) + uplus2t(const std::vector &heap_terms) + : uplus_expr_methods(get_intheap_type(), uplus_id, heap_terms) { } uplus2t(const uplus2t &ref) = default; @@ -3354,38 +3330,60 @@ class uplus2t : public uplus_expr_methods class locadd2t : public locadd_expr_methods { public: - locadd2t(const expr2tc &loc, const expr2tc &offset) - : locadd_expr_methods(get_intloc_type(), locadd_id, loc, offset) + locadd2t(const expr2tc &location, const expr2tc &offset) + : locadd_expr_methods(get_intloc_type(), locadd_id, location, offset) { } locadd2t(const locadd2t &ref) = default; - std::string offset_as_string() const; - static std::string field_names[esbmct::num_type_fields]; }; -class heap_region2t: public heap_region_expr_methods +class heap_region2t : public heap_region_expr_methods { public: heap_region2t( + const type2tc &type, const expr2tc &flag, - const expr2tc &start_loc, - const expr2tc &pt_bytes, - const expr2tc &size, - bool is_split) - : heap_region_expr_methods( - get_intheap_type(), heap_region_id, - flag, start_loc, pt_bytes, size, is_split) + const expr2tc &source_location) + : heap_region_expr_methods(type, heap_region_id, flag, source_location) { } heap_region2t(const heap_region2t &ref) = default; - bool update(uint byte_len); + // bool update(uint byte_len); + + static std::string field_names[esbmct::num_type_fields]; +}; + +class locationof2t : public locationof_expr_methods +{ +public: + locationof2t(const expr2tc &heap_term) + : locationof_expr_methods(get_intloc_type(), locationof_id, heap_term) + { + } + locationof2t(const locationof2t &ref) = default; + + static std::string field_names[esbmct::num_type_fields]; +}; + +class fieldof2t : public fieldof_expr_methods +{ +public: + fieldof2t( + const type2tc &type, + const expr2tc &heap_region, + const expr2tc &field) + : fieldof_expr_methods(type, fieldof_id, heap_region, field) + { + } + fieldof2t(const fieldof2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; }; +// maybe deprecated class pointer_with_region2t : public pointer_with_region_expr_methods { public: @@ -3397,17 +3395,19 @@ class pointer_with_region2t : public pointer_with_region_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +// maybe deprecated class heap_load2t : public heap_load_expr_methods { public: heap_load2t( - const type2tc &type, + const type2tc &type, + const expr2tc &flag, const expr2tc &heap, const expr2tc &start_loc, unsigned int byte_len) : heap_load_expr_methods( type, expr2t::heap_load_id, - heap, start_loc, byte_len) + flag, heap, start_loc, byte_len) { } heap_load2t(const heap_load2t& ref) = default; @@ -3418,8 +3418,14 @@ class heap_load2t : public heap_load_expr_methods class heap_update2t : public heap_update_expr_methods { public: - heap_update2t(expr2tc source_heap, expr2tc start_addr, expr2tc updated_val, unsigned int byte_len) - : heap_update_expr_methods(get_intheap_type(), heap_update_id, source_heap, start_addr, updated_val, byte_len) + heap_update2t( + const type2tc &type, + const expr2tc &source_heap, + const expr2tc &update_field, + const expr2tc &update_value) + : heap_update_expr_methods( + type, heap_update_id, + source_heap, update_field, update_value) { } heap_update2t(const heap_update2t &ref) = default; @@ -3430,8 +3436,12 @@ class heap_update2t : public heap_update_expr_methods class heap_append2t : public heap_append_expr_methods { public: - heap_append2t(expr2tc source_heap, expr2tc start_addr, expr2tc create_val, unsigned int byte_len) - : heap_append_expr_methods(get_intheap_type(), heap_append_id, source_heap, start_addr, create_val, byte_len) + heap_append2t( + const expr2tc &source_heap, + const expr2tc &heap_term) + : heap_append_expr_methods( + get_intheap_type(), heap_append_id, + source_heap, heap_term) { } heap_append2t(const heap_append2t &ref) = default; @@ -3442,8 +3452,11 @@ class heap_append2t : public heap_append_expr_methods class heap_delete2t : public heap_delete_expr_methods { public: - heap_delete2t(expr2tc source_heap, expr2tc del_addr, unsigned int byte_len) - : heap_delete_expr_methods(get_intheap_type(), heap_delete_id, source_heap, del_addr, byte_len) + heap_delete2t( + const expr2tc &source_heap, + const expr2tc &location) + : heap_delete_expr_methods( + get_intheap_type(), heap_delete_id, source_heap, location) { } heap_delete2t(const heap_delete2t &ref) = default; @@ -3451,18 +3464,21 @@ class heap_delete2t : public heap_delete_expr_methods static std::string field_names[esbmct::num_type_fields]; }; -class heap_contains2t : public heap_contains_expr_methods +class heap_contain2t : public heap_contain_expr_methods { public: - heap_contains2t(expr2tc hterm, expr2tc heap, unsigned int byte_len) - : heap_contains_expr_methods(get_bool_type(), heap_contains_id, hterm, heap, byte_len) + heap_contain2t( + const expr2tc &location, const expr2tc &heap) + : heap_contain_expr_methods(get_bool_type(), heap_contain_id, location, heap) { } - heap_contains2t(const heap_contains2t &ref) = default; + heap_contain2t(const heap_contain2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; }; +/* ================================ SLHV ================================ */ + /** Is operand not-a-number. Used to implement C library isnan function for * float/double values. Boolean result. @extends arith_1op */ class isnan2t : public isnan_expr_methods diff --git a/src/irep2/irep2_type.cpp b/src/irep2/irep2_type.cpp index 2a97b80e..099d6b28 100644 --- a/src/irep2/irep2_type.cpp +++ b/src/irep2/irep2_type.cpp @@ -183,10 +183,42 @@ unsigned int empty_type2t::get_width() const { throw symbolic_type_excp(); } + unsigned int intheap_type2t::get_width() const { throw symbolic_type_excp(); } + +bool intheap_type2t::do_alignment(unsigned int access_sz) +{ + if (is_aligned) return false; + if (total_bytes % access_sz != 0) + { + log_error("Do not support unaligned access"); + abort(); + } + unsigned int num_of_fields = total_bytes / access_sz; + if (!field_types.empty()) field_types.clear(); + for (unsigned int i = 0; i < num_of_fields; i++) + field_types.push_back(get_empty_type()); + is_aligned = true; + return true; +} + +bool intheap_type2t::set_field_type(unsigned int field, const type2tc &type) +{ + if (field >= field_types.size()) + { + log_error("Out of fields size"); + abort(); + } + if (!is_empty_type(field_types[field])) return false; + field_types[field] = + (is_pointer_type(type) || is_intloc_type(type)) ? + get_intloc_type() : get_int64_type(); + return true; +} + unsigned int intloc_type2t::get_width() const { throw symbolic_type_excp(); diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index a57692c0..11391eb7 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -203,6 +203,41 @@ class array_data : public type2t traits; }; +class intheap_data : public type2t +{ +public: + intheap_data( + type2t::type_ids id, + const std::vector &ft, + unsigned int tb, + bool ir, + bool ia) + : type2t(id), field_types(ft), total_bytes(tb), + is_region(ir), is_aligned(ia) + { + } + intheap_data(const intheap_data &ref) = default; + + std::vector field_types; + unsigned int total_bytes; + bool is_region; + bool is_aligned; + + // Type mangling: + typedef esbmct::field_traits, intheap_data, &intheap_data::field_types> + field_types_field; + typedef esbmct::field_traits + total_bytes_field; + typedef esbmct::field_traits + is_region_field; + typedef esbmct::field_traits + is_aligned_field; + typedef esbmct::type2t_traits< + field_types_field, + total_bytes_field, + is_region_field, + is_aligned_field> traits; +}; class pointer_data : public type2t { @@ -319,7 +354,7 @@ irep_typedefs(fixedbv, fixedbv_data); irep_typedefs(floatbv, floatbv_data); irep_typedefs(cpp_name, cpp_name_data); irep_typedefs(vector, array_data); -irep_typedefs(intheap, type2t); +irep_typedefs(intheap, intheap_data); irep_typedefs(intloc, type2t); #undef irep_typedefs @@ -358,12 +393,20 @@ class empty_type2t : public empty_type_methods class intheap_type2t : public intheap_type_methods { public: - intheap_type2t() : intheap_type_methods(intheap_id) + intheap_type2t( + const std::vector &field_types, + unsigned int total_bytes, + bool is_region, + bool is_aligned) + : intheap_type_methods(intheap_id, field_types, total_bytes, is_region, is_aligned) { } intheap_type2t(const intheap_type2t &ref) = default; unsigned int get_width() const override; + bool do_alignment(unsigned int access_sz); + bool set_field_type(unsigned int field, const type2tc &type); + static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 89a4fd7e..8e73edf8 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -197,7 +197,7 @@ inline bool is_slhv_expr(const expr2tc &expr) is_locadd2t(expr) || is_pointer_with_region2t(expr) || is_heap_append2t(expr) || - is_heap_contains2t(expr) || + is_heap_contain2t(expr) || is_heap_delete2t(expr) || is_heap_load2t(expr) || is_heap_region2t(expr) || diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 0b23396c..29b6cec3 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -12,7 +12,7 @@ std::string empty_type2t::field_names[esbmct::num_type_fields] = std::string intloc_type2t::field_names[esbmct::num_type_fields] = {"", "", "", "", ""}; std::string intheap_type2t::field_names[esbmct::num_type_fields] = - {"", "", "", "", ""}; + {"field_types", "total_bytes", "is_region", "is_aligned", ""}; std::string symbol_type2t::field_names[esbmct::num_type_fields] = {"symbol_name", "", "", "", ""}; std::string struct_type2t::field_names[esbmct::num_type_fields] = @@ -163,25 +163,29 @@ std::string member2t::field_names[esbmct::num_type_fields] = std::string index2t::field_names[esbmct::num_type_fields] = {"source_value", "index", "", "", ""}; std::string points_to2t::field_names[esbmct::num_type_fields] = -{"addr", "content", "", "", ""}; + {"location", "content", "", "", ""}; std::string uplus2t::field_names[esbmct::num_type_fields] = -{"uplus_members", "uplus_num", "", "", ""}; + {"heap_terms", "", "", "", ""}; std::string locadd2t::field_names[esbmct::num_type_fields] = -{"loc", "offset", "", "", ""}; + {"location", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = -{"flag", "start_loc", "pt_bytes", "size", "is_split"}; + {"flag", "source_location", "", "", ""}; +std::string locationof2t::field_names[esbmct::num_type_fields] = + {"heap_term", "", "", "", ""}; +std::string fieldof2t::field_names[esbmct::num_type_fields] = + {"heap_region", "field", "", "", ""}; std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = -{"loc_ptr", "region", "", "", ""}; + {"loc_ptr", "region", "", "", ""}; std::string heap_load2t::field_names[esbmct::num_type_fields] = -{"src_heap", "start_loc", "byte_len", "", ""}; + {"src_heap", "start_loc", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = -{"src_heap", "start_addr", "updated_val", "byte_len", ""}; + {"source_heap", "update_field", "update_val", "", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = -{"src_heap", "start_addr", "create_val", "byte_len", ""}; + {"source_heap", "heap_term", "", "", ""}; std::string heap_delete2t::field_names[esbmct::num_type_fields] = -{"src_heap", "del_addr", "byte_len", "", ""}; -std::string heap_contains2t::field_names[esbmct::num_type_fields] = -{"hterm", "heap", "byte_len", "", ""}; + {"source_heap", "location", "", "", ""}; +std::string heap_contain2t::field_names[esbmct::num_type_fields] = + {"location", "heap", "", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string overflow2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 62b3c10a..a9946854 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -32,13 +32,15 @@ expr_typedefs2(index, index_data); expr_typedefs2(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); -expr_typedefs5(heap_region, heap_region_data); +expr_typedefs3(heap_region, heap_region_data); +expr_typedefs1(locationof, locationof_data); +expr_typedefs3(fieldof, fieldof_data); expr_typedefs2(pointer_with_region, pointer_with_region_data); expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); -expr_typedefs4(heap_append, heap_append_data); -expr_typedefs3(heap_delete, heap_delete_data); -expr_typedefs3(heap_contains, heap_contains_data); +expr_typedefs2(heap_append, heap_append_data); +expr_typedefs2(heap_delete, heap_delete_data); +expr_typedefs2(heap_contain, heap_contains_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); expr_typedefs2(dereference, dereference_data); diff --git a/src/irep2/templates/irep2_templates_type.cpp b/src/irep2/templates/irep2_templates_type.cpp index 6e7307a4..6e6efbc3 100644 --- a/src/irep2/templates/irep2_templates_type.cpp +++ b/src/irep2/templates/irep2_templates_type.cpp @@ -2,7 +2,7 @@ type_typedefs_empty(bool_type, type2t); type_typedefs_empty(empty_type, type2t); -type_typedefs_empty(intheap_type, type2t); +type_typedefs4(intheap_type, intheap_data); type_typedefs_empty(intloc_type, type2t); type_typedefs1(symbol_type, symbol_type_data); type_typedefs5(struct_type, struct_union_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index bf4267ae..3f5ab91b 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -137,10 +137,6 @@ const expr2tc &dereferencet::get_symbol(const expr2tc &expr) return expr; } -const expr2tc &get_heap_symbol(const expr2tc &object) { - -} - /************************* Expression decomposing code ************************/ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) @@ -157,7 +153,6 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) case expr2t::if_id: dereference_guard_expr(expr, guard, mode); break; - case expr2t::address_of_id: dereference_addrof_expr(expr, guard, mode); break; @@ -192,7 +187,6 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) expr = res; break; } - default: { // Recurse over the operands @@ -289,8 +283,6 @@ void dereferencet::dereference_addrof_expr( // this has *no* side effect! address_of2t &addrof = to_address_of2t(expr); - if (is_heap_region2t(addrof.ptr_obj)) return; - if (is_dereference2t(addrof.ptr_obj)) { dereference2t &deref = to_dereference2t(addrof.ptr_obj); @@ -484,6 +476,7 @@ expr2tc dereferencet::dereference( // collect objects dest may point to value_setst::valuest points_to_set; + log_status("---- value set for "); src->dump(); dereference_callback.get_value_set(src, points_to_set); @@ -814,25 +807,29 @@ expr2tc dereferencet::build_reference_to( // type2tc ptr_type = pointer_type2tc(object->type); // expr2tc obj_ptr = typecast2tc(ptr_type, object); - log_status("befor building pointer guard"); - object->dump(); + log_status("before building pointer guard"); + value->dump(); deref_expr->dump(); type->dump(); guardt tmp_guard(guard); - if (is_heap_region2t(object)) + if (is_heap_region2t(value)) { heap_region2t& heap_region = to_heap_region2t(value); if (!is_free(mode) && !is_internal(mode)) { - int access_sz = type_byte_size(type).to_uint64(); - // Update its pt bytes - if (heap_region.update(access_sz)) - dereference_callback.update_regions(value); + int access_sz = type->get_width() / 8; + // Do alignment + intheap_type2t &_type = to_intheap_type(heap_region.type); + bool has_changed = _type.do_alignment(access_sz); + if (false) + { + to_symbol2t(heap_region.flag).type = heap_region.type; + dereference_callback.update_heap_type(heap_region.flag); + } } - - pointer_guard = same_object2tc(deref_expr, object); + pointer_guard = same_object2tc(deref_expr, value); tmp_guard.add(pointer_guard); } else @@ -841,12 +838,13 @@ expr2tc dereferencet::build_reference_to( abort(); } + log_status("generated pointer guard:"); pointer_guard->dump(); // Check that the object we're accessing is actually alive and valid for this // mode. - valid_check(object, tmp_guard, mode); + valid_check(value, tmp_guard, mode); log_status("finish checking"); @@ -902,11 +900,11 @@ expr2tc dereferencet::build_reference_to( } else { + if (!is_nil_expr(lexical_offset)) + final_offset = add2tc(final_offset->type, final_offset, lexical_offset); + if (!is_constant_int2t(final_offset)) - { - final_offset = deref_expr; - } - // TODO: add lexical offset + final_offset = final_offset.simplify(); } // If we're in internal mode, collect all of our data into one struct, insert @@ -1276,28 +1274,25 @@ void dereferencet::build_reference_slhv( offset->dump(); assert(is_heap_region2t(value)); if(is_scalar_type(type)) { - if (!is_constant_int2t(offset)) offset.simplify(); - assert(is_constant_int2t(offset)); - int offset_bytes = to_constant_int2t(offset).value.to_uint64(); - + if (!is_constant_int2t(offset)) + { + log_error("Do not support non-constant offset"); + abort(); + } + + unsigned int field = to_constant_int2t(offset).value.to_uint64(); heap_region2t& heap_region = to_heap_region2t(value); - expr2tc heap = heap_region.flag; - int access_sz = type_byte_size(type).to_uint64(); - expr2tc access_ptr; - if (offset_bytes == 0) - access_ptr = heap_region.start_loc; - else - { - assert(offset_bytes % access_sz == 0); - int offset_pt = offset_bytes / access_sz; - access_ptr = locadd2tc( - heap_region.start_loc, - gen_long(get_int64_type(), offset_pt) - ); + intheap_type2t &_type = to_intheap_type(heap_region.type); + if (_type.set_field_type(field, type)) + { + heap_region.flag->type = heap_region.type; + dereference_callback.update_heap_type(heap_region.flag); } - value = heap_load2tc(type, heap, access_ptr, access_sz); + expr2tc heap = heap_region.flag; + + value = fieldof2tc(type, value, gen_ulong(field)); } else { log_error("ERROR: currently not support non-scalar type dereference"); abort(); @@ -2570,8 +2565,7 @@ void dereferencet::check_heap_region_access( assert(is_heap_region2t(value)); const heap_region2t& heap_region = to_heap_region2t(value); - heap_region.pt_bytes->dump(); - heap_region.size->dump(); + heap_region.type->dump(); expr2tc offset_e = offset; if (!is_constant_int2t(offset_e) && is_signedbv_type(offset_e)) @@ -2579,13 +2573,13 @@ void dereferencet::check_heap_region_access( std::string sz_id = dereference_callback.get_nondet_id("nondet_region_size::"); expr2tc sz = symbol2tc(get_uint64_type(), sz_id); - expr2tc sz_pt = points_to2tc(heap_region.start_loc, sz); + expr2tc sz_pt = points_to2tc(heap_region.source_location, sz); expr2tc alloc_size_heap; migrate_expr( symbol_expr( - *ns.lookup(dereference_callback.get_alooc_size_heap_name())), + *ns.lookup(dereference_callback.get_alloc_size_heap_name())), alloc_size_heap); - expr2tc heap_ct = heap_contains2tc(sz_pt, alloc_size_heap, 1); + expr2tc heap_ct = heap_contain2tc(sz_pt, alloc_size_heap); expr2tc data_sz = gen_ulong(type->get_width()); expr2tc offset_check; @@ -2611,7 +2605,7 @@ void dereferencet::check_heap_region_access( std::string nondet_off_id = dereference_callback.get_nondet_id("nondet_off::"); expr2tc off_var = symbol2tc(get_uint64_type(), nondet_off_id); - expr2tc target_loc = locadd2tc(heap_region.start_loc, off_var); + expr2tc target_loc = locadd2tc(heap_region.source_location, off_var); expr2tc offset_loc = locadd2tc(ptr, off_var); expr2tc eq = equality2tc(target_loc, offset_loc); expr2tc ge = greaterthanequal2tc(off_var, gen_ulong(0)); diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 840ceb52..e1afbff1 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -153,22 +153,14 @@ class dereference_callbackt * */ virtual bool is_live_variable(const expr2tc &sym) = 0; - /** Update regionss in value set and in eq system - * @param region - */ - virtual void update_regions(const expr2tc ®ion) - { - log_error("Do not support"); - abort(); - } - virtual void update_heap_region_rec(expr2tc &expr, const expr2tc ®ion) + virtual void update_heap_type(const expr2tc &flag) { log_error("Do not support"); abort(); } - virtual std::string get_loaded_value_flag(const expr2tc &expr) + virtual void update_heap_type_rec(expr2tc &expr, const symbol2t &flag) { log_error("Do not support"); abort(); @@ -180,7 +172,7 @@ class dereference_callbackt abort(); } - virtual irep_idt get_alooc_size_heap_name() + virtual irep_idt get_alloc_size_heap_name() { log_error("Do not support"); abort(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 3fb7c7f5..a43997a4 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -203,13 +203,6 @@ void value_sett::get_value_set(const expr2tc &expr, object_mapt &dest) const // Then, start fetching values. get_value_set_rec(new_expr, dest, "", new_expr->type); - - // Convert values into expressions to return. - log_status("result value set:"); - for (object_mapt::const_iterator it = dest.begin(); - it != dest.end(); - it++) - to_expr(it)->dump(); } void value_sett::get_value_set_rec( @@ -565,12 +558,15 @@ void value_sett::get_value_set_rec( if (v_it != values.end()) { make_union(dest, v_it->second.object_map); + log_status("points_to somthing"); + for (auto obj : dest) + object_numbering[obj.first]->dump(); return; } } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || - is_heap_region2t(expr) || is_heap_update2t(expr) || is_heap_append2t(expr)) + is_heap_region2t(expr) || is_heap_append2t(expr)) { log_status("get value set rec: SLHV"); expr2tc new_object = expr; @@ -581,40 +577,68 @@ void value_sett::get_value_set_rec( if (is_locadd2t(expr)) { const locadd2t& locadd = to_locadd2t(expr); - expr2tc base_ptr = locadd.loc; - expr2tc off = locadd.offset; - - if ((!is_pointer_type(base_ptr) && !is_intloc_type(base_ptr)) || - is_pointer_type(off) || is_intloc_type(off)) - { - log_error("Wrong locadd expr"); - abort(); - } - - // Do not need to update offset in SLHV - log_status("here"); - get_value_set_rec(base_ptr, dest, suffix, original_type); - return; + assert(is_intloc_type(locadd.location)); + abort(); + // TODO } - if (is_pointer_with_region2t(expr)) + if (is_locationof2t(expr)) { get_value_set_rec( - to_pointer_with_region2t(expr).region, + to_locationof2t(expr).heap_term, dest, suffix, original_type ); return; } - if (is_heap_load2t(expr)) + if (is_fieldof2t(expr)) { + const fieldof2t &fieldof = to_fieldof2t(expr); + const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + expr2tc field = fieldof.field; + + if (!is_constant_int2t(field)) + { + log_error("Do not support dynamic offset yet"); + abort(); + } + + std::string str_field = + std::to_string(to_constant_int2t(field).value.to_uint64()); + get_value_set_rec( - to_heap_load2t(expr).start_loc, - dest, suffix, original_type + heap_region.flag, + dest, + "::field::" + str_field + "::" + suffix, + original_type ); return; } + if (is_heap_update2t(expr)) + { + log_status("finish get_value_set_rec heap_update"); + abort(); + } + + // if (is_pointer_with_region2t(expr)) + // { + // get_value_set_rec( + // to_pointer_with_region2t(expr).region, + // dest, suffix, original_type + // ); + // return; + // } + + // if (is_heap_load2t(expr)) + // { + // get_value_set_rec( + // to_heap_load2t(expr).flag, + // dest, suffix, original_type + // ); + // return; + // } + if (is_add2t(expr) || is_sub2t(expr)) { // Consider pointer arithmetic. This takes takes the form of finding the @@ -1178,7 +1202,6 @@ void value_sett::assign( if (is_array_type(lhs_type)) { - log_status("value set assign: lhs is_array_type"); const array_type2t &arr_type = to_array_type(lhs_type); expr2tc unknown = unknown2tc( arr_type.array_size ? arr_type.array_size->type : index_type2()); @@ -1225,6 +1248,18 @@ void value_sett::assign( return; } + if (is_intheap_type(lhs_type)) + { + if (to_intheap_type(lhs_type).is_region && is_heap_update2t(rhs)) + { + const heap_update2t &heap_upd = to_heap_update2t(rhs); + expr2tc lhs_field = + fieldof2tc(rhs->type, heap_upd.source_heap, heap_upd.update_field); + assign(lhs_field, heap_upd.update_value, true); + return; + } + } + // basic type object_mapt values_rhs; get_value_set(rhs, values_rhs); @@ -1376,6 +1411,27 @@ void value_sett::assign_rec( "." + component_name + suffix, add_to_sets); } + else if (is_fieldof2t(lhs)) + { + const fieldof2t &fieldof = to_fieldof2t(lhs); + + expr2tc field = fieldof.field; + if (!is_constant_int2t(field)) + { + log_error("Do not support dynamic offset yet"); + abort(); + } + std::string str_field = + std::to_string(to_constant_int2t(field).value.to_uint64()); + + const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + + assign_rec( + heap_region.flag, + values_rhs, + "::field::" + str_field + "::" + suffix, + add_to_sets); + } else if ( is_constant_string2t(lhs) || is_null_object2t(lhs) || is_valid_object2t(lhs) || is_deallocated_obj2t(lhs) || diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index a2d56bfb..4c82379b 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -333,20 +333,24 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) log_status("begin convert expr"); expr->dump(); + log_status("done"); smt_astt a; + switch (expr->expr_id) { case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: case expr2t::heap_region_id: + case expr2t::locationof_id: + case expr2t::fieldof_id: case expr2t::pointer_with_region_id: case expr2t::points_to_id: case expr2t::uplus_id: case expr2t::locadd_id: case expr2t::heap_update_id: case expr2t::heap_load_id: - case expr2t::heap_contains_id: + case expr2t::heap_contain_id: case expr2t::heap_append_id: case expr2t::heap_delete_id: { a = convert_slhv_opts(expr, args); diff --git a/src/solvers/smt/smt_memspace.cpp b/src/solvers/smt/smt_memspace.cpp index d34459f7..9e4f64de 100644 --- a/src/solvers/smt/smt_memspace.cpp +++ b/src/solvers/smt/smt_memspace.cpp @@ -539,12 +539,6 @@ smt_astt smt_convt::convert_addr_of(const expr2tc &expr) return convert_ast(tmp); } - if (is_heap_region2t(obj.ptr_obj)) - { - convert_ast(obj.ptr_obj); - return convert_ast(to_heap_region2t(obj.ptr_obj).start_loc); - } - log_error("Unrecognized address_of operand:\n{}", *expr); abort(); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 4993d0cb..dd74055c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -159,7 +159,6 @@ smt_sortt z3_slhv_convt::mk_intloc_sort() { } smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) { - assert(is_intloc_type(type)); return mk_intloc_sort(); } @@ -191,30 +190,104 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { smt_astt z3_slhv_convt::convert_slhv_opts( - const expr2tc &expr, const std::vector& args) { - switch (expr->expr_id) { - case expr2t::constant_intheap_id: return mk_emp(); - case expr2t::constant_intloc_id: return mk_nil(); + const expr2tc &expr, const std::vector& args) +{ + switch (expr->expr_id) + { + case expr2t::constant_intheap_id: + return mk_emp(); + case expr2t::constant_intloc_id: + return mk_nil(); case expr2t::heap_region_id: { log_status("convert heap region"); - assert(args.size() == 4); - const heap_region2t& region = to_heap_region2t(expr); - region.dump(); - assert(is_constant_int2t(region.size)); - const int n = to_constant_int2t(region.size).as_ulong(); + const intheap_type2t &type = to_intheap_type(expr->type); std::vector pt_vec; - for (unsigned i = 0; i < n; i++) { - smt_astt loc = i == 0 ? args[1] : mk_locadd(args[1], mk_smt_int(BigInt(i))); - smt_astt v = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - pt_vec.push_back(mk_pt(loc, v)); + if (type.is_aligned) + { + for (unsigned i = 0; i < type.field_types.size(); i++) { + smt_astt loc = i == 0 ? args[1] : mk_locadd(args[1], mk_smt_int(BigInt(i))); + smt_sortt sort = + is_intloc_type(type.field_types[i]) ? + mk_intloc_sort() : mk_int_sort(); + std::string name = + mk_fresh_name( + is_intloc_type(type.field_types[i]) ? + "tmp_loc::" : "tmp_val::"); + smt_astt v = mk_fresh(sort, name); + pt_vec.push_back(mk_pt(loc, v)); + } + } + else + { + // Default sort is intloc + pt_vec.push_back( + mk_pt( + args[1], + mk_fresh(mk_intloc_sort(), mk_fresh_name("tmp_loc::") + ) + ) + ); } return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); } - case expr2t::pointer_with_region_id: + case expr2t::locationof_id: + { + const locationof2t &locof = to_locationof2t(expr); + if (!is_heap_region2t(locof.heap_term)) + { + log_error("We can't get a location of a non-region heap"); + abort(); + } + return convert_ast(to_heap_region2t(locof.heap_term).source_location); + } + case expr2t::fieldof_id: { - return convert_ast(to_pointer_with_region2t(expr).loc_ptr); + const fieldof2t &fieldof = to_fieldof2t(expr); + + if (is_constant_intheap2t(fieldof.heap_region)) + return mk_fresh( + convert_sort(fieldof.type), + mk_fresh_name("invalid_loc_")); + + if (!is_heap_region2t(fieldof.heap_region)) + { + log_error("We can't get a location of a non-region heap"); + abort(); + } + if (!is_constant_int2t(fieldof.field)) + { + log_error("Wrong field"); + abort(); + } + unsigned int field = to_constant_int2t(fieldof.field).value.to_uint64(); + + // TODO : do more analysis + const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + const intheap_type2t &_type = to_intheap_type(heap_region.type); + + smt_astt source_loc = convert_ast(heap_region.source_location); + smt_astt loc = field == 0 ? + source_loc : mk_locadd(source_loc, convert_ast(fieldof.field)); + + smt_sortt s1; + std::string name; + if (!_type.is_aligned) + { + s1 = mk_intloc_sort(); + name = mk_fresh_name("tmp_loc::"); + } + else + { + s1 = is_intloc_type(_type.field_types[field]) ? mk_intloc_sort() : mk_int_sort(); + name = mk_fresh_name( + is_intloc_type(_type.field_types[field]) ? "tmp_loc::" : "tmp_val::"); + } + smt_astt v1 = mk_fresh(s1, name); + + assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region.flag))); + return v1; } case expr2t::points_to_id: { @@ -239,9 +312,6 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_append_id: { - const heap_append2t& heap_app = to_heap_append2t(expr); - // TODO : fix width - assert(heap_app.byte_len == 4); smt_astt h = args[0]; smt_astt adr = args[1]; smt_astt val = args[2]; @@ -250,51 +320,34 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_update_id: { - const heap_update2t& heap_upd = to_heap_update2t(expr); - // TODO : fix width - assert(heap_upd.byte_len == 4); - smt_astt h = args[0]; - smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); - smt_astt adr = args[1]; + const heap_update2t &heap_upd = to_heap_update2t(expr); + const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_heap); + smt_astt h = convert_ast(heap_region.flag); + + smt_astt source_loc = convert_ast(heap_region.source_location); + smt_astt field = convert_ast(heap_upd.update_field); + smt_astt loc = mk_locadd(source_loc, field); smt_astt val = args[2]; + + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); // current heap state - smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(adr, v1), h1)); + smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(loc, v1), h1)); assert_ast(o_state); // new heap state - return mk_uplus(mk_pt(adr, val), h1); - } - case expr2t::heap_load_id: - { - const heap_load2t& heap_load = to_heap_load2t(expr); - // TODO : fix width - // assert(heap_load.byte_len == 4); - //current heap state - - smt_astt v1; - - if (is_pointer_type(heap_load.type) || is_intloc_type(heap_load.type)) - v1 = mk_fresh(mk_intloc_sort(), mk_fresh_name("tmp_loc::")); - else - v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - - assert_ast(mk_subh(mk_pt(args[1], v1), args[0])); - return v1; + return mk_uplus(mk_pt(loc, val), h1); } - case expr2t::heap_contains_id: + case expr2t::heap_contain_id: { - const heap_contains2t& heap_ct = to_heap_contains2t(expr); - // TODO : fix width - // assert(heap_ct.byte_len == 4); + const heap_contain2t& heap_ct = to_heap_contain2t(expr); smt_astt sh; - if (is_symbol2t(heap_ct.hterm) || - is_pointer_with_region2t(heap_ct.hterm) || - is_pointer_object2t(heap_ct.hterm)) + if (is_symbol2t(heap_ct.location) || + is_pointer_object2t(heap_ct.location)) { sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); // TODO : support multiple loaded } - else if (is_points_to2t(heap_ct.hterm)) + else if (is_points_to2t(heap_ct.location)) { sh = args[0]; } @@ -324,23 +377,22 @@ z3_slhv_convt::convert_slhv_opts( smt_astt z3_slhv_convt::project(const expr2tc &expr) { - if (is_symbol2t(expr) || - is_constant_intheap2t(expr) || - is_constant_intloc2t(expr)) - return convert_ast(expr); - else if (is_pointer_with_region2t(expr)) + + if (is_symbol2t(expr)) return convert_ast(expr); else if (is_heap_region2t(expr)) - return convert_ast(to_heap_region2t(expr).start_loc); - else if (is_heap_load2t(expr)) - return project(to_heap_load2t(expr).start_loc); + return this->project(to_heap_region2t(expr).source_location); + else if (is_locationof2t(expr)) + return this->project(to_locationof2t(expr).heap_term); + else if (is_fieldof2t(expr)) + return this->project(to_fieldof2t(expr).heap_region); else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); else if (is_locadd2t(expr) || is_add2t(expr) || is_sub2t(expr)) { expr2tc ptr; if (is_locadd2t(expr)) - ptr = to_locadd2t(expr).loc; + ptr = to_locadd2t(expr).location; else if (is_add2t(expr)) ptr = (is_pointer_type(to_add2t(expr).side_1) || is_intloc_type(to_add2t(expr).side_1))? to_add2t(expr).side_1 : to_add2t(expr).side_2; diff --git a/src/util/c_types.cpp b/src/util/c_types.cpp index 53da0d67..51183b95 100644 --- a/src/util/c_types.cpp +++ b/src/util/c_types.cpp @@ -394,9 +394,10 @@ type2tc get_empty_type() return empty_type; } -type2tc get_intheap_type() { - static type2tc intheap_type = intheap_type2tc(); - return intheap_type; +type2tc get_intheap_type(unsigned int sz) +{ + std::vector field_types; + return intheap_type2tc(field_types, sz, sz != 0, false); } type2tc get_intloc_type() { diff --git a/src/util/c_types.h b/src/util/c_types.h index 66886eea..e9e7cb69 100644 --- a/src/util/c_types.h +++ b/src/util/c_types.h @@ -72,7 +72,7 @@ type2tc get_uint_type(unsigned int sz); type2tc get_int_type(unsigned int sz); type2tc get_bool_type(); type2tc get_empty_type(); -type2tc get_intheap_type(); +type2tc get_intheap_type(unsigned int sz = 0); type2tc get_intloc_type(); type2tc size_type2(); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 719bd722..15447c91 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2605,12 +2605,23 @@ exprt migrate_expr_back(const expr2tc &ref) migrate_expr_back(ref2.source_value), migrate_expr_back(ref2.index)); return index; } + case expr2t::points_to_id: + { + const points_to2t &ref2 = to_points_to2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt pt("points_to", thetype); + pt.copy_to_operands( + migrate_expr_back(ref2.location), + migrate_expr_back(ref2.content) + ); + return pt; + } case expr2t::uplus_id: { const uplus2t & ref2 = to_uplus2t(ref); typet thetype = migrate_type_back(ref->type); exprt uplus("uplus", thetype); - for(expr2tc op2 : ref2.uplus_members) { + for(expr2tc op2 : ref2.heap_terms) { uplus.copy_to_operands(migrate_expr_back(op2)); } return uplus; @@ -2620,7 +2631,7 @@ exprt migrate_expr_back(const expr2tc &ref) const locadd2t &ref2 = to_locadd2t(ref); typet thetype = migrate_type_back(ref->type); exprt locadd("locadd", thetype); - locadd.copy_to_operands(migrate_expr_back(ref2.loc)); + locadd.copy_to_operands(migrate_expr_back(ref2.location)); locadd.copy_to_operands(migrate_expr_back(ref2.offset)); return locadd; } @@ -2630,11 +2641,26 @@ exprt migrate_expr_back(const expr2tc &ref) typet thetype = migrate_type_back(ref->type); exprt region("heap_region", thetype); region.copy_to_operands(migrate_expr_back(ref2.flag)); - region.copy_to_operands(migrate_expr_back(ref2.start_loc)); - region.copy_to_operands(migrate_expr_back(ref2.pt_bytes)); - region.copy_to_operands(migrate_expr_back(ref2.size)); + region.copy_to_operands(migrate_expr_back(ref2.source_location)); return region; } + case expr2t::locationof_id: + { + const locationof2t &ref2 = to_locationof2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt locationof("locationof", thetype); + locationof.copy_to_operands(migrate_expr_back(ref2.heap_term)); + return locationof; + } + case expr2t::fieldof_id: + { + const fieldof2t &ref2 = to_fieldof2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt fieldof("fieldof", thetype); + fieldof.copy_to_operands(migrate_expr_back(ref2.heap_region)); + fieldof.copy_to_operands(migrate_expr_back(ref2.field)); + return fieldof; + } case expr2t::pointer_with_region_id: { const pointer_with_region2t &ref2 = to_pointer_with_region2t(ref); @@ -2649,20 +2675,28 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_load2t& ref2 = to_heap_load2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_load("heap_load", thetype); - heap_load.copy_to_operands(migrate_expr_back(ref2.heap)); - heap_load.copy_to_operands(migrate_expr_back(ref2.start_loc)); - heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + // heap_load.copy_to_operands(migrate_expr_back(ref2.heap)); + // heap_load.copy_to_operands(migrate_expr_back(ref2.source_location)); + // heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); return heap_load; } + case expr2t::heap_update_id: + { + const heap_update2t &ref2 = to_heap_update2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt heap_update("heap_update", thetype); + heap_update.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_update.copy_to_operands(migrate_expr_back(ref2.update_field)); + heap_update.copy_to_operands(migrate_expr_back(ref2.update_value)); + return heap_update; + } case expr2t::heap_append_id: { const heap_append2t &ref2 = to_heap_append2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_append("heap_append", thetype); - heap_append.copy_to_operands(migrate_expr_back(ref2.src_heap)); - heap_append.copy_to_operands(migrate_expr_back(ref2.start_addr)); - heap_append.copy_to_operands(migrate_expr_back(ref2.create_val)); - heap_append.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + heap_append.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_append.copy_to_operands(migrate_expr_back(ref2.heap_term)); return heap_append; } case expr2t::heap_delete_id: @@ -2670,43 +2704,18 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_delete2t &ref2 = to_heap_delete2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_delete("heap_delete", thetype); - heap_delete.copy_to_operands(migrate_expr_back(ref2.src_heap)); - heap_delete.copy_to_operands(migrate_expr_back(ref2.del_addr)); - heap_delete.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); + heap_delete.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_delete.copy_to_operands(migrate_expr_back(ref2.location)); return heap_delete; } - case expr2t::heap_update_id: - { - const heap_update2t &ref2 = to_heap_update2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt heap_update("heap_update", thetype); - heap_update.copy_to_operands(migrate_expr_back(ref2.src_heap)); - heap_update.copy_to_operands(migrate_expr_back(ref2.start_addr)); - heap_update.copy_to_operands(migrate_expr_back(ref2.updated_val)); - heap_update.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); - return heap_update; - } - case expr2t::heap_contains_id: + case expr2t::heap_contain_id: { - const heap_contains2t &ref2 = to_heap_contains2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt heap_contains("heap_contains", thetype); - heap_contains.copy_to_operands(migrate_expr_back(ref2.hterm)); - heap_contains.copy_to_operands(migrate_expr_back(ref2.heap)); - heap_contains.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); - return heap_contains; - - } - case expr2t::points_to_id: - { - const points_to2t &ref2 = to_points_to2t(ref); + const heap_contain2t &ref2 = to_heap_contain2t(ref); typet thetype = migrate_type_back(ref->type); - exprt pt("points_to", thetype); - pt.copy_to_operands( - migrate_expr_back(ref2.addr), - migrate_expr_back(ref2.content) - ); - return pt; + exprt heap_contain("heap_contain", thetype); + heap_contain.copy_to_operands(migrate_expr_back(ref2.location)); + heap_contain.copy_to_operands(migrate_expr_back(ref2.heap)); + return heap_contain; } case expr2t::isnan_id: { From f68e3f31905ca91f57866f87c240181c4142f363 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 23 Aug 2024 12:27:12 +0800 Subject: [PATCH 052/126] update encoding of same-object --- src/esbmc/bmc.cpp | 17 -- src/goto-symex/builtin_functions.cpp | 35 +--- src/goto-symex/execution_state.cpp | 3 - src/goto-symex/goto_symex_state.cpp | 4 +- src/goto-symex/slice.cpp | 6 +- src/goto-symex/symex_assign.cpp | 2 +- src/irep2/irep2.h | 4 +- src/irep2/irep2_expr.cpp | 2 - src/irep2/irep2_expr.h | 107 +--------- src/irep2/irep2_utils.h | 6 +- src/irep2/templates/irep2_templates.cpp | 8 +- .../templates/irep2_templates_expr_data.cpp | 2 - src/pointer-analysis/dereference.cpp | 6 +- src/pointer-analysis/value_set.cpp | 31 +-- src/solvers/smt/smt_conv.cpp | 6 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 191 ++++++++++-------- src/solvers/z3-slhv/z3_slhv_conv.h | 7 +- src/util/migrate.cpp | 23 +-- 18 files changed, 160 insertions(+), 300 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 6ba86f0b..485c9549 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -646,25 +646,8 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) { runtime_solver = std::unique_ptr(create_solver("", ns, options)); - show_vcc(*eq); - // log_status("smt_convt created"); - // if (options.get_bool_option("z3-slhv")) { - // show_vcc(*eq); - // generate_smt_from_equation(*runtime_solver, *eq); - // return smt_convt::P_SMTLIB; - // } } - // if (!options.get_bool_option("smt-during-symex") && options.get_bool_option("z3-slhv")) { - - // log_status("enter branch dealing with slhv encoding"); - // z3_slhv_convt* slhv_conv = new z3_slhv_convt(ns, options); - // slhv_converter = std::unique_ptr(slhv_conv); - - // std::string smt_str = generate_slhv_smt_from_equation(*slhv_converter, *eq); - // return smt_convt::P_SMTLIB; - // } - if ( options.get_bool_option("multi-property") && options.get_bool_option("base-case")) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 53bfcd19..1a7e9355 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -282,17 +282,6 @@ expr2tc goto_symext::symex_mem( } to_intheap_type(heap_type).is_region = true; - // uint total_bytes = to_constant_int2t(bytes).value.to_uint64(); - // uint pt_bytes = type.get()->get_width() / 8; - // uint size = total_bytes / pt_bytes; - // if (pt_bytes == 1) - // { - // pt_bytes = total_bytes; - // size = 1; - // } - // expr2tc region_pt_bytes = constant_int2tc(get_uint64_type(), BigInt(pt_bytes)); - // expr2tc region_size = constant_int2tc(get_uint64_type(), BigInt(size)); - symbol.type.dynamic(true); symbol.mode = "C"; new_context.add(symbol); @@ -319,12 +308,11 @@ expr2tc goto_symext::symex_mem( log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); - // // link pointer variable and heap variable - // expr2tc pwr = pointer_with_region2tc(rhs_base_loc, rhs_heap); - // track_new_pointer( - // rhs_base_loc, - // get_intheap_type(), - // gen_ulong(total_bytes)); + // link pointer variable and heap variable + track_new_pointer( + rhs_base_loc, + get_intheap_type(), + gen_ulong(to_intheap_type(heap_type).total_bytes)); dynamic_memory.emplace_back( rhs_heap, @@ -336,15 +324,6 @@ expr2tc goto_symext::symex_mem( log_status("create valueset base loc symbol and assign"); symex_assign(code_assign2tc(lhs, locationof2tc(rhs_region))); - // if (is_heap_load2t(lhs)) - // { - // guardt g; - // symex_assign_heap_load(lhs, lhs, pwr, pwr, g, false); - // } - // else - // { - // symex_assign(code_assign2tc(lhs, pwr)); - // } return expr2tc(); } } @@ -380,9 +359,7 @@ void goto_symext::track_new_pointer( symex_assign(code_assign2tc(sz_index_expr, object_size_exp), true); } else { - type2tc allocsize_heap_type = get_intheap_type(); - allocsize_heap_type->dump(); - expr2tc allocsize_symbol = symbol2tc(allocsize_heap_type, alloc_size_heap_name); + expr2tc allocsize_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); // TODO SLHV: add non-constant size later assert(is_constant_int2t(size)); diff --git a/src/goto-symex/execution_state.cpp b/src/goto-symex/execution_state.cpp index 88e2f6eb..1ad125b9 100644 --- a/src/goto-symex/execution_state.cpp +++ b/src/goto-symex/execution_state.cpp @@ -201,8 +201,6 @@ void execution_statet::symex_step(reachability_treet &art) statet &state = get_active_state(); const goto_programt::instructiont &instruction = *state.source.pc; last_insn = &instruction; - // log_status("#### current symex_step instruction:"); - // instruction.dump(); merge_gotos(); if (break_insn != 0 && break_insn == instruction.location_number) @@ -299,7 +297,6 @@ void execution_statet::symex_step(reachability_treet &art) analyze_assign(assign); } state.source.pc++; - log_status("done!!!"); break; default: goto_symext::symex_step(art); diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index a5196abc..42896b14 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -80,9 +80,7 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const } if (is_locationof2t(expr)) - { - return constant_propagation(to_locationof2t(expr).heap_term); - } + return constant_propagation(to_locationof2t(expr).source_region); if (is_array_type(expr)) { diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 8f210861..31edecbf 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,10 +11,10 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; + if (is_locationof2t(expr)) return false; + if (is_heap_region2t(expr)) - return get_symbols(to_heap_region2t(expr).source_location); - else if (is_pointer_with_region2t(expr)) - return get_symbols(to_pointer_with_region2t(expr).loc_ptr); + return get_symbols(to_heap_region2t(expr).flag); else { // Recursively look if any of the operands has a inner symbol diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 491a3d37..459f4ae0 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -160,7 +160,7 @@ void goto_symext::symex_assign( allocsize_heap.lvalue = true; allocsize_heap.type = typet(typet::t_intheap); new_context.add(allocsize_heap); - expr2tc new_lhs = symbol2tc(get_intheap_type(), allocsize_heap.id); + expr2tc new_lhs = symbol2tc(get_intheap_type(), allocsize_heap.id); expr2tc new_rhs = gen_emp(); symex_assign(code_assign2tc(new_lhs, new_rhs)); } diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index e43aeacf..13a44369 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -109,8 +109,6 @@ BOOST_PP_LIST_CONS(heap_region, \ BOOST_PP_LIST_CONS(locationof, \ BOOST_PP_LIST_CONS(fieldof, \ - BOOST_PP_LIST_CONS(pointer_with_region, \ - BOOST_PP_LIST_CONS(heap_load, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_delete, \ @@ -155,7 +153,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 00dc8fc7..e6fb900e 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -80,8 +80,6 @@ static const char *expr_names[] = { "heap_region", "locationof", "fieldof", - "pointer_with_region", - "heap_load", "heap_update", "heap_append", "heap_delete", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index bf2a5457..764f3016 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1012,15 +1012,15 @@ class locationof_data : public expr2t const type2tc &t, datatype_ops::expr_ids id, const expr2tc &ht) - : expr2t(t, id), heap_term(ht) + : expr2t(t, id), source_region(ht) { } locationof_data(const locationof_data& ref) = default; - expr2tc heap_term; + expr2tc source_region; // Type mangling: - typedef esbmct::field_traits + typedef esbmct::field_traits heap_term_field; typedef esbmct::expr2t_traits traits; }; @@ -1049,63 +1049,6 @@ class fieldof_data : public expr2t typedef esbmct::expr2t_traits traits; }; -class pointer_with_region_data : public expr2t -{ -public: - pointer_with_region_data( - const type2tc &t, - datatype_ops::expr_ids id, - expr2tc loc_ptr, - expr2tc region) - : expr2t(t, id), loc_ptr(loc_ptr), region(region) - { - } - - expr2tc loc_ptr; - expr2tc region; - - // Type mangling: - typedef esbmct::field_traits - pointer_with_region_loc_ptr_field; - typedef esbmct::field_traits - pointer_with_region_region_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_load_data : public expr2t { -public: - heap_load_data( - const type2tc &t, - datatype_ops::expr_ids id, - const expr2tc &flag, - const expr2tc &heap, - const expr2tc &start_loc, - unsigned int byte_len) - : expr2t(t, id), flag(flag), heap(heap), start_loc(start_loc), byte_len(byte_len) - { - } - - expr2tc flag; - expr2tc heap; - expr2tc start_loc; - unsigned int byte_len; - - // Type mangling: - typedef esbmct::field_traits - heap_load_data_flag_field; - typedef esbmct::field_traits - heap_load_data_heap_field; - typedef esbmct::field_traits - heap_load_data_start_loc_field; - typedef esbmct::field_traits - heap_load_data_byte_len_field; - typedef esbmct::expr2t_traits< - heap_load_data_flag_field, - heap_load_data_heap_field, - heap_load_data_start_loc_field, - heap_load_data_byte_len_field> traits; -}; - class heap_update_data : public expr2t { public: @@ -1115,16 +1058,16 @@ class heap_update_data : public expr2t const expr2tc &sh, const expr2tc &uf, const expr2tc &uv) - : expr2t(t, id), source_heap(sh), update_field(uf), update_value(uv) + : expr2t(t, id), source_region(sh), update_field(uf), update_value(uv) { } - expr2tc source_heap; + expr2tc source_region; expr2tc update_field; expr2tc update_value; // Type mangling: - typedef esbmct::field_traits + typedef esbmct::field_traits source_heap_field; typedef esbmct::field_traits update_field_field; @@ -1833,8 +1776,6 @@ irep_typedefs(locadd, locadd_data); irep_typedefs(heap_region, heap_region_data); irep_typedefs(locationof, locationof_data); irep_typedefs(fieldof, fieldof_data); -irep_typedefs(pointer_with_region, pointer_with_region_data); -irep_typedefs(heap_load, heap_load_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); irep_typedefs(heap_delete, heap_delete_data); @@ -3359,8 +3300,8 @@ class heap_region2t : public heap_region_expr_methods class locationof2t : public locationof_expr_methods { public: - locationof2t(const expr2tc &heap_term) - : locationof_expr_methods(get_intloc_type(), locationof_id, heap_term) + locationof2t(const expr2tc &source_region) + : locationof_expr_methods(get_intloc_type(), locationof_id, source_region) { } locationof2t(const locationof2t &ref) = default; @@ -3383,38 +3324,6 @@ class fieldof2t : public fieldof_expr_methods static std::string field_names[esbmct::num_type_fields]; }; -// maybe deprecated -class pointer_with_region2t : public pointer_with_region_expr_methods -{ -public: - pointer_with_region2t(expr2tc loc_ptr, expr2tc region) - : pointer_with_region_expr_methods(get_intloc_type(), pointer_with_region_id, loc_ptr, region) - { - } - - static std::string field_names[esbmct::num_type_fields]; -}; - -// maybe deprecated -class heap_load2t : public heap_load_expr_methods -{ -public: - heap_load2t( - const type2tc &type, - const expr2tc &flag, - const expr2tc &heap, - const expr2tc &start_loc, - unsigned int byte_len) - : heap_load_expr_methods( - type, expr2t::heap_load_id, - flag, heap, start_loc, byte_len) - { - } - heap_load2t(const heap_load2t& ref) = default; - - static std::string field_names[esbmct::num_type_fields]; -}; - class heap_update2t : public heap_update_expr_methods { public: diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 8e73edf8..0bc2624f 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -195,13 +195,13 @@ inline bool is_slhv_expr(const expr2tc &expr) is_constant_intloc2t(expr) || is_points_to2t(expr) || is_locadd2t(expr) || - is_pointer_with_region2t(expr) || is_heap_append2t(expr) || is_heap_contain2t(expr) || is_heap_delete2t(expr) || - is_heap_load2t(expr) || is_heap_region2t(expr) || - is_heap_update2t(expr); + is_heap_update2t(expr) || + is_locationof2t(expr) || + is_fieldof2t(expr); } /** Test if expr is true. First checks whether the expr is a constant bool, and diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 29b6cec3..20d15dcc 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -171,15 +171,11 @@ std::string locadd2t::field_names[esbmct::num_type_fields] = std::string heap_region2t::field_names[esbmct::num_type_fields] = {"flag", "source_location", "", "", ""}; std::string locationof2t::field_names[esbmct::num_type_fields] = - {"heap_term", "", "", "", ""}; + {"source_region", "", "", "", ""}; std::string fieldof2t::field_names[esbmct::num_type_fields] = {"heap_region", "field", "", "", ""}; -std::string pointer_with_region2t::field_names[esbmct::num_type_fields] = - {"loc_ptr", "region", "", "", ""}; -std::string heap_load2t::field_names[esbmct::num_type_fields] = - {"src_heap", "start_loc", "byte_len", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = - {"source_heap", "update_field", "update_val", "", ""}; + {"source_region", "update_field", "update_val", "", ""}; std::string heap_append2t::field_names[esbmct::num_type_fields] = {"source_heap", "heap_term", "", "", ""}; std::string heap_delete2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index a9946854..56d8109b 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -35,8 +35,6 @@ expr_typedefs2(locadd, locadd_data); expr_typedefs3(heap_region, heap_region_data); expr_typedefs1(locationof, locationof_data); expr_typedefs3(fieldof, fieldof_data); -expr_typedefs2(pointer_with_region, pointer_with_region_data); -expr_typedefs4(heap_load, heap_load_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs2(heap_append, heap_append_data); expr_typedefs2(heap_delete, heap_delete_data); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 3f5ab91b..942798d3 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -485,8 +485,6 @@ expr2tc dereferencet::dereference( e->dump(); log_status("----"); } - // now build big case split - // only "good" objects /* If the value-set contains unknown or invalid, we cannot be sure it contains * all possible values and we have to add a fallback symbol in case all guards @@ -823,13 +821,13 @@ expr2tc dereferencet::build_reference_to( // Do alignment intheap_type2t &_type = to_intheap_type(heap_region.type); bool has_changed = _type.do_alignment(access_sz); - if (false) + if (has_changed) { to_symbol2t(heap_region.flag).type = heap_region.type; dereference_callback.update_heap_type(heap_region.flag); } } - pointer_guard = same_object2tc(deref_expr, value); + pointer_guard = same_object2tc(deref_expr, locationof2tc(value)); tmp_guard.add(pointer_guard); } else diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index a43997a4..b001a5c9 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -568,12 +568,17 @@ void value_sett::get_value_set_rec( if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || is_heap_region2t(expr) || is_heap_append2t(expr)) { - log_status("get value set rec: SLHV"); expr2tc new_object = expr; insert(dest, new_object, BigInt(0)); return; } + if (is_points_to2t(expr)) + { + log_status("finish get_value_set_rec points_to"); + abort(); + } + if (is_locadd2t(expr)) { const locadd2t& locadd = to_locadd2t(expr); @@ -585,7 +590,7 @@ void value_sett::get_value_set_rec( if (is_locationof2t(expr)) { get_value_set_rec( - to_locationof2t(expr).heap_term, + to_locationof2t(expr).source_region, dest, suffix, original_type ); return; @@ -621,24 +626,6 @@ void value_sett::get_value_set_rec( abort(); } - // if (is_pointer_with_region2t(expr)) - // { - // get_value_set_rec( - // to_pointer_with_region2t(expr).region, - // dest, suffix, original_type - // ); - // return; - // } - - // if (is_heap_load2t(expr)) - // { - // get_value_set_rec( - // to_heap_load2t(expr).flag, - // dest, suffix, original_type - // ); - // return; - // } - if (is_add2t(expr) || is_sub2t(expr)) { // Consider pointer arithmetic. This takes takes the form of finding the @@ -1254,9 +1241,9 @@ void value_sett::assign( { const heap_update2t &heap_upd = to_heap_update2t(rhs); expr2tc lhs_field = - fieldof2tc(rhs->type, heap_upd.source_heap, heap_upd.update_field); + fieldof2tc(rhs->type, heap_upd.source_region, heap_upd.update_field); assign(lhs_field, heap_upd.update_value, true); - return; + return; } } diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 4c82379b..39a92714 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -315,6 +315,10 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::pointer_offset_id: case expr2t::pointer_object_id: case expr2t::pointer_capability_id: + + case expr2t::fieldof_id: + case expr2t::heap_update_id: + case expr2t::heap_delete_id: break; // Don't convert their operands default: @@ -344,12 +348,10 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::heap_region_id: case expr2t::locationof_id: case expr2t::fieldof_id: - case expr2t::pointer_with_region_id: case expr2t::points_to_id: case expr2t::uplus_id: case expr2t::locadd_id: case expr2t::heap_update_id: - case expr2t::heap_load_id: case expr2t::heap_contain_id: case expr2t::heap_append_id: case expr2t::heap_delete_id: { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index dd74055c..ad900c9c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -63,6 +63,7 @@ smt_convt::resultt z3_slhv_convt::dec_solve() { for(z3::expr expr : solver.assertions()) { out << expr.to_string() << '\n'; } + out.close(); } z3::check_result result = solver.check(); @@ -200,7 +201,6 @@ z3_slhv_convt::convert_slhv_opts( return mk_nil(); case expr2t::heap_region_id: { - log_status("convert heap region"); const intheap_type2t &type = to_intheap_type(expr->type); std::vector pt_vec; @@ -235,21 +235,90 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::locationof_id: { const locationof2t &locof = to_locationof2t(expr); - if (!is_heap_region2t(locof.heap_term)) + if (!is_heap_region2t(locof.source_region)) { log_error("We can't get a location of a non-region heap"); abort(); } - return convert_ast(to_heap_region2t(locof.heap_term).source_location); + return convert_ast(to_heap_region2t(locof.source_region).source_location); + } + case expr2t::points_to_id: + { + assert(args.size() == 2); + return mk_pt(args[0], args[1]); + } + case expr2t::uplus_id: + { + assert(args.size() >= 2); + smt_astt h = args[0]; + for (int i = 1; i < args.size(); i++) { + h = mk_uplus(h, args[i]); + } + return h; + } + case expr2t::add_id: + case expr2t::sub_id: + case expr2t::locadd_id: + { + assert(args.size() == 2); + return mk_locadd(args[0], args[1]); + } + case expr2t::heap_append_id: + { + smt_astt h = args[0]; + smt_astt t = args[1]; + // new heap state + return mk_uplus(h, t); + } + case expr2t::heap_contain_id: + { + const heap_contain2t& heap_ct = to_heap_contain2t(expr); + smt_astt sh; + if (is_symbol2t(heap_ct.location) || is_pointer_object2t(heap_ct.location)) + { + sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); + } + else if (is_points_to2t(heap_ct.location)) + { + sh = args[0]; + } + return mk_subh(sh, args[1]); } case expr2t::fieldof_id: + case expr2t::heap_update_id: + case expr2t::heap_delete_id: { - const fieldof2t &fieldof = to_fieldof2t(expr); + z3_slhv_convt::smt_ast_pair sap = convert_opt_without_assert(expr); + assert_ast(sap.first); + return sap.second; + } + case expr2t::same_object_id: + { + // Do project for SLHV + const same_object2t& same = to_same_object2t(expr); + z3_slhv_convt::smt_ast_pair p1 = this->project(same.side_1); + z3_slhv_convt::smt_ast_pair p2 = this->project(same.side_2); + + smt_astt cond = mk_and(p1.first, p2.first); + smt_astt eq = mk_eq(p1.second, p2.second); - if (is_constant_intheap2t(fieldof.heap_region)) - return mk_fresh( - convert_sort(fieldof.type), - mk_fresh_name("invalid_loc_")); + return mk_and(cond, eq); + } + default: { + log_status("Invalid SLHV operations!!!"); + abort(); + } + } +} + +z3_slhv_convt::smt_ast_pair +z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) +{ + switch (expr->expr_id) + { + case expr2t::fieldof_id: + { + const fieldof2t &fieldof = to_fieldof2t(expr); if (!is_heap_region2t(fieldof.heap_region)) { @@ -261,9 +330,13 @@ z3_slhv_convt::convert_slhv_opts( log_error("Wrong field"); abort(); } + if (is_constant_intheap2t(fieldof.heap_region)) + return std::make_pair( + mk_smt_bool(true), + mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); + unsigned int field = to_constant_int2t(fieldof.field).value.to_uint64(); - // TODO : do more analysis const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); const intheap_type2t &_type = to_intheap_type(heap_region.type); @@ -286,110 +359,70 @@ z3_slhv_convt::convert_slhv_opts( } smt_astt v1 = mk_fresh(s1, name); - assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region.flag))); - return v1; - } - case expr2t::points_to_id: - { - assert(args.size() == 2); - return mk_pt(args[0], args[1]); - } - case expr2t::uplus_id: - { - assert(args.size() >= 2); - smt_astt h = args[0]; - for (int i = 1; i < args.size(); i++) { - h = mk_uplus(h, args[i]); - } - return h; - } - case expr2t::add_id: - case expr2t::sub_id: - case expr2t::locadd_id: - { - assert(args.size() == 2); - return mk_locadd(args[0], args[1]); - } - case expr2t::heap_append_id: - { - smt_astt h = args[0]; - smt_astt adr = args[1]; - smt_astt val = args[2]; - // new heap state - return mk_uplus(h, mk_pt(adr, val)); + smt_astt assert_expr = mk_subh(mk_pt(loc, v1), convert_ast(heap_region.flag)); + return std::make_pair(assert_expr, v1); } case expr2t::heap_update_id: { const heap_update2t &heap_upd = to_heap_update2t(expr); - const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_heap); - smt_astt h = convert_ast(heap_region.flag); + if (!is_heap_region2t(heap_upd.source_region)) + { + log_error("Do not support heap update for other heap terms"); + abort(); + } + + const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_region); + smt_astt h = convert_ast(heap_region.flag); smt_astt source_loc = convert_ast(heap_region.source_location); smt_astt field = convert_ast(heap_upd.update_field); smt_astt loc = mk_locadd(source_loc, field); - smt_astt val = args[2]; + smt_astt val = convert_ast(heap_upd.update_value); smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); + // current heap state - smt_astt o_state = mk_eq(h, mk_uplus(mk_pt(loc, v1), h1)); - assert_ast(o_state); + smt_astt assert_expr = mk_eq(h, mk_uplus(mk_pt(loc, v1), h1)); + // new heap state - return mk_uplus(mk_pt(loc, val), h1); - } - case expr2t::heap_contain_id: - { - const heap_contain2t& heap_ct = to_heap_contain2t(expr); - smt_astt sh; - if (is_symbol2t(heap_ct.location) || - is_pointer_object2t(heap_ct.location)) - { - sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); - // TODO : support multiple loaded - } - else if (is_points_to2t(heap_ct.location)) - { - sh = args[0]; - } - return mk_subh(sh, args[1]); + return std::make_pair(assert_expr, mk_uplus(mk_pt(loc, val), h1)); } case expr2t::heap_delete_id: { + const heap_delete2t &heap_del = to_heap_delete2t(expr); + + smt_astt h = convert_ast(heap_del.source_heap); + smt_astt l = convert_ast(heap_del.location); + smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - assert_ast(mk_eq(args[0], mk_uplus(h1, mk_pt(args[1], v1)))); - return h1; - } - case expr2t::same_object_id: - { - // Do project for SLHV - const same_object2t& same = to_same_object2t(expr); - smt_astt p1 = this->project(same.side_1); - smt_astt p2 = this->project(same.side_2); - return mk_eq(p1, p2); + smt_astt assert_expr = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); + + return std::make_pair(assert_expr, v1); } default: { - log_status("Invalid SLHV operations!!!"); - abort(); + return std::make_pair(mk_smt_bool(true), convert_ast(expr)); } } } -smt_astt z3_slhv_convt::project(const expr2tc &expr) +z3_slhv_convt::smt_ast_pair +z3_slhv_convt::project(const expr2tc &expr) { - if (is_symbol2t(expr)) - return convert_ast(expr); + return convert_opt_without_assert(expr); else if (is_heap_region2t(expr)) return this->project(to_heap_region2t(expr).source_location); else if (is_locationof2t(expr)) - return this->project(to_locationof2t(expr).heap_term); + return this->project(to_locationof2t(expr).source_region); else if (is_fieldof2t(expr)) - return this->project(to_fieldof2t(expr).heap_region); + return convert_opt_without_assert(expr); else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); else if (is_locadd2t(expr) || is_add2t(expr) || is_sub2t(expr)) { + // TODO : fix expr2tc ptr; if (is_locadd2t(expr)) ptr = to_locadd2t(expr).location; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index f24cb747..0ed5f49d 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -41,7 +41,12 @@ class z3_slhv_convt : public z3_convt { smt_sortt convert_slhv_sorts(const type2tc &type) override; smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; - smt_astt project(const expr2tc &expr); + + typedef std::pair smt_ast_pair; + + smt_ast_pair convert_opt_without_assert(const expr2tc &expr); + + smt_ast_pair project(const expr2tc &expr); void dump_smt() override; diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 15447c91..999dc0a8 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2649,7 +2649,7 @@ exprt migrate_expr_back(const expr2tc &ref) const locationof2t &ref2 = to_locationof2t(ref); typet thetype = migrate_type_back(ref->type); exprt locationof("locationof", thetype); - locationof.copy_to_operands(migrate_expr_back(ref2.heap_term)); + locationof.copy_to_operands(migrate_expr_back(ref2.source_region)); return locationof; } case expr2t::fieldof_id: @@ -2661,31 +2661,12 @@ exprt migrate_expr_back(const expr2tc &ref) fieldof.copy_to_operands(migrate_expr_back(ref2.field)); return fieldof; } - case expr2t::pointer_with_region_id: - { - const pointer_with_region2t &ref2 = to_pointer_with_region2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt pointer_with_region("pointer_with_region", thetype); - pointer_with_region.copy_to_operands(migrate_expr_back(ref2.loc_ptr)); - pointer_with_region.copy_to_operands(migrate_expr_back(ref2.region)); - return pointer_with_region; - } - case expr2t::heap_load_id: - { - const heap_load2t& ref2 = to_heap_load2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt heap_load("heap_load", thetype); - // heap_load.copy_to_operands(migrate_expr_back(ref2.heap)); - // heap_load.copy_to_operands(migrate_expr_back(ref2.source_location)); - // heap_load.set("byte_len", irep_idt(std::to_string(ref2.byte_len))); - return heap_load; - } case expr2t::heap_update_id: { const heap_update2t &ref2 = to_heap_update2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_update("heap_update", thetype); - heap_update.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_update.copy_to_operands(migrate_expr_back(ref2.source_region)); heap_update.copy_to_operands(migrate_expr_back(ref2.update_field)); heap_update.copy_to_operands(migrate_expr_back(ref2.update_value)); return heap_update; From 4fab9da8f560d2e37f6f1f8295340524447d7784 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 23 Aug 2024 16:53:42 +0800 Subject: [PATCH 053/126] turn pointer arithmetic to locadd --- src/esbmc/show_vcc.cpp | 2 +- src/goto-symex/builtin_functions.cpp | 3 +- src/goto-symex/symex_assign.cpp | 39 ++++++++++++++++ src/irep2/irep2_expr.cpp | 69 ++++++---------------------- src/irep2/irep2_expr.h | 7 ++- src/irep2/irep2_type.h | 2 + src/pointer-analysis/dereference.cpp | 40 ++++++++++++++-- src/pointer-analysis/value_set.cpp | 21 +++++++-- src/solvers/z3-slhv/z3_slhv_conv.cpp | 13 +++--- src/util/simplify_expr2.cpp | 21 +++++++++ 10 files changed, 144 insertions(+), 73 deletions(-) diff --git a/src/esbmc/show_vcc.cpp b/src/esbmc/show_vcc.cpp index 1e57a667..74888567 100644 --- a/src/esbmc/show_vcc.cpp +++ b/src/esbmc/show_vcc.cpp @@ -61,7 +61,7 @@ void bmct::show_vcc(const symex_target_equationt &eq) } else { - std::ofstream out(filename.c_str()); + std::ofstream out(filename.c_str(), std::ios_base::app); if (!out) log_error("failed to open {}", filename); else diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 1a7e9355..a8365ed2 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -268,8 +268,7 @@ expr2tc goto_symext::symex_mem( else { expr2tc bytes = size; - if (!is_constant_int2t(bytes)) - bytes = bytes->simplify(); + do_simplify(bytes); if (is_constant_int2t(bytes)) { heap_type = get_intheap_type(to_constant_int2t(bytes).value.to_uint64()); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 459f4ae0..c7a20695 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -137,6 +137,7 @@ void goto_symext::symex_assign( const guardt &guard) { log_status("xxxxxxxxxxxx symex assign: "); + code_assign->dump(); const code_assign2t &code = to_code_assign2t(code_assign); expr2tc assign_target = code.target; @@ -188,6 +189,13 @@ void goto_symext::symex_assign( { replace_null(lhs); replace_null(rhs); + + log_status("here"); + + replace_by_locadd(lhs); + log_status("here"); + replace_by_locadd(rhs); + log_status("here"); } log_status("symex assign lhs : ------------- "); @@ -948,4 +956,35 @@ void goto_symext::replace_null(expr2tc &expr) replace_null(e); }); } +} + +void goto_symext::replace_by_locadd(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + + expr->Foreach_operand([this](expr2tc &e) { replace_by_locadd(e); }); + + if (is_add2t(expr) || is_sub2t(expr)) + { + expr2tc side_1 = is_add2t(expr) ? to_add2t(expr).side_1 : to_sub2t(expr).side_1; + expr2tc side_2 = is_add2t(expr) ? to_add2t(expr).side_2 : to_sub2t(expr).side_2; + + if (is_pointer_type(side_2) || is_intloc_type(side_2)) + std::swap(side_1, side_2); + + if (is_pointer_type(side_2) || is_intloc_type(side_2)) + { + log_error("Wrong pointer arithmetic"); + abort(); + } + + if (is_sub2t(expr)) side_2 = neg2tc(side_2->type, side_2); + + expr2tc locadd = locadd2tc(side_1, side_2); + do_simplify(locadd); + + locadd->dump(); + + expr = locadd; + } } \ No newline at end of file diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index e6fb900e..f293ef80 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -439,60 +439,6 @@ void with2t::assert_consistency() const assert(type == source_value->type); } -// bool heap_region2t::update(uint byte_len) -// { -// uint old_bytes = to_constant_int2t(field_bytes).value.to_uint64(); -// uint old_size = to_constant_int2t(size).value.to_uint64(); - -// assert(old_bytes * old_size % byte_len == 0); -// // TODO: allow to split only one time -// if (is_aligned) { -// assert(byte_len == old_bytes); -// return false; -// } - -// uint new_bytes = byte_len; -// uint new_size; -// if (byte_len != old_bytes) -// { -// new_size = old_bytes * old_size / byte_len; -// is_aligned = true; -// field_bytes = constant_int2tc(get_uint64_type(), BigInt(new_bytes)); -// size = constant_int2tc(get_uint64_type(), BigInt(new_size)); -// return true; -// } -// return false; -// } - -// std::string locadd2t::offset_as_string() const -// { -// if (is_symbol2t(offset)) -// return to_symbol2t(offset).get_symbol_name(); -// else if (is_neg2t(offset)) -// { -// neg2t off = to_neg2t(offset); -// expr2tc val = off.value.simplify(); -// if (!is_constant_int2t(val)) -// { -// log_error("Doe no support for offset_as_string of neg"); -// abort(); -// } -// return std::string("-") -// + std::to_string(to_constant_int2t(val).value.to_int64()); -// } -// else -// { -// expr2tc off = offset; -// if (!is_constant_int2t(off)) off = off.simplify(); -// if (!is_constant_int2t(off)) -// { -// log_error("Doe no support for offset_as_string"); -// abort(); -// } -// return std::to_string(to_constant_int2t(off).value.to_int64()); -// } -// } - const expr2tc &object_descriptor2t::get_root_object() const { const expr2tc *tmp = &object; @@ -540,3 +486,18 @@ arith_2ops::arith_2ops( // TODO: Add consistency checks for vectors #endif } + +expr2tc locadd2t::get_base_location() const +{ + if (is_locadd2t(location)) + return to_locadd2t(location).get_base_location(); + return location; +} + +expr2tc locadd2t::get_offset() const +{ + expr2tc off = offset; + if (is_locadd2t(location)) + off = add2tc(off->type, off, to_locadd2t(location).get_offset()); + return off; +} \ No newline at end of file diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 764f3016..dda6d86f 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -3277,6 +3277,11 @@ class locadd2t : public locadd_expr_methods } locadd2t(const locadd2t &ref) = default; + expr2tc do_simplify() const override; + + expr2tc get_base_location() const; + expr2tc get_offset() const; + static std::string field_names[esbmct::num_type_fields]; }; @@ -3292,8 +3297,6 @@ class heap_region2t : public heap_region_expr_methods } heap_region2t(const heap_region2t &ref) = default; - // bool update(uint byte_len); - static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index 11391eb7..1b80546c 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -400,6 +400,8 @@ class intheap_type2t : public intheap_type_methods bool is_aligned) : intheap_type_methods(intheap_id, field_types, total_bytes, is_region, is_aligned) { + if (is_region && this->field_types.empty()) + this->field_types.push_back(empty_type2tc()); } intheap_type2t(const intheap_type2t &ref) = default; unsigned int get_width() const override; diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 942798d3..c4218893 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -500,13 +500,30 @@ expr2tc dereferencet::dereference( expr2tc value; if (!known_exhaustive) value = make_failed_symbol(type); + + // TODO : fix + // Extract base location ad offset from locadd + expr2tc new_src = src; + expr2tc offset = lexical_offset; + if (is_locadd2t(src)) + { + new_src = to_locadd2t(src).get_base_location(); + expr2tc off_from_src = to_locadd2t(src).get_offset(); + if (is_nil_expr(offset)) + offset = off_from_src; + else + offset = add2tc(offset->type, offset, off_from_src); + expr2tc simp = offset->simplify(); + if (!is_nil_expr(simp)) + offset = simp; + } for (const expr2tc &target : points_to_set) { expr2tc new_value, pointer_guard; new_value = build_reference_to( - target, mode, src, type, guard, lexical_offset, pointer_guard); + target, mode, new_src, type, guard, offset, pointer_guard); if (is_nil_expr(new_value)) continue; @@ -809,6 +826,8 @@ expr2tc dereferencet::build_reference_to( value->dump(); deref_expr->dump(); type->dump(); + if (!is_nil_expr(lexical_offset)) + lexical_offset->dump(); guardt tmp_guard(guard); if (is_heap_region2t(value)) @@ -898,11 +917,15 @@ expr2tc dereferencet::build_reference_to( } else { + log_status("set final offset"); + final_offset->dump(); if (!is_nil_expr(lexical_offset)) final_offset = add2tc(final_offset->type, final_offset, lexical_offset); - if (!is_constant_int2t(final_offset)) - final_offset = final_offset.simplify(); + expr2tc simp = final_offset->simplify(); + if (!is_nil_expr(simp)) final_offset = simp; + + final_offset->dump(); } // If we're in internal mode, collect all of our data into one struct, insert @@ -1274,6 +1297,7 @@ void dereferencet::build_reference_slhv( if(is_scalar_type(type)) { if (!is_constant_int2t(offset)) { + // TODO : support log_error("Do not support non-constant offset"); abort(); } @@ -1282,7 +1306,15 @@ void dereferencet::build_reference_slhv( heap_region2t& heap_region = to_heap_region2t(value); intheap_type2t &_type = to_intheap_type(heap_region.type); - if (_type.set_field_type(field, type)) + if (field >= _type.field_types.size()) + { + expr2tc sym = symbol2tc( + type, + dereference_callback.get_nondet_id("undefined_behavior_var")); + value = sym; + return; + } + else if (_type.set_field_type(field, type)) { heap_region.flag->type = heap_region.type; dereference_callback.update_heap_type(heap_region.flag); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index b001a5c9..3b7cbcae 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -581,10 +581,23 @@ void value_sett::get_value_set_rec( if (is_locadd2t(expr)) { - const locadd2t& locadd = to_locadd2t(expr); - assert(is_intloc_type(locadd.location)); - abort(); - // TODO + expr2tc simp = expr; + + if (!is_symbol2t(to_locadd2t(simp).location) || + !is_constant_int2t(to_locadd2t(simp).offset)) + simp = simp->simplify(); + + if (!is_symbol2t(to_locadd2t(simp).location) || + !is_constant_int2t(to_locadd2t(simp).offset)) + { + log_error("Do not support dynamic pointer arithmetic"); + abort(); + } + + const locadd2t &locadd = to_locadd2t(simp); + + get_value_set_rec(locadd.location, dest, suffix, original_type); + return; } if (is_locationof2t(expr)) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index ad900c9c..b18b5934 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -201,19 +201,20 @@ z3_slhv_convt::convert_slhv_opts( return mk_nil(); case expr2t::heap_region_id: { - const intheap_type2t &type = to_intheap_type(expr->type); + const intheap_type2t &_type = to_intheap_type(expr->type); std::vector pt_vec; - if (type.is_aligned) + if (_type.is_aligned) { - for (unsigned i = 0; i < type.field_types.size(); i++) { + for (unsigned i = 0; i < _type.field_types.size(); i++) + { smt_astt loc = i == 0 ? args[1] : mk_locadd(args[1], mk_smt_int(BigInt(i))); smt_sortt sort = - is_intloc_type(type.field_types[i]) ? + is_intloc_type(_type.field_types[i]) ? mk_intloc_sort() : mk_int_sort(); std::string name = mk_fresh_name( - is_intloc_type(type.field_types[i]) ? + is_intloc_type(_type.field_types[i]) ? "tmp_loc::" : "tmp_val::"); smt_astt v = mk_fresh(sort, name); pt_vec.push_back(mk_pt(loc, v)); @@ -399,7 +400,7 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); smt_astt assert_expr = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); - return std::make_pair(assert_expr, v1); + return std::make_pair(assert_expr, h1); } default: { return std::make_pair(mk_smt_bool(true), convert_ast(expr)); diff --git a/src/util/simplify_expr2.cpp b/src/util/simplify_expr2.cpp index 2e80881f..88eaa554 100644 --- a/src/util/simplify_expr2.cpp +++ b/src/util/simplify_expr2.cpp @@ -1060,6 +1060,27 @@ expr2tc index2t::do_simplify() const return expr2tc(); } +expr2tc locadd2t::do_simplify() const +{ + expr2tc src_loc = location; + expr2tc off = offset; + + while(is_locadd2t(src_loc)) + { + off = add2tc(off->type, off, to_locadd2t(src_loc).offset); + src_loc = to_locadd2t(src_loc).location; + } + + if (!is_constant_int2t(off)) + off = off->simplify(); + + if (src_loc != location && + off != offset && !is_nil_expr(off)) + return locadd2tc(src_loc, off); + + return expr2tc(); +} + expr2tc not2t::do_simplify() const { expr2tc simp = try_simplification(value); From 072fea2c2f5f097cf9a68b8e70352f90bbd44e1b Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 24 Aug 2024 10:53:47 +0800 Subject: [PATCH 054/126] trunc output file before show vcc --- src/esbmc/bmc.cpp | 14 +++++++++----- src/esbmc/show_vcc.cpp | 2 +- src/goto-symex/slice.cpp | 6 +++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 485c9549..63446181 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -625,8 +625,11 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) if (options.get_bool_option("show-vcc")) { - show_vcc(*eq); - return smt_convt::P_SMTLIB; + // show_vcc(*eq); + // return smt_convt::P_SMTLIB; + const std::string &output_file = options.get_option("output"); + if (!output_file.empty() && output_file != "-") + std::ofstream(output_file.c_str()) << ""; } if (result.remaining_claims == 0) @@ -653,6 +656,8 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) options.get_bool_option("base-case")) return multi_property_check(*eq, result.remaining_claims); + if (options.get_bool_option("show-vcc")) show_vcc(*eq); + return run_decision_procedure(*runtime_solver, *eq); } @@ -732,8 +737,6 @@ smt_convt::resultt bmct::multi_property_check( &is_fail_fast, &fail_fast_limit, &fail_fast_cnt](const size_t &i) { - - log_status("begin to check claim {}", i); //"multi-fail-fast n": stop after first n SATs found. if (is_fail_fast && fail_fast_cnt >= fail_fast_limit) @@ -773,7 +776,8 @@ smt_convt::resultt bmct::multi_property_check( if (!options.get_bool_option("no-slice")) slicer.run(local_eq.SSA_steps); - show_vcc(local_eq); + if (options.get_bool_option("show-vcc")) + show_vcc(local_eq); // Initialize a solver std::unique_ptr runtime_solver(create_solver("", ns, options)); diff --git a/src/esbmc/show_vcc.cpp b/src/esbmc/show_vcc.cpp index 74888567..c9f4615d 100644 --- a/src/esbmc/show_vcc.cpp +++ b/src/esbmc/show_vcc.cpp @@ -61,7 +61,7 @@ void bmct::show_vcc(const symex_target_equationt &eq) } else { - std::ofstream out(filename.c_str(), std::ios_base::app); + std::ofstream out(filename.c_str(), std::ofstream::app); if (!out) log_error("failed to open {}", filename); else diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 31edecbf..8e7def16 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,8 +11,12 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; + + // locationof only has heap_region as oprend + // the location of heap_region is completely fresh + // and is not being used in symbolic execution if (is_locationof2t(expr)) return false; - + if (is_heap_region2t(expr)) return get_symbols(to_heap_region2t(expr).flag); else From 19e4eb8c3daa14cc90155b263eee5945fe3b6a58 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 24 Aug 2024 15:47:22 +0800 Subject: [PATCH 055/126] correct dereferencing a pointer --- src/goto-symex/builtin_functions.cpp | 40 ++++++++++---------------- src/goto-symex/goto_symex.h | 2 +- src/goto-symex/symex_assign.cpp | 32 ++++++++++++--------- src/irep2/irep2_expr.h | 6 ++-- src/pointer-analysis/dereference.cpp | 42 ++++++++++++++++++++++++---- src/pointer-analysis/value_set.cpp | 31 ++++++++++---------- src/solvers/z3-slhv/z3_slhv_conv.cpp | 6 ++-- src/util/migrate.cpp | 2 +- src/util/type_byte_size.cpp | 6 ++++ 9 files changed, 99 insertions(+), 68 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index a8365ed2..bbddcb9b 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -110,7 +110,7 @@ expr2tc goto_symext::symex_mem( const expr2tc &lhs, const sideeffect2t &code) { - log_status("symex_mem start: "); + log_status(" ------------------- symex_mem --------------------------- "); lhs->dump(); code.dump(); @@ -122,11 +122,6 @@ expr2tc goto_symext::symex_mem( expr2tc size = code.size; bool size_is_one = false; - log_status("alloctype : "); - type->dump(); - log_status("size : "); - size->dump(); - if (is_nil_type(type)) type = char_type2(); @@ -259,27 +254,22 @@ expr2tc goto_symext::symex_mem( symbol.type = typet(typet::t_intheap); - type2tc heap_type; - if (size_is_one) - { - heap_type = get_intheap_type(type_byte_size(type).to_uint64()); - to_intheap_type(heap_type).is_aligned = true; - } - else + + unsigned int bytes = type_byte_size(type).to_uint64(); + type2tc heap_type = get_intheap_type(bytes); + + intheap_type2t &_heap_type = to_intheap_type(heap_type); + _heap_type.is_region = true; + if (is_struct_type(type)) { - expr2tc bytes = size; - do_simplify(bytes); - if (is_constant_int2t(bytes)) - { - heap_type = get_intheap_type(to_constant_int2t(bytes).value.to_uint64()); - } - else - { - log_error("Do not support dynamic size"); - abort(); - } + struct_type2t &_type = to_struct_type(type); + _heap_type.is_aligned = true; + _heap_type.field_types.clear(); + for(auto inner_type : _type.get_structure_members()) + _heap_type.field_types.push_back( + is_pointer_type(inner_type) ? get_intloc_type() : get_int64_type() + ); } - to_intheap_type(heap_type).is_region = true; symbol.type.dynamic(true); symbol.mode = "C"; diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 785a7a9f..eb21851b 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -809,7 +809,7 @@ class goto_symext * Replace member, indexof ... by locadd * @param expr Expr to a location. */ - void replace_by_locadd(expr2tc &expr); + void replace_pointer_airth(expr2tc &expr); /** * Fetch reference to global dynamic object counter. diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index c7a20695..3a5bf4ba 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -190,12 +190,8 @@ void goto_symext::symex_assign( replace_null(lhs); replace_null(rhs); - log_status("here"); - - replace_by_locadd(lhs); - log_status("here"); - replace_by_locadd(rhs); - log_status("here"); + replace_pointer_airth(lhs); + replace_pointer_airth(rhs); } log_status("symex assign lhs : ------------- "); @@ -910,14 +906,14 @@ void goto_symext::symex_assign_fieldof( assert(is_scalar_type(rhs)); const fieldof2t& fieldof = to_fieldof2t(lhs); - const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); expr2tc update_heap = - heap_update2tc(heap_region.type, fieldof.heap_region, fieldof.field, rhs); + heap_update2tc(heap_region.type, fieldof.source_region, fieldof.field, rhs); symex_assign_rec( heap_region.flag, - fieldof.heap_region, + fieldof.source_region, update_heap, update_heap, guard, hidden); @@ -958,11 +954,11 @@ void goto_symext::replace_null(expr2tc &expr) } } -void goto_symext::replace_by_locadd(expr2tc &expr) +void goto_symext::replace_pointer_airth(expr2tc &expr) { if (is_nil_expr(expr)) return; - expr->Foreach_operand([this](expr2tc &e) { replace_by_locadd(e); }); + expr->Foreach_operand([this](expr2tc &e) { replace_pointer_airth(e); }); if (is_add2t(expr) || is_sub2t(expr)) { @@ -982,9 +978,19 @@ void goto_symext::replace_by_locadd(expr2tc &expr) expr2tc locadd = locadd2tc(side_1, side_2); do_simplify(locadd); - - locadd->dump(); expr = locadd; } + + if (is_member2t(expr)) + { + // replaced by fieldof + const member2t &member = to_member2t(expr); + + const struct_type2t &struct_type = to_struct_type(member.source_value->type); + + expr2tc field = gen_ulong(struct_type.get_component_number(member.member)); + + expr = fieldof2tc(member.type, member.source_value, field); + } } \ No newline at end of file diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index dda6d86f..dd9af0c8 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1033,16 +1033,16 @@ class fieldof_data : public expr2t datatype_ops::expr_ids id, const expr2tc &hr, const expr2tc &f) - : expr2t(t, id), heap_region(hr), field(f) + : expr2t(t, id), source_region(hr), field(f) { } fieldof_data(const fieldof_data &ref) = default; - expr2tc heap_region; + expr2tc source_region; expr2tc field; // Type mangling: - typedef esbmct::field_traits + typedef esbmct::field_traits heap_region_field; typedef esbmct::field_traits field_field; diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index c4218893..256a8245 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -173,6 +173,7 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) expr = result; break; } + case expr2t::fieldof_id: case expr2t::index_id: case expr2t::member_id: { @@ -437,6 +438,27 @@ expr2tc dereferencet::dereference_expr_nonscalar( u.datatype_members.front(), guard, mode, base); } + if (is_fieldof2t(expr)) + { + fieldof2t &fieldof = to_fieldof2t(expr); + + if (!is_dereference2t(fieldof.source_region)) + { + log_error("Do not support struct in struct yet"); + abort(); + } + + dereference2t &deref = to_dereference2t(fieldof.source_region); + + // Get the heap region + dereference_expr(deref.value, guard, dereferencet::READ); + + expr2tc offset_to_scalar = fieldof.field; + simplify(offset_to_scalar); + + return dereference(deref.value, base->type, guard, mode, offset_to_scalar); + } + // there should be no sudden transition back to scalars, except through // dereferences. Return nil to indicate that there was no dereference at // the bottom of this. @@ -503,6 +525,7 @@ expr2tc dereferencet::dereference( // TODO : fix // Extract base location ad offset from locadd + // In SLHV, all offset is in word-level expr2tc new_src = src; expr2tc offset = lexical_offset; if (is_locadd2t(src)) @@ -872,6 +895,9 @@ expr2tc dereferencet::build_reference_to( // Value set tracking emits objects with some cruft built on top of them. value = get_base_object(value); + value->dump(); + type->dump(); + // Final offset computations start here expr2tc final_offset = o.offset; #if 0 @@ -1293,6 +1319,7 @@ void dereferencet::build_reference_slhv( value->dump(); guard.dump(); offset->dump(); + type->dump(); assert(is_heap_region2t(value)); if(is_scalar_type(type)) { if (!is_constant_int2t(offset)) @@ -1304,24 +1331,29 @@ void dereferencet::build_reference_slhv( unsigned int field = to_constant_int2t(offset).value.to_uint64(); heap_region2t& heap_region = to_heap_region2t(value); - intheap_type2t &_type = to_intheap_type(heap_region.type); - if (field >= _type.field_types.size()) + + unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); + // heap region as a value + if (field == 0 && access_sz == _type.total_bytes) return; + + if (field >= _type.field_types.size() || + access_sz != _type.total_bytes / _type.field_types.size()) { + // Out of bound or unaligned expr2tc sym = symbol2tc( type, dereference_callback.get_nondet_id("undefined_behavior_var")); value = sym; return; } - else if (_type.set_field_type(field, type)) + + if (_type.set_field_type(field, type)) { heap_region.flag->type = heap_region.type; dereference_callback.update_heap_type(heap_region.flag); } - expr2tc heap = heap_region.flag; - value = fieldof2tc(type, value, gen_ulong(field)); } else { log_error("ERROR: currently not support non-scalar type dereference"); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 3b7cbcae..1cfaa0db 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -566,19 +566,16 @@ void value_sett::get_value_set_rec( } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || - is_heap_region2t(expr) || is_heap_append2t(expr)) + is_heap_append2t(expr) || is_heap_delete2t(expr) || + // heap_region as a constant + // deref a heap region use fieldof(region, 0) + is_heap_region2t(expr)) { expr2tc new_object = expr; insert(dest, new_object, BigInt(0)); return; } - if (is_points_to2t(expr)) - { - log_status("finish get_value_set_rec points_to"); - abort(); - } - if (is_locadd2t(expr)) { expr2tc simp = expr; @@ -612,7 +609,7 @@ void value_sett::get_value_set_rec( if (is_fieldof2t(expr)) { const fieldof2t &fieldof = to_fieldof2t(expr); - const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); expr2tc field = fieldof.field; if (!is_constant_int2t(field)) @@ -621,21 +618,21 @@ void value_sett::get_value_set_rec( abort(); } - std::string str_field = - std::to_string(to_constant_int2t(field).value.to_uint64()); + unsigned int _field = to_constant_int2t(field).value.to_uint64(); get_value_set_rec( heap_region.flag, dest, - "::field::" + str_field + "::" + suffix, + "::field::" + std::to_string(_field) + "::" + suffix, original_type ); return; } - if (is_heap_update2t(expr)) + if (is_heap_update2t(expr) || is_points_to2t(expr)) { - log_status("finish get_value_set_rec heap_update"); + expr->dump(); + log_status("fini get_value_set_rec heap_update"); abort(); } @@ -1421,15 +1418,15 @@ void value_sett::assign_rec( log_error("Do not support dynamic offset yet"); abort(); } - std::string str_field = - std::to_string(to_constant_int2t(field).value.to_uint64()); - const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + unsigned int _field = to_constant_int2t(field).value.to_uint64(); + + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); assign_rec( heap_region.flag, values_rhs, - "::field::" + str_field + "::" + suffix, + "::field::" + std::to_string(_field) + "::" + suffix, add_to_sets); } else if ( diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index b18b5934..9c50cab0 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -321,7 +321,7 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) { const fieldof2t &fieldof = to_fieldof2t(expr); - if (!is_heap_region2t(fieldof.heap_region)) + if (!is_heap_region2t(fieldof.source_region)) { log_error("We can't get a location of a non-region heap"); abort(); @@ -331,14 +331,14 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) log_error("Wrong field"); abort(); } - if (is_constant_intheap2t(fieldof.heap_region)) + if (is_constant_intheap2t(fieldof.source_region)) return std::make_pair( mk_smt_bool(true), mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); unsigned int field = to_constant_int2t(fieldof.field).value.to_uint64(); - const heap_region2t &heap_region = to_heap_region2t(fieldof.heap_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); const intheap_type2t &_type = to_intheap_type(heap_region.type); smt_astt source_loc = convert_ast(heap_region.source_location); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 999dc0a8..881ae168 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2657,7 +2657,7 @@ exprt migrate_expr_back(const expr2tc &ref) const fieldof2t &ref2 = to_fieldof2t(ref); typet thetype = migrate_type_back(ref->type); exprt fieldof("fieldof", thetype); - fieldof.copy_to_operands(migrate_expr_back(ref2.heap_region)); + fieldof.copy_to_operands(migrate_expr_back(ref2.source_region)); fieldof.copy_to_operands(migrate_expr_back(ref2.field)); return fieldof; } diff --git a/src/util/type_byte_size.cpp b/src/util/type_byte_size.cpp index 12ecc4ac..6ba2a7ad 100644 --- a/src/util/type_byte_size.cpp +++ b/src/util/type_byte_size.cpp @@ -453,6 +453,12 @@ const expr2tc &get_base_object(const expr2tc &expr) if (is_dereference2t(expr)) return get_base_object(to_dereference2t(expr).value); + + if (is_locationof2t(expr)) + return get_base_object(to_locationof2t(expr).source_region); + + if (is_fieldof2t(expr)) + return get_base_object(to_fieldof2t(expr).source_region); return expr; } From cc24ac34c431c73dc41425ab4e589e129e9a1e59 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 24 Aug 2024 22:07:02 +0800 Subject: [PATCH 056/126] fix heap region size, propagating and renaming heap region's flag --- src/goto-symex/builtin_functions.cpp | 46 ++++++++++++++++------------ src/goto-symex/goto_symex_state.cpp | 32 +++++++++++-------- src/goto-symex/symex_assign.cpp | 8 ++--- src/pointer-analysis/dereference.cpp | 17 +++++++--- src/pointer-analysis/value_set.cpp | 2 +- 5 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index bbddcb9b..e29b2306 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -254,10 +254,16 @@ expr2tc goto_symext::symex_mem( symbol.type = typet(typet::t_intheap); + expr2tc _total_bytes = code.operand; + do_simplify(_total_bytes); + if (!is_constant_int2t(_total_bytes)) + { + log_status("Do not support dynamic size"); + abort(); + } + unsigned int bytes = to_constant_int2t(_total_bytes).value.to_uint64(); - unsigned int bytes = type_byte_size(type).to_uint64(); type2tc heap_type = get_intheap_type(bytes); - intheap_type2t &_heap_type = to_intheap_type(heap_type); _heap_type.is_region = true; if (is_struct_type(type)) @@ -291,6 +297,9 @@ expr2tc goto_symext::symex_mem( new_context.add(heap_region_loc); expr2tc rhs_base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); + // rhs_base_loc do not change during its lifetime + // use l2 symbol, do not need to be renamed + cur_state->rename(rhs_base_loc); expr2tc rhs_region = heap_region2tc(heap_type, rhs_heap, rhs_base_loc); @@ -445,29 +454,28 @@ void goto_symext::symex_free(const expr2tc &expr) expr2tc falsity = gen_false_expr(); symex_assign(code_assign2tc(valid_index_expr, falsity), true); } else { - expr2tc freed_pointer; - expr2tc freed_heap; + expr2tc free_ptr = code.operand; + expr2tc is_src_loc = gen_false_expr(); + // set each heap region to empty, guarded by item.gurad for(auto const& item : internal_deref_items) { assert(is_heap_region2t(item.object)); const heap_region2t& heap_region = to_heap_region2t(item.object); - if(is_nil_expr(freed_pointer)) { - freed_pointer = heap_region.source_location; - freed_heap = heap_region.flag; - } else { - freed_pointer = - if2tc(freed_pointer->type, item.guard, heap_region.source_location, freed_pointer); - freed_heap = - if2tc(get_intheap_type(), item.guard, heap_region.flag, freed_heap); - } - + expr2tc free_heap = heap_region.flag; + expr2tc free_loc = heap_region.source_location; expr2tc emp_heap = gen_emp(); - log_status("symex free freed_heap emp_heap"); - symex_assign(code_assign2tc(freed_heap, emp_heap)); - expr2tc alloc_size_heap_symbol = symbol2tc(get_intheap_type(), alloc_size_heap_name); - expr2tc heap_deleted = heap_delete2tc(alloc_size_heap_symbol, freed_pointer); - symex_assign(code_assign2tc(alloc_size_heap_symbol, heap_deleted)); + + expr2tc _is_src_loc = equality2tc(free_ptr, free_loc); + is_src_loc = or2tc(is_src_loc, _is_src_loc); + + guardt g; g.add(_is_src_loc); + symex_assign(code_assign2tc(free_heap, emp_heap), false, g); } + // delete the pointer in alloc_size heap + expr2tc alloc_size_heap = symbol2tc(get_intheap_type(), alloc_size_heap_name); + expr2tc new_heap = heap_delete2tc(alloc_size_heap, free_ptr); + guardt g; g.add(is_src_loc); + symex_assign(code_assign2tc(alloc_size_heap, new_heap), false, g); } log_status("xxxxxxx symex free done"); diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 42896b14..08bcf6f9 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -210,6 +210,13 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) expr2tc l1_lhs = lhs; expr2tc const_value = constant_propagation(rhs) ? rhs : expr2tc(); + + // Each heap region has only one unique flag that does not change + // during its lifetime. The l1 version of flag is the representation. + // For constant_propagation, all heap regions should hold their flag. + if (is_heap_region2t(const_value)) + level2.get_original_name(to_heap_region2t(const_value).flag); + level2.make_assignment(lhs, const_value, rhs); if (use_value_set) @@ -273,23 +280,22 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } - else if (is_heap_region2t(expr)) - { - // Don't replace flag with heap region - // Get the newest symbol - heap_region2t &heap_region = to_heap_region2t(expr); - - // rename location - rename(heap_region.source_location); - - // use the newest l2 symbol - level2.get_ident_name(heap_region.flag); - } - else + else if (!is_heap_region2t(expr)) { // do this recursively expr->Foreach_operand([this](expr2tc &e) { rename(e); }); } + + // If we get a heap region from a symbol, + // then set the flag to the newest one. + // It is redundant from symex, but is clear for display + if (is_heap_region2t(expr)) + { + // Only need to rename flag to l2 since source location + // already has l2 name. + heap_region2t &heap_region = to_heap_region2t(expr); + level2.get_ident_name(heap_region.flag); + } } void goto_symex_statet::rename_address(expr2tc &expr) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 3a5bf4ba..ab6c5bbf 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -369,15 +369,15 @@ void goto_symext::symex_assign_symbol( guardt &guard, const bool hidden) { + // put assignment guard in rhs + if (!guard.is_true()) + rhs = if2tc(rhs->type, guard.as_expr(), rhs, lhs); + log_status("lhs:"); lhs->dump(); log_status("rhs:"); rhs->dump(); - // put assignment guard in rhs - if (!guard.is_true()) - rhs = if2tc(rhs->type, guard.as_expr(), rhs, lhs); - cur_state->rename(rhs); do_simplify(rhs); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 256a8245..d8581ada 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -961,11 +961,18 @@ expr2tc dereferencet::build_reference_to( { dereference_callbackt::internal_item internal; internal.object = value; - // Converting offset to bytes - internal.offset = typecast2tc( - signed_size_type2(), - div2tc( - final_offset->type, final_offset, gen_long(final_offset->type, 8))); + + if (use_old_encoding) + { + // Converting offset to bytes + internal.offset = typecast2tc( + signed_size_type2(), + div2tc( + final_offset->type, final_offset, gen_long(final_offset->type, 8))); + } + else + internal.offset = final_offset; + internal.guard = pointer_guard; internal_items.push_back(internal); return expr2tc(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 1cfaa0db..bd1f7058 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -1252,7 +1252,7 @@ void value_sett::assign( const heap_update2t &heap_upd = to_heap_update2t(rhs); expr2tc lhs_field = fieldof2tc(rhs->type, heap_upd.source_region, heap_upd.update_field); - assign(lhs_field, heap_upd.update_value, true); + assign(lhs_field, heap_upd.update_value, add_to_sets); return; } } From 5ce55849b387a3e6b4f2c21a1c46918bfea2c3af Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 25 Aug 2024 16:56:57 +0800 Subject: [PATCH 057/126] fix encoding of check heap region size --- src/esbmc/bmc.cpp | 2 - src/goto-symex/dynamic_allocation.cpp | 15 +- src/goto-symex/goto_symex_state.cpp | 11 +- src/goto-symex/symex_main.cpp | 4 +- src/goto-symex/symex_target_equation.cpp | 1 + src/pointer-analysis/dereference.cpp | 299 ++++++++--------------- src/pointer-analysis/dereference.h | 10 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 4 + 8 files changed, 134 insertions(+), 212 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 63446181..0d637092 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -794,8 +794,6 @@ smt_convt::resultt bmct::multi_property_check( fine_timet sat_stop = current_time(); log_status( "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); - - log_status("Result : {}", (result == smt_convt::P_SATISFIABLE)); // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 13dafd5d..fb3784e3 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -29,19 +29,18 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc index_expr = index2tc(get_bool_type(), alloc_arr_2, obj_expr); expr = index_expr; - } else { - log_status("replace valid_object"); + // Checking that the object is valid by heap_alloc_size + log_status(" --- generate cond for checking heap region --- "); const valid_object2t &obj = to_valid_object2t(expr); obj.dump(); - assert(is_heap_region2t(obj.value)); const heap_region2t& valid_inner = to_heap_region2t(obj.value); - expr2tc alloc_size_heap_2; - log_status("before migrate"); - migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap_2); - log_status("migrate over"); - expr2tc heap_contain = heap_contain2tc(valid_inner.source_location, alloc_size_heap_2); + // get alloc size heap + expr2tc alloc_size_heap; + migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); + expr2tc heap_contain = heap_contain2tc(valid_inner.source_location, alloc_size_heap); expr = heap_contain; + log_status(" --- generate cond for checking heap region --- "); } } else if (is_invalid_pointer2t(expr)) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 08bcf6f9..9dcc4f44 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -210,11 +210,11 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) expr2tc l1_lhs = lhs; expr2tc const_value = constant_propagation(rhs) ? rhs : expr2tc(); - + // Each heap region has only one unique flag that does not change // during its lifetime. The l1 version of flag is the representation. // For constant_propagation, all heap regions should hold their flag. - if (is_heap_region2t(const_value)) + if (!is_nil_expr(const_value) && is_heap_region2t(const_value)) level2.get_original_name(to_heap_region2t(const_value).flag); level2.make_assignment(lhs, const_value, rhs); @@ -286,14 +286,15 @@ void goto_symex_statet::rename(expr2tc &expr) expr->Foreach_operand([this](expr2tc &e) { rename(e); }); } - // If we get a heap region from a symbol, - // then set the flag to the newest one. - // It is redundant from symex, but is clear for display + // If we get a heap region from a symbol, then set the flag to + // the newest one. Since some variable will be reset to l1 version, + // it is also neccessary to rename source location. if (is_heap_region2t(expr)) { // Only need to rename flag to l2 since source location // already has l2 name. heap_region2t &heap_region = to_heap_region2t(expr); + rename(heap_region.source_location); level2.get_ident_name(heap_region.flag); } } diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 2a304bb3..5444332a 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1223,9 +1223,9 @@ void goto_symext::add_memory_leak_checks() "dereference failure: forgotten memory: " + get_pretty_name(it.name)); } } else { - log_status("memleak encoding"); + log_status(" ----------- [memleak encoding ]----------- "); for (auto const &it : dynamic_memory){ - log_status("allocated object {}: ", it.name ); + log_status("allocated object {}: ", it.name); expr2tc deallocated = equality2tc(it.obj, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 13f9d08d..be3fe7f8 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -190,6 +190,7 @@ void symex_target_equationt::convert_internal_step( if (step.is_assume() || step.is_assert()) { + // step.cond_ast = false_val; log_status("step is_assume || step is_assert"); expr2tc tmp(step.cond); step.cond_ast = smt_conv.convert_ast(tmp); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index d8581ada..063fc720 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -527,6 +527,7 @@ expr2tc dereferencet::dereference( // Extract base location ad offset from locadd // In SLHV, all offset is in word-level expr2tc new_src = src; + // TODO : rename new_src by constant to get offset expr2tc offset = lexical_offset; if (is_locadd2t(src)) { @@ -675,8 +676,10 @@ expr2tc dereferencet::build_reference_to( const expr2tc &lexical_offset, expr2tc &pointer_guard) { - log_status("build reference to for:"); + log_status(" =================== build reference to =================== "); what->dump(); + deref_expr->dump(); + expr2tc value; pointer_guard = gen_false_expr(); @@ -841,10 +844,6 @@ expr2tc dereferencet::build_reference_to( } else { value = object; - // Produce a guard that the dereferenced pointer points at this object. - // type2tc ptr_type = pointer_type2tc(object->type); - // expr2tc obj_ptr = typecast2tc(ptr_type, object); - log_status("before building pointer guard"); value->dump(); deref_expr->dump(); @@ -878,7 +877,6 @@ expr2tc dereferencet::build_reference_to( abort(); } - log_status("generated pointer guard:"); pointer_guard->dump(); @@ -895,64 +893,27 @@ expr2tc dereferencet::build_reference_to( // Value set tracking emits objects with some cruft built on top of them. value = get_base_object(value); - value->dump(); - type->dump(); - // Final offset computations start here expr2tc final_offset = o.offset; + + if (!is_constant_int2t(final_offset) || + to_constant_int2t(final_offset).value.to_uint64() != 0) + { + log_error("Wrong offset for object"); + abort(); + } + #if 0 // FIXME: benchmark this, on tacas. dereference_callback.rename(final_offset); #endif - // If offset is unknown, or whatever, we have to consider it - // nondeterministic, and let the reference builders deal with it. + // maybe used later unsigned int alignment = o.alignment; - bool use_old_encoding = !options.get_bool_option("z3-slhv"); - if (use_old_encoding) - { - if (!is_constant_int2t(final_offset)) - { - assert(alignment != 0); - - /* The expression being dereferenced doesn't need to be just a symbol: it - * might have all kind of things messing with alignment in there. */ - if (!is_symbol2t(deref_expr)) - { - alignment = 1; - } - - final_offset = - pointer_offset2tc(get_int_type(config.ansi_c.address_width), deref_expr); - } - - type2tc offset_type = bitsize_type2(); - if (final_offset->type != offset_type) - final_offset = typecast2tc(offset_type, final_offset); - - // Converting final_offset from bytes to bits! - final_offset = - mul2tc(final_offset->type, final_offset, gen_long(final_offset->type, 8)); - - // Add any offset introduced lexically at the dereference site, i.e. member - // or index exprs, like foo->bar[3]. If bar is of integer type, we translate - // that to be a dereference of foo + extra_offset, resulting in an integer. - if (!is_nil_expr(lexical_offset)) - final_offset = add2tc(final_offset->type, final_offset, lexical_offset); - } - else - { - log_status("set final offset"); - final_offset->dump(); - if (!is_nil_expr(lexical_offset)) - final_offset = add2tc(final_offset->type, final_offset, lexical_offset); - - expr2tc simp = final_offset->simplify(); - if (!is_nil_expr(simp)) final_offset = simp; - - final_offset->dump(); - } + if (!is_nil_expr(lexical_offset)) + final_offset = add2tc(final_offset->type, final_offset, lexical_offset); + simplify(final_offset); // If we're in internal mode, collect all of our data into one struct, insert // it into the list of internal data, and then bail. The caller does not want @@ -961,50 +922,17 @@ expr2tc dereferencet::build_reference_to( { dereference_callbackt::internal_item internal; internal.object = value; - - if (use_old_encoding) - { - // Converting offset to bytes - internal.offset = typecast2tc( - signed_size_type2(), - div2tc( - final_offset->type, final_offset, gen_long(final_offset->type, 8))); - } - else - internal.offset = final_offset; - + internal.offset = final_offset; // offset for SLHV internal.guard = pointer_guard; internal_items.push_back(internal); return expr2tc(); } - if (is_code_type(value) || is_code_type(type)) - { - if (!check_code_access(value, final_offset, type, tmp_guard, mode)) - return expr2tc(); - /* here, both of them are code */ - } - else if (is_array_type(value)) // Encode some access bounds checks. - { - bounds_check(value, final_offset, type, tmp_guard); - } - else if (is_heap_region2t(value)) - { + // other checks may be added later + if (is_heap_region2t(value)) check_heap_region_access(value, final_offset, type, tmp_guard, mode); - } - else - { - check_data_obj_access(value, final_offset, type, tmp_guard, mode); - } - - simplify(final_offset); - - // Converting alignment to bits here - alignment *= 8; - // Call reference building methods. For the given data object in value, - // an expression of type type will be constructed that reads from it. - build_reference_slhv(value, final_offset, type, tmp_guard, mode, alignment); + build_deref_slhv(value, final_offset, type, tmp_guard, mode, alignment); return value; } @@ -1314,7 +1242,7 @@ void dereferencet::build_reference_rec( } } -void dereferencet::build_reference_slhv( +void dereferencet::build_deref_slhv( expr2tc &value, const expr2tc &offset, const type2tc &type, @@ -1322,50 +1250,59 @@ void dereferencet::build_reference_slhv( modet mode, unsigned long alignment) { - log_status("build reference slhv"); + log_status(" ----------------- build deref slhv ----------------- "); value->dump(); guard.dump(); offset->dump(); type->dump(); - assert(is_heap_region2t(value)); - if(is_scalar_type(type)) { - if (!is_constant_int2t(offset)) - { - // TODO : support - log_error("Do not support non-constant offset"); - abort(); - } - - unsigned int field = to_constant_int2t(offset).value.to_uint64(); - heap_region2t& heap_region = to_heap_region2t(value); - intheap_type2t &_type = to_intheap_type(heap_region.type); - - unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); - // heap region as a value - if (field == 0 && access_sz == _type.total_bytes) return; - - if (field >= _type.field_types.size() || - access_sz != _type.total_bytes / _type.field_types.size()) - { - // Out of bound or unaligned - expr2tc sym = symbol2tc( - type, - dereference_callback.get_nondet_id("undefined_behavior_var")); - value = sym; - return; - } - - if (_type.set_field_type(field, type)) - { - heap_region.flag->type = heap_region.type; - dereference_callback.update_heap_type(heap_region.flag); - } - value = fieldof2tc(type, value, gen_ulong(field)); - } else { + if (!is_scalar_type(type)) + { log_error("ERROR: currently not support non-scalar type dereference"); abort(); } + if (!is_constant_int2t(offset)) + { + // TODO : support + log_error("Do not support non-constant offset"); + abort(); + } + + heap_region2t& heap_region = to_heap_region2t(value); + unsigned int field = to_constant_int2t(offset).value.to_uint64(); + intheap_type2t &_type = to_intheap_type(heap_region.type); + unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); + + if (!_type.is_aligned) + { + log_error("heap region must be aligned"); + abort(); + } + + // heap region as a value + if (field == 0 && access_sz == _type.total_bytes) return; + + if (field >= _type.field_types.size() || + access_sz != _type.total_bytes / _type.field_types.size()) + { + // Out of bound or unaligned - undefined behavior + expr2tc sym = symbol2tc( + type, + dereference_callback.get_nondet_id("undefined_behavior_var")); + value = sym; + return; + } + else + value = fieldof2tc(type, value, gen_ulong(field)); + + // update field type + if (_type.set_field_type(field, type)) + { + heap_region.flag->type = heap_region.type; + dereference_callback.update_heap_type(heap_region.flag); + } + + log_status(" ----------------- build deref slhv ----------------- "); } void dereferencet::construct_from_array( @@ -2627,78 +2564,51 @@ void dereferencet::check_heap_region_access( modet mode) { // This check is in byte-level; - log_status("check heap region access"); - guard.dump(); - log_status("offset"); - offset->dump(); - assert(is_heap_region2t(value)); - const heap_region2t& heap_region = to_heap_region2t(value); - - heap_region.type->dump(); + // Since we construct offset in word level and store total bytes + // of region in heap_alloc_size, offset should be transfered to + // byte-level. - expr2tc offset_e = offset; - if (!is_constant_int2t(offset_e) && is_signedbv_type(offset_e)) - offset_e = offset_e.simplify(); - - std::string sz_id = dereference_callback.get_nondet_id("nondet_region_size::"); - expr2tc sz = symbol2tc(get_uint64_type(), sz_id); - expr2tc sz_pt = points_to2tc(heap_region.source_location, sz); - expr2tc alloc_size_heap; - migrate_expr( - symbol_expr( - *ns.lookup(dereference_callback.get_alloc_size_heap_name())), - alloc_size_heap); - expr2tc heap_ct = heap_contain2tc(sz_pt, alloc_size_heap); + log_status(" ------------------ check heap region access ------------------ "); + value->dump(); + offset->dump(); + type->dump(); + guard.dump(); - expr2tc data_sz = gen_ulong(type->get_width()); - expr2tc offset_check; - if (!is_constant_int2t(offset_e)) + if (!is_constant_int2t(offset)) { - // pointer arithmetic - if (is_add2t(offset_e) || is_sub2t(offset_e)) - { - expr2tc side_1 = is_add2t(offset_e) ? - to_add2t(offset_e).side_1 : to_sub2t(offset_e).side_1; - expr2tc side_2 = is_add2t(offset_e) ? - to_add2t(offset_e).side_2 : to_sub2t(offset_e).side_2; - - expr2tc ptr = is_pointer_type(side_1) ? side_1 : side_2; - expr2tc off = is_pointer_type(side_1) ? side_2 : side_1; - - if (!is_signedbv_type(off) && !is_unsignedbv_type(off)) - { - log_error("Do not support"); - abort(); - } - - std::string nondet_off_id = dereference_callback.get_nondet_id("nondet_off::"); - expr2tc off_var = symbol2tc(get_uint64_type(), nondet_off_id); + // TODO : support + log_error("Do not support non-constant offset"); + abort(); + } - expr2tc target_loc = locadd2tc(heap_region.source_location, off_var); - expr2tc offset_loc = locadd2tc(ptr, off_var); - expr2tc eq = equality2tc(target_loc, offset_loc); - expr2tc ge = greaterthanequal2tc(off_var, gen_ulong(0)); - expr2tc lt = lessthan2tc(off_var, sz); + const heap_region2t& heap_region = to_heap_region2t(value); + const intheap_type2t &_type = to_intheap_type(heap_region.type); - offset_check = and2tc(eq, and2tc(ge, lt)); - } - else - { - log_error("Do not support"); - abort(); - } - } - else + if (!_type.is_aligned) { - expr2tc off_var = offset_e; - offset_check = - and2tc( - greaterthanequal2tc(off_var, gen_ulong(0)), - lessthan2tc(off_var, sz) - ); + log_error("heap region must be aligned"); + abort(); } - expr2tc bound_check = not2tc(and2tc(heap_ct, offset_check)); + unsigned int _offset_bytes = + to_constant_int2t(offset).value.to_uint64() * 8; + expr2tc offset_bytes = gen_ulong(_offset_bytes); + + expr2tc total_bytes = gen_ulong(_type.total_bytes); + + expr2tc access_sz = gen_ulong(type_byte_size(type, &ns).to_uint64()); + expr2tc l = offset_bytes; + expr2tc r = add2tc(l->type, l, access_sz); + simplify(r); + expr2tc offset_cond = + and2tc( + greaterthanequal2tc(l, gen_ulong(0)), + lessthanequal2tc(r, total_bytes) + ); + + offset_cond->dump(); + + expr2tc bound_check = not2tc(offset_cond); if(!options.get_bool_option("no-bounds-check")) { guardt tmp_guard = guard; @@ -2709,7 +2619,8 @@ void dereferencet::check_heap_region_access( tmp_guard ); } - // TODO: maybe add alignment check + + log_status(" ------------------ check heap region access ------------------ "); } void dereferencet::check_alignment( diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index e1afbff1..5e1f8857 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -462,12 +462,16 @@ class dereferencet const type2tc &type, const guardt &guard, modet mode); + + // Offset is in word level(parameter) and alignment is + // in byte level. Alignment is in byte level(not used). void check_heap_region_access( const expr2tc &value, const expr2tc &offset, const type2tc &type, const guardt &guard, modet mode); + void check_alignment(BigInt minwidth, const expr2tc &offset, const guardt &guard); unsigned int static compute_num_bytes_to_extract( @@ -486,7 +490,11 @@ class dereferencet const guardt &guard, modet mode, unsigned long alignment = 0); - void build_reference_slhv( + + // SLHV does not have references in symbolic execution. + // Offset is in word level(parameter) and alignment is + // in byte level. Alignment is in byte level(not used). + void build_deref_slhv( expr2tc &value, const expr2tc &offset, const type2tc &type, diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 9c50cab0..e4651082 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -69,6 +69,10 @@ smt_convt::resultt z3_slhv_convt::dec_solve() { z3::check_result result = solver.check(); log_status("z3-slhv debug: after check"); + log_status("Dec result - {}", + result == z3::sat ? "sat" : + result == z3::unsat ? "unsat" : + "error"); if (result == z3::sat) return P_SATISFIABLE; From 2bc8a457f5f92d3f12d85ed24b36674e91805336 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 27 Aug 2024 19:21:19 +0800 Subject: [PATCH 058/126] make points-to for heap_contain --- src/goto-symex/dynamic_allocation.cpp | 19 +++++++----- src/irep2/irep2_expr.h | 31 ++++++++++--------- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 13 +++----- src/util/migrate.cpp | 4 +-- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index fb3784e3..9767a1de 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -34,11 +34,17 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_status(" --- generate cond for checking heap region --- "); const valid_object2t &obj = to_valid_object2t(expr); obj.dump(); - const heap_region2t& valid_inner = to_heap_region2t(obj.value); + const heap_region2t &valid_inner = to_heap_region2t(obj.value); + const intheap_type2t &_type = to_intheap_type(valid_inner.type); // get alloc size heap expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - expr2tc heap_contain = heap_contain2tc(valid_inner.source_location, alloc_size_heap); + + expr2tc size = gen_ulong(_type.total_bytes); + expr2tc heap_contain = + heap_contain2tc( + points_to2tc(valid_inner.source_location, size), + alloc_size_heap); expr = heap_contain; log_status(" --- generate cond for checking heap region --- "); } @@ -84,13 +90,12 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { + // TODO : support + log_error("Dot not support invalid pointer yet"); + abort(); + expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - - expr2tc heap_contain = heap_contain2tc(obj_expr, alloc_size_heap); - expr2tc not_valid = not2tc(heap_contain); - - expr = not_valid; } } else if (is_deallocated_obj2t(expr)) diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index dd9af0c8..8ace91fc 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1120,26 +1120,26 @@ class heap_delete_data : public expr2t { typedef esbmct::expr2t_traits traits; }; -class heap_contains_data : public expr2t { +class heap_contain_data : public expr2t { public: - heap_contains_data( + heap_contain_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &l, - const expr2tc &h) - : expr2t(t, id), location(l), heap(h) + const expr2tc &ht, + const expr2tc &th) + : expr2t(t, id), heap_term(ht), target_heap(th) { } - expr2tc location; - expr2tc heap; + expr2tc heap_term; + expr2tc target_heap; //Type mangling: - typedef esbmct::field_traits - location_field; - typedef esbmct::field_traits - heap_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + heap_term_field; + typedef esbmct::field_traits + target_heap_field; + typedef esbmct::expr2t_traits traits; }; /* ================================ SLHV ================================ */ @@ -1779,7 +1779,7 @@ irep_typedefs(fieldof, fieldof_data); irep_typedefs(heap_update, heap_update_data); irep_typedefs(heap_append, heap_append_data); irep_typedefs(heap_delete, heap_delete_data); -irep_typedefs(heap_contain, heap_contains_data); +irep_typedefs(heap_contain, heap_contain_data); irep_typedefs(isnan, bool_1op); irep_typedefs(overflow, overflow_ops); irep_typedefs(overflow_cast, overflow_cast_data); @@ -3380,8 +3380,9 @@ class heap_contain2t : public heap_contain_expr_methods { public: heap_contain2t( - const expr2tc &location, const expr2tc &heap) - : heap_contain_expr_methods(get_bool_type(), heap_contain_id, location, heap) + const expr2tc &heap_term, const expr2tc &target_heap) + : heap_contain_expr_methods( + get_bool_type(), heap_contain_id, heap_term, target_heap) { } heap_contain2t(const heap_contain2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 20d15dcc..910053c7 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -181,7 +181,7 @@ std::string heap_append2t::field_names[esbmct::num_type_fields] = std::string heap_delete2t::field_names[esbmct::num_type_fields] = {"source_heap", "location", "", "", ""}; std::string heap_contain2t::field_names[esbmct::num_type_fields] = - {"location", "heap", "", "", ""}; + {"heap_term", "target_heap", "", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string overflow2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 56d8109b..e21aa1fe 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -38,7 +38,7 @@ expr_typedefs3(fieldof, fieldof_data); expr_typedefs4(heap_update, heap_update_data); expr_typedefs2(heap_append, heap_append_data); expr_typedefs2(heap_delete, heap_delete_data); -expr_typedefs2(heap_contain, heap_contains_data); +expr_typedefs2(heap_contain, heap_contain_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); expr_typedefs2(dereference, dereference_data); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index e4651082..94b3e829 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -278,16 +278,13 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::heap_contain_id: { const heap_contain2t& heap_ct = to_heap_contain2t(expr); - smt_astt sh; - if (is_symbol2t(heap_ct.location) || is_pointer_object2t(heap_ct.location)) + if (!is_intheap_type(heap_ct.heap_term) || + !is_intheap_type(heap_ct.target_heap)) { - sh = mk_pt(args[0], mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::"))); - } - else if (is_points_to2t(heap_ct.location)) - { - sh = args[0]; + log_error("Wrong heap term"); + abort(); } - return mk_subh(sh, args[1]); + return mk_subh(args[0], args[1]); } case expr2t::fieldof_id: case expr2t::heap_update_id: diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 881ae168..7f008cc3 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2694,8 +2694,8 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_contain2t &ref2 = to_heap_contain2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_contain("heap_contain", thetype); - heap_contain.copy_to_operands(migrate_expr_back(ref2.location)); - heap_contain.copy_to_operands(migrate_expr_back(ref2.heap)); + heap_contain.copy_to_operands(migrate_expr_back(ref2.heap_term)); + heap_contain.copy_to_operands(migrate_expr_back(ref2.target_heap)); return heap_contain; } case expr2t::isnan_id: From c98663edd3cfb40fa91194ce627a1a7ef2e032d0 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 29 Aug 2024 14:42:56 +0800 Subject: [PATCH 059/126] add flagof --- src/goto-symex/dynamic_allocation.cpp | 5 +- src/goto-symex/goto_symex_state.cpp | 23 +-- src/goto-symex/symex_assign.cpp | 7 +- src/goto-symex/symex_main.cpp | 5 +- src/goto-symex/symex_target_equation.cpp | 15 -- src/irep2/irep2.h | 3 +- src/irep2/irep2_expr.cpp | 1 + src/irep2/irep2_expr.h | 173 ++++++------------ src/irep2/templates/irep2_templates.cpp | 4 +- .../templates/irep2_templates_expr_data.cpp | 16 +- .../templates/irep2_templates_expr_ops.cpp | 8 + src/pointer-analysis/dereference.cpp | 6 +- src/pointer-analysis/value_set.cpp | 16 +- src/solvers/smt/smt_conv.cpp | 1 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 97 +++++++--- src/util/migrate.cpp | 28 ++- src/util/type_byte_size.cpp | 7 +- 17 files changed, 203 insertions(+), 212 deletions(-) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 9767a1de..b3905450 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -43,8 +43,9 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc size = gen_ulong(_type.total_bytes); expr2tc heap_contain = heap_contain2tc( - points_to2tc(valid_inner.source_location, size), - alloc_size_heap); + alloc_size_heap, + points_to2tc(valid_inner.source_location, size) + ); expr = heap_contain; log_status(" --- generate cond for checking heap region --- "); } diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 9dcc4f44..496ec218 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -80,7 +80,7 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const } if (is_locationof2t(expr)) - return constant_propagation(to_locationof2t(expr).source_region); + return constant_propagation(to_locationof2t(expr).source_heap); if (is_array_type(expr)) { @@ -280,23 +280,20 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } - else if (!is_heap_region2t(expr)) + else if (is_heap_region2t(expr)) { - // do this recursively - expr->Foreach_operand([this](expr2tc &e) { rename(e); }); - } - - // If we get a heap region from a symbol, then set the flag to - // the newest one. Since some variable will be reset to l1 version, - // it is also neccessary to rename source location. - if (is_heap_region2t(expr)) - { - // Only need to rename flag to l2 since source location - // already has l2 name. heap_region2t &heap_region = to_heap_region2t(expr); rename(heap_region.source_location); + // Return to l1 name first + level2.get_original_name(heap_region.flag); + // Get the newest l2 name level2.get_ident_name(heap_region.flag); } + else + { + // do this recursively + expr->Foreach_operand([this](expr2tc &e) { rename(e); }); + } } void goto_symex_statet::rename_address(expr2tc &expr) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index ab6c5bbf..8076f61a 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -906,14 +906,15 @@ void goto_symext::symex_assign_fieldof( assert(is_scalar_type(rhs)); const fieldof2t& fieldof = to_fieldof2t(lhs); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); + const expr2tc &field = fieldof.operand; expr2tc update_heap = - heap_update2tc(heap_region.type, fieldof.source_region, fieldof.field, rhs); + heap_update2tc(heap_region.type, fieldof.source_heap, field, rhs); symex_assign_rec( heap_region.flag, - fieldof.source_region, + fieldof.source_heap, update_heap, update_heap, guard, hidden); diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 5444332a..df99dbda 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1223,10 +1223,11 @@ void goto_symext::add_memory_leak_checks() "dereference failure: forgotten memory: " + get_pretty_name(it.name)); } } else { - log_status(" ----------- [memleak encoding ]----------- "); + log_status(" ----------- [memleak encoding]----------- "); for (auto const &it : dynamic_memory){ log_status("allocated object {}: ", it.name); - expr2tc deallocated = equality2tc(it.obj, gen_emp()); + expr2tc obj_flag = flagof2tc(it.obj); + expr2tc deallocated = equality2tc(obj_flag, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); cur_state->rename(cond); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index be3fe7f8..6929b399 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -160,26 +160,11 @@ void symex_target_equationt::convert_internal_step( if (step.ignore) { - // std::ostringstream oss; - // step.output(ns, oss); - // log_status("{}", oss.str()); - // log_status("convert internal step ignored ------ "); - - // log_status("-------------- over -----------------"); step.cond_ast = true_val; step.guard_ast = false_val; return; } - if (ssa_trace) - { - // log_status("-------------- ssa trace -----------------"); - // std::ostringstream oss; - // step.output(ns, oss); - // log_status("{}", oss.str()); - // log_status("-------------- ssa trace end -----------------"); - } - log_status(" ============================== step ======================== "); step.dump(); log_status(" ============================== step ======================== "); diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 13a44369..601c5774 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -107,6 +107,7 @@ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(heap_region, \ + BOOST_PP_LIST_CONS(flagof, \ BOOST_PP_LIST_CONS(locationof, \ BOOST_PP_LIST_CONS(fieldof, \ BOOST_PP_LIST_CONS(heap_update, \ @@ -153,7 +154,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index f293ef80..a49356a6 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -78,6 +78,7 @@ static const char *expr_names[] = { "uplus", "locadd", "heap_region", + "flagof", "locationof", "fieldof", "heap_update", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 8ace91fc..4ef14c45 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1005,141 +1005,71 @@ class heap_region_data : public expr2t typedef esbmct::expr2t_traits traits; }; -class locationof_data : public expr2t +class heap_ops : public expr2t { public: - locationof_data( + heap_ops( const type2tc &t, - datatype_ops::expr_ids id, - const expr2tc &ht) - : expr2t(t, id), source_region(ht) + expr2t::expr_ids id, + const expr2tc &h) + : expr2t(t, id), source_heap(h) { } - locationof_data(const locationof_data& ref) = default; + heap_ops(const heap_ops& ref) = default; - expr2tc source_region; + expr2tc source_heap; // Type mangling: - typedef esbmct::field_traits - heap_term_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + source_heap_field; + typedef esbmct::expr2t_traits traits; }; -class fieldof_data : public expr2t +class heap_1op : public heap_ops { public: - fieldof_data( + heap_1op( const type2tc &t, - datatype_ops::expr_ids id, - const expr2tc &hr, - const expr2tc &f) - : expr2t(t, id), source_region(hr), field(f) + heap_ops::expr_ids id, + const expr2tc &h, + const expr2tc &op) + : heap_ops(t, id, h), operand(op) { } - fieldof_data(const fieldof_data &ref) = default; + heap_1op(const heap_1op &ref) = default; - expr2tc source_region; - expr2tc field; + expr2tc operand; // Type mangling: - typedef esbmct::field_traits - heap_region_field; - typedef esbmct::field_traits - field_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + operand_field; + typedef esbmct::expr2t_traits traits; }; -class heap_update_data : public expr2t +class heap_2ops : public heap_ops { public: - heap_update_data( + heap_2ops( const type2tc &t, - datatype_ops::expr_ids id, - const expr2tc &sh, - const expr2tc &uf, - const expr2tc &uv) - : expr2t(t, id), source_region(sh), update_field(uf), update_value(uv) + heap_ops::expr_ids id, + const expr2tc &h, + const expr2tc &op1, + const expr2tc &op2) + : heap_ops(t, id, h), operand_1(op1), operand_2(op2) { } + heap_2ops(const heap_2ops &ref) = default; - expr2tc source_region; - expr2tc update_field; - expr2tc update_value; + expr2tc operand_1; + expr2tc operand_2; // Type mangling: - typedef esbmct::field_traits - source_heap_field; - typedef esbmct::field_traits - update_field_field; - typedef esbmct::field_traits - update_value_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_append_data : public expr2t { -public: - heap_append_data( - const type2tc & t, - datatype_ops::expr_ids id, - const expr2tc &sh, - const expr2tc &ht) - : expr2t(t, id), source_heap(sh), heap_term(ht) - { - } - - expr2tc source_heap; - expr2tc heap_term; - - // Type mangling: - typedef esbmct::field_traits - source_heap_field; - typedef esbmct::field_traits - heap_term_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_delete_data : public expr2t { -public: - heap_delete_data( - const type2tc & t, - datatype_ops::expr_ids id, - const expr2tc &sh, - const expr2tc &l) - : expr2t(t, id), source_heap(sh), location(l) - { - } - - expr2tc source_heap; - expr2tc location; - - // Type mangling: - typedef esbmct::field_traits - source_heap_field; - typedef esbmct::field_traits - location_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_contain_data : public expr2t { -public: - heap_contain_data( - const type2tc &t, - datatype_ops::expr_ids id, - const expr2tc &ht, - const expr2tc &th) - : expr2t(t, id), heap_term(ht), target_heap(th) - { - } - - expr2tc heap_term; - expr2tc target_heap; - - //Type mangling: - typedef esbmct::field_traits - heap_term_field; - typedef esbmct::field_traits - target_heap_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::field_traits + operand_1_field; + typedef esbmct::field_traits + operand_2_field; + typedef esbmct::expr2t_traits< + source_heap_field, operand_1_field, operand_2_field> traits; }; /* ================================ SLHV ================================ */ @@ -1774,12 +1704,13 @@ irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); irep_typedefs(heap_region, heap_region_data); -irep_typedefs(locationof, locationof_data); -irep_typedefs(fieldof, fieldof_data); -irep_typedefs(heap_update, heap_update_data); -irep_typedefs(heap_append, heap_append_data); -irep_typedefs(heap_delete, heap_delete_data); -irep_typedefs(heap_contain, heap_contain_data); +irep_typedefs(flagof, heap_ops); +irep_typedefs(locationof, heap_ops); +irep_typedefs(fieldof, heap_1op); +irep_typedefs(heap_update, heap_2ops); +irep_typedefs(heap_append, heap_1op); +irep_typedefs(heap_delete, heap_1op); +irep_typedefs(heap_contain, heap_1op); irep_typedefs(isnan, bool_1op); irep_typedefs(overflow, overflow_ops); irep_typedefs(overflow_cast, overflow_cast_data); @@ -3300,6 +3231,18 @@ class heap_region2t : public heap_region_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +class flagof2t : public flagof_expr_methods +{ +public: + flagof2t(const expr2tc &source_region) + : flagof_expr_methods(get_intheap_type(), flagof_id, source_region) + { + } + flagof2t(const flagof2t &ref) = default; + + static std::string field_names[esbmct::num_type_fields]; +}; + class locationof2t : public locationof_expr_methods { public: @@ -3380,9 +3323,9 @@ class heap_contain2t : public heap_contain_expr_methods { public: heap_contain2t( - const expr2tc &heap_term, const expr2tc &target_heap) + const expr2tc &source_heap, const expr2tc &heap_term) : heap_contain_expr_methods( - get_bool_type(), heap_contain_id, heap_term, target_heap) + get_bool_type(), heap_contain_id, source_heap, heap_term) { } heap_contain2t(const heap_contain2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 910053c7..bbf67151 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -170,6 +170,8 @@ std::string locadd2t::field_names[esbmct::num_type_fields] = {"location", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = {"flag", "source_location", "", "", ""}; +std::string flagof2t::field_names[esbmct::num_type_fields] = + {"source_region", "", "", "", ""}; std::string locationof2t::field_names[esbmct::num_type_fields] = {"source_region", "", "", "", ""}; std::string fieldof2t::field_names[esbmct::num_type_fields] = @@ -181,7 +183,7 @@ std::string heap_append2t::field_names[esbmct::num_type_fields] = std::string heap_delete2t::field_names[esbmct::num_type_fields] = {"source_heap", "location", "", "", ""}; std::string heap_contain2t::field_names[esbmct::num_type_fields] = - {"heap_term", "target_heap", "", "", ""}; + {"source_heap", "heap_term", "", "", ""}; std::string isnan2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string overflow2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index e21aa1fe..014f26c8 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -29,16 +29,6 @@ expr_typedefs4(byte_update, byte_update_data); expr_typedefs3(with, with_data); expr_typedefs2(member, member_data); expr_typedefs2(index, index_data); -expr_typedefs2(points_to, points_to_data); -expr_typedefs1(uplus, uplus_data); -expr_typedefs2(locadd, locadd_data); -expr_typedefs3(heap_region, heap_region_data); -expr_typedefs1(locationof, locationof_data); -expr_typedefs3(fieldof, fieldof_data); -expr_typedefs4(heap_update, heap_update_data); -expr_typedefs2(heap_append, heap_append_data); -expr_typedefs2(heap_delete, heap_delete_data); -expr_typedefs2(heap_contain, heap_contain_data); expr_typedefs2(overflow_cast, overflow_cast_data); expr_typedefs3(dynamic_object, dynamic_object_data); expr_typedefs2(dereference, dereference_data); @@ -65,3 +55,9 @@ expr_typedefs2(code_cpp_throw, code_cpp_throw_data); expr_typedefs2(code_cpp_throw_decl, code_cpp_throw_decl_data); expr_typedefs1(code_cpp_throw_decl_end, code_cpp_throw_decl_data); expr_typedefs3(extract, extract_data); + + +expr_typedefs2(points_to, points_to_data); +expr_typedefs1(uplus, uplus_data); +expr_typedefs2(locadd, locadd_data); +expr_typedefs3(heap_region, heap_region_data); \ No newline at end of file diff --git a/src/irep2/templates/irep2_templates_expr_ops.cpp b/src/irep2/templates/irep2_templates_expr_ops.cpp index 01a7cf7b..338cf3ef 100644 --- a/src/irep2/templates/irep2_templates_expr_ops.cpp +++ b/src/irep2/templates/irep2_templates_expr_ops.cpp @@ -46,3 +46,11 @@ expr_typedefs1(bswap, arith_1op); expr_typedefs2(concat, bit_2ops); expr_typedefs1(isnan, bool_1op); expr_typedefs1(overflow_neg, overflow_ops); + +expr_typedefs1(locationof, heap_ops); +expr_typedefs1(flagof, heap_ops); +expr_typedefs3(fieldof, heap_1op); +expr_typedefs4(heap_update, heap_2ops); +expr_typedefs2(heap_append, heap_1op); +expr_typedefs2(heap_delete, heap_1op); +expr_typedefs2(heap_contain, heap_1op); \ No newline at end of file diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 063fc720..3ae141e1 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -442,18 +442,18 @@ expr2tc dereferencet::dereference_expr_nonscalar( { fieldof2t &fieldof = to_fieldof2t(expr); - if (!is_dereference2t(fieldof.source_region)) + if (!is_dereference2t(fieldof.source_heap)) { log_error("Do not support struct in struct yet"); abort(); } - dereference2t &deref = to_dereference2t(fieldof.source_region); + dereference2t &deref = to_dereference2t(fieldof.source_heap); // Get the heap region dereference_expr(deref.value, guard, dereferencet::READ); - expr2tc offset_to_scalar = fieldof.field; + expr2tc offset_to_scalar = fieldof.operand; simplify(offset_to_scalar); return dereference(deref.value, base->type, guard, mode, offset_to_scalar); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index bd1f7058..34477f95 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -600,7 +600,7 @@ void value_sett::get_value_set_rec( if (is_locationof2t(expr)) { get_value_set_rec( - to_locationof2t(expr).source_region, + to_locationof2t(expr).source_heap, dest, suffix, original_type ); return; @@ -609,8 +609,8 @@ void value_sett::get_value_set_rec( if (is_fieldof2t(expr)) { const fieldof2t &fieldof = to_fieldof2t(expr); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); - expr2tc field = fieldof.field; + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); + expr2tc field = fieldof.operand; if (!is_constant_int2t(field)) { @@ -1250,9 +1250,11 @@ void value_sett::assign( if (to_intheap_type(lhs_type).is_region && is_heap_update2t(rhs)) { const heap_update2t &heap_upd = to_heap_update2t(rhs); + const expr2tc &upd_field = heap_upd.operand_1; + const expr2tc &upd_value = heap_upd.operand_2; expr2tc lhs_field = - fieldof2tc(rhs->type, heap_upd.source_region, heap_upd.update_field); - assign(lhs_field, heap_upd.update_value, add_to_sets); + fieldof2tc(rhs->type, heap_upd.source_heap, upd_field); + assign(lhs_field, upd_value, add_to_sets); return; } } @@ -1412,7 +1414,7 @@ void value_sett::assign_rec( { const fieldof2t &fieldof = to_fieldof2t(lhs); - expr2tc field = fieldof.field; + expr2tc field = fieldof.operand; if (!is_constant_int2t(field)) { log_error("Do not support dynamic offset yet"); @@ -1421,7 +1423,7 @@ void value_sett::assign_rec( unsigned int _field = to_constant_int2t(field).value.to_uint64(); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); assign_rec( heap_region.flag, diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 39a92714..efc37b22 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -346,6 +346,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: case expr2t::heap_region_id: + case expr2t::flagof_id: case expr2t::locationof_id: case expr2t::fieldof_id: case expr2t::points_to_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 94b3e829..8df266bc 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -237,15 +237,36 @@ z3_slhv_convt::convert_slhv_opts( } return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); } + case expr2t::flagof_id: + { + const flagof2t &flagof = to_flagof2t(expr); + + if (is_symbol2t(flagof.source_heap)) + { + if (!is_intheap_type(flagof.source_heap->type)) + { + log_error("Wrong intheap type"); + abort(); + } + return args[0]; + } + + if (!is_heap_region2t(flagof.source_heap)) + { + log_error("We can't get a location of a non-region heap"); + abort(); + } + return convert_ast(to_heap_region2t(flagof.source_heap).flag); + } case expr2t::locationof_id: { const locationof2t &locof = to_locationof2t(expr); - if (!is_heap_region2t(locof.source_region)) + if (!is_heap_region2t(locof.source_heap)) { log_error("We can't get a location of a non-region heap"); abort(); } - return convert_ast(to_heap_region2t(locof.source_region).source_location); + return convert_ast(to_heap_region2t(locof.source_heap).source_location); } case expr2t::points_to_id: { @@ -270,6 +291,11 @@ z3_slhv_convt::convert_slhv_opts( } case expr2t::heap_append_id: { + const heap_append2t &heap_app = to_heap_append2t(expr); + + if (is_constant_intheap2t(heap_app.source_heap)) + return args[1]; + smt_astt h = args[0]; smt_astt t = args[1]; // new heap state @@ -278,13 +304,14 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::heap_contain_id: { const heap_contain2t& heap_ct = to_heap_contain2t(expr); - if (!is_intheap_type(heap_ct.heap_term) || - !is_intheap_type(heap_ct.target_heap)) + const expr2tc &src_heap = heap_ct.source_heap; + const expr2tc &heap_term = heap_ct.operand; + if (!is_intheap_type(src_heap) || !is_intheap_type(heap_term)) { log_error("Wrong heap term"); abort(); } - return mk_subh(args[0], args[1]); + return mk_subh(args[1], args[0]); } case expr2t::fieldof_id: case expr2t::heap_update_id: @@ -322,29 +349,31 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) { const fieldof2t &fieldof = to_fieldof2t(expr); - if (!is_heap_region2t(fieldof.source_region)) + if (is_constant_intheap2t(fieldof.source_heap)) + return std::make_pair( + mk_smt_bool(true), + mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); + + if (!is_heap_region2t(fieldof.source_heap)) { log_error("We can't get a location of a non-region heap"); abort(); } - if (!is_constant_int2t(fieldof.field)) + if (!is_constant_int2t(fieldof.operand)) { log_error("Wrong field"); abort(); } - if (is_constant_intheap2t(fieldof.source_region)) - return std::make_pair( - mk_smt_bool(true), - mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); - unsigned int field = to_constant_int2t(fieldof.field).value.to_uint64(); - - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_region); + const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); const intheap_type2t &_type = to_intheap_type(heap_region.type); - + const expr2tc &field = fieldof.operand; + + unsigned int _field = to_constant_int2t(field).value.to_uint64(); + smt_astt source_loc = convert_ast(heap_region.source_location); - smt_astt loc = field == 0 ? - source_loc : mk_locadd(source_loc, convert_ast(fieldof.field)); + smt_astt loc = _field == 0 ? + source_loc : mk_locadd(source_loc, convert_ast(field)); smt_sortt s1; std::string name; @@ -355,9 +384,9 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) } else { - s1 = is_intloc_type(_type.field_types[field]) ? mk_intloc_sort() : mk_int_sort(); + s1 = is_intloc_type(_type.field_types[_field]) ? mk_intloc_sort() : mk_int_sort(); name = mk_fresh_name( - is_intloc_type(_type.field_types[field]) ? "tmp_loc::" : "tmp_val::"); + is_intloc_type(_type.field_types[_field]) ? "tmp_loc::" : "tmp_val::"); } smt_astt v1 = mk_fresh(s1, name); @@ -367,35 +396,45 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) case expr2t::heap_update_id: { const heap_update2t &heap_upd = to_heap_update2t(expr); - if (!is_heap_region2t(heap_upd.source_region)) + if (!is_heap_region2t(heap_upd.source_heap)) { log_error("Do not support heap update for other heap terms"); abort(); } + if (!is_constant_int2t(heap_upd.operand_1)) + { + log_error("Wrong field"); + abort(); + } + + const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_heap); + const expr2tc &upd_field = heap_upd.operand_1; + const expr2tc &upd_value = heap_upd.operand_2; - const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_region); + unsigned int _field = to_constant_int2t(upd_field).value.to_uint64(); smt_astt h = convert_ast(heap_region.flag); smt_astt source_loc = convert_ast(heap_region.source_location); - smt_astt field = convert_ast(heap_upd.update_field); - smt_astt loc = mk_locadd(source_loc, field); - smt_astt val = convert_ast(heap_upd.update_value); + smt_astt field = convert_ast(upd_field); + smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, field); + smt_astt val = convert_ast(upd_value); smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); // current heap state - smt_astt assert_expr = mk_eq(h, mk_uplus(mk_pt(loc, v1), h1)); + smt_astt h_state = mk_uplus(h1, mk_pt(loc, v1)); + smt_astt assert_expr = mk_eq(h, h_state); // new heap state - return std::make_pair(assert_expr, mk_uplus(mk_pt(loc, val), h1)); + return std::make_pair(assert_expr, h_state); } case expr2t::heap_delete_id: { const heap_delete2t &heap_del = to_heap_delete2t(expr); smt_astt h = convert_ast(heap_del.source_heap); - smt_astt l = convert_ast(heap_del.location); + smt_astt l = convert_ast(heap_del.operand); smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); @@ -416,8 +455,10 @@ z3_slhv_convt::project(const expr2tc &expr) return convert_opt_without_assert(expr); else if (is_heap_region2t(expr)) return this->project(to_heap_region2t(expr).source_location); + else if (is_flagof2t(expr)) + return this->project(to_flagof2t(expr).source_heap); else if (is_locationof2t(expr)) - return this->project(to_locationof2t(expr).source_region); + return this->project(to_locationof2t(expr).source_heap); else if (is_fieldof2t(expr)) return convert_opt_without_assert(expr); else if (is_typecast2t(expr)) diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 7f008cc3..56a54f74 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2644,12 +2644,20 @@ exprt migrate_expr_back(const expr2tc &ref) region.copy_to_operands(migrate_expr_back(ref2.source_location)); return region; } + case expr2t::flagof_id: + { + const flagof2t &ref2 = to_flagof2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt flagof("flagof", thetype); + flagof.copy_to_operands(migrate_expr_back(ref2.source_heap)); + return flagof; + } case expr2t::locationof_id: { const locationof2t &ref2 = to_locationof2t(ref); typet thetype = migrate_type_back(ref->type); exprt locationof("locationof", thetype); - locationof.copy_to_operands(migrate_expr_back(ref2.source_region)); + locationof.copy_to_operands(migrate_expr_back(ref2.source_heap)); return locationof; } case expr2t::fieldof_id: @@ -2657,8 +2665,8 @@ exprt migrate_expr_back(const expr2tc &ref) const fieldof2t &ref2 = to_fieldof2t(ref); typet thetype = migrate_type_back(ref->type); exprt fieldof("fieldof", thetype); - fieldof.copy_to_operands(migrate_expr_back(ref2.source_region)); - fieldof.copy_to_operands(migrate_expr_back(ref2.field)); + fieldof.copy_to_operands(migrate_expr_back(ref2.source_heap)); + fieldof.copy_to_operands(migrate_expr_back(ref2.operand)); return fieldof; } case expr2t::heap_update_id: @@ -2666,9 +2674,9 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_update2t &ref2 = to_heap_update2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_update("heap_update", thetype); - heap_update.copy_to_operands(migrate_expr_back(ref2.source_region)); - heap_update.copy_to_operands(migrate_expr_back(ref2.update_field)); - heap_update.copy_to_operands(migrate_expr_back(ref2.update_value)); + heap_update.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_update.copy_to_operands(migrate_expr_back(ref2.operand_1)); + heap_update.copy_to_operands(migrate_expr_back(ref2.operand_2)); return heap_update; } case expr2t::heap_append_id: @@ -2677,7 +2685,7 @@ exprt migrate_expr_back(const expr2tc &ref) typet thetype = migrate_type_back(ref->type); exprt heap_append("heap_append", thetype); heap_append.copy_to_operands(migrate_expr_back(ref2.source_heap)); - heap_append.copy_to_operands(migrate_expr_back(ref2.heap_term)); + heap_append.copy_to_operands(migrate_expr_back(ref2.operand)); return heap_append; } case expr2t::heap_delete_id: @@ -2686,7 +2694,7 @@ exprt migrate_expr_back(const expr2tc &ref) typet thetype = migrate_type_back(ref->type); exprt heap_delete("heap_delete", thetype); heap_delete.copy_to_operands(migrate_expr_back(ref2.source_heap)); - heap_delete.copy_to_operands(migrate_expr_back(ref2.location)); + heap_delete.copy_to_operands(migrate_expr_back(ref2.operand)); return heap_delete; } case expr2t::heap_contain_id: @@ -2694,8 +2702,8 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_contain2t &ref2 = to_heap_contain2t(ref); typet thetype = migrate_type_back(ref->type); exprt heap_contain("heap_contain", thetype); - heap_contain.copy_to_operands(migrate_expr_back(ref2.heap_term)); - heap_contain.copy_to_operands(migrate_expr_back(ref2.target_heap)); + heap_contain.copy_to_operands(migrate_expr_back(ref2.source_heap)); + heap_contain.copy_to_operands(migrate_expr_back(ref2.operand)); return heap_contain; } case expr2t::isnan_id: diff --git a/src/util/type_byte_size.cpp b/src/util/type_byte_size.cpp index 6ba2a7ad..0d5be611 100644 --- a/src/util/type_byte_size.cpp +++ b/src/util/type_byte_size.cpp @@ -453,12 +453,15 @@ const expr2tc &get_base_object(const expr2tc &expr) if (is_dereference2t(expr)) return get_base_object(to_dereference2t(expr).value); + + if (is_flagof2t(expr)) + return get_base_object(to_flagof2t(expr).source_heap); if (is_locationof2t(expr)) - return get_base_object(to_locationof2t(expr).source_region); + return get_base_object(to_locationof2t(expr).source_heap); if (is_fieldof2t(expr)) - return get_base_object(to_fieldof2t(expr).source_region); + return get_base_object(to_fieldof2t(expr).source_heap); return expr; } From d182cd33f6a47f0178e0e66b20fb653a3f3078c4 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 30 Aug 2024 09:50:33 +0800 Subject: [PATCH 060/126] adjust condition for symex_free --- src/goto-symex/builtin_functions.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index e29b2306..2f107035 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -455,29 +455,28 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(valid_index_expr, falsity), true); } else { expr2tc free_ptr = code.operand; - expr2tc is_src_loc = gen_false_expr(); + expr2tc when = gen_false_expr(); // set each heap region to empty, guarded by item.gurad for(auto const& item : internal_deref_items) { assert(is_heap_region2t(item.object)); + log_status("free object guard"); + item.guard->dump(); + const heap_region2t& heap_region = to_heap_region2t(item.object); expr2tc free_heap = heap_region.flag; - expr2tc free_loc = heap_region.source_location; - expr2tc emp_heap = gen_emp(); + guardt g; g.add(item.guard); + symex_assign(code_assign2tc(free_heap, gen_emp()), false, g); - expr2tc _is_src_loc = equality2tc(free_ptr, free_loc); - is_src_loc = or2tc(is_src_loc, _is_src_loc); - - guardt g; g.add(_is_src_loc); - symex_assign(code_assign2tc(free_heap, emp_heap), false, g); + // collect guards for deleting heap alloc size + when = or2tc(when, item.guard); } // delete the pointer in alloc_size heap expr2tc alloc_size_heap = symbol2tc(get_intheap_type(), alloc_size_heap_name); expr2tc new_heap = heap_delete2tc(alloc_size_heap, free_ptr); - guardt g; g.add(is_src_loc); + guardt g; g.add(when); symex_assign(code_assign2tc(alloc_size_heap, new_heap), false, g); } - log_status("xxxxxxx symex free done"); } From 99541ca4a17e8e2bd51288903b7dc77e87785f8a Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 30 Aug 2024 14:50:56 +0800 Subject: [PATCH 061/126] move region info to intheap type --- src/goto-symex/builtin_functions.cpp | 21 ++--- src/goto-symex/dynamic_allocation.cpp | 14 +++- src/goto-symex/goto_symex.h | 4 +- src/goto-symex/goto_symex_state.cpp | 24 +----- src/goto-symex/slice.cpp | 19 ++--- src/goto-symex/symex_assign.cpp | 19 ++--- src/goto-symex/symex_dereference.cpp | 66 +++++---------- src/goto-symex/symex_main.cpp | 3 +- src/irep2/irep2.h | 3 +- src/irep2/irep2_expr.cpp | 1 - src/irep2/irep2_expr.h | 13 --- src/irep2/irep2_type.h | 16 +++- src/irep2/templates/irep2_templates.cpp | 4 +- .../templates/irep2_templates_expr_ops.cpp | 1 - src/pointer-analysis/dereference.cpp | 83 +++++++++---------- src/pointer-analysis/dereference.h | 4 +- src/pointer-analysis/value_set.cpp | 35 +++++--- src/solvers/smt/smt_conv.cpp | 1 - src/solvers/z3-slhv/z3_slhv_conv.cpp | 67 ++++----------- src/util/c_types.cpp | 3 +- src/util/migrate.cpp | 8 -- src/util/type_byte_size.cpp | 3 - 22 files changed, 159 insertions(+), 253 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 2f107035..9422f210 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -281,10 +281,7 @@ expr2tc goto_symext::symex_mem( symbol.mode = "C"; new_context.add(symbol); - expr2tc rhs_heap = symbol2tc(heap_type, symbol.id); - guardt rhs_guard = cur_state->guard; - - // set a location for new heap region + // create a new location for new heap region symbolt heap_region_loc; heap_region_loc.name = "heap_region_loc_"+ i2string(dynamic_counter); @@ -301,6 +298,12 @@ expr2tc goto_symext::symex_mem( // use l2 symbol, do not need to be renamed cur_state->rename(rhs_base_loc); + // store base location in intheap type + _heap_type.location = rhs_base_loc; + + expr2tc rhs_heap = symbol2tc(heap_type, symbol.id); + guardt rhs_guard = cur_state->guard; + expr2tc rhs_region = heap_region2tc(heap_type, rhs_heap, rhs_base_loc); log_status("symex assign in symex_mem: allocated_heap = heaplet"); @@ -320,7 +323,7 @@ expr2tc goto_symext::symex_mem( ); log_status("create valueset base loc symbol and assign"); - symex_assign(code_assign2tc(lhs, locationof2tc(rhs_region))); + symex_assign(code_assign2tc(lhs, locationof2tc(rhs_heap))); return expr2tc(); } @@ -459,14 +462,12 @@ void goto_symext::symex_free(const expr2tc &expr) // set each heap region to empty, guarded by item.gurad for(auto const& item : internal_deref_items) { - assert(is_heap_region2t(item.object)); + assert(is_intheap_type(item.object)); log_status("free object guard"); item.guard->dump(); - - const heap_region2t& heap_region = to_heap_region2t(item.object); - expr2tc free_heap = heap_region.flag; + guardt g; g.add(item.guard); - symex_assign(code_assign2tc(free_heap, gen_emp()), false, g); + symex_assign(code_assign2tc(item.object, gen_emp()), false, g); // collect guards for deleting heap alloc size when = or2tc(when, item.guard); diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index b3905450..02ea409c 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -33,9 +33,15 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) // Checking that the object is valid by heap_alloc_size log_status(" --- generate cond for checking heap region --- "); const valid_object2t &obj = to_valid_object2t(expr); - obj.dump(); - const heap_region2t &valid_inner = to_heap_region2t(obj.value); - const intheap_type2t &_type = to_intheap_type(valid_inner.type); + const expr2tc &heap_region = obj.value; + if (!is_intheap_type(heap_region->type) || + !to_intheap_type(heap_region->type).is_region) + { + log_error("Wrong object"); + abort(); + } + + const intheap_type2t &_type = to_intheap_type(heap_region->type); // get alloc size heap expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); @@ -44,7 +50,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc heap_contain = heap_contain2tc( alloc_size_heap, - points_to2tc(valid_inner.source_location, size) + points_to2tc(_type.location, size) ); expr = heap_contain; log_status(" --- generate cond for checking heap region --- "); diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index eb21851b..71b248ab 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -969,8 +969,8 @@ class symex_dereference_statet : public dereference_callbackt dump_internal_state(const std::list &data) override; bool is_live_variable(const expr2tc &sym) override; - void update_heap_type(const expr2tc &flag) override; - void update_heap_type_rec(expr2tc &expr, const symbol2t &flag) override; + void update_heap_type(const intheap_type2t &type) override; + void update_heap_type_rec(expr2tc &expr, const intheap_type2t &type) override; std::string get_nondet_id(std::string prefix = "") override; irep_idt get_alloc_size_heap_name() override; }; diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 496ec218..92f179f9 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -67,9 +67,7 @@ void goto_symex_statet::initialize( bool goto_symex_statet::constant_propagation(const expr2tc &expr) const { // SLHV propagation - if (is_constant_intheap2t(expr) || - is_constant_intloc2t(expr) || - is_heap_region2t(expr)) + if (is_constant_intheap2t(expr) || is_constant_intloc2t(expr)) return true; if (is_locadd2t(expr)) @@ -210,13 +208,6 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) expr2tc l1_lhs = lhs; expr2tc const_value = constant_propagation(rhs) ? rhs : expr2tc(); - - // Each heap region has only one unique flag that does not change - // during its lifetime. The l1 version of flag is the representation. - // For constant_propagation, all heap regions should hold their flag. - if (!is_nil_expr(const_value) && is_heap_region2t(const_value)) - level2.get_original_name(to_heap_region2t(const_value).flag); - level2.make_assignment(lhs, const_value, rhs); if (use_value_set) @@ -230,6 +221,7 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) l1_lhs->dump(); log_status("#####"); value_set.assign(l1_lhs, l1_rhs); + log_status("update value set done!!!!"); } } @@ -263,7 +255,8 @@ void goto_symex_statet::rename_type(expr2tc &expr) void goto_symex_statet::rename(expr2tc &expr) { // rename all the symbols with their last known value - if (is_nil_expr(expr)) + if (is_nil_expr(expr) || + is_heap_region2t(expr)) return; rename_type(expr); @@ -280,15 +273,6 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } - else if (is_heap_region2t(expr)) - { - heap_region2t &heap_region = to_heap_region2t(expr); - rename(heap_region.source_location); - // Return to l1 name first - level2.get_original_name(heap_region.flag); - // Get the newest l2 name - level2.get_ident_name(heap_region.flag); - } else { // do this recursively diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 8e7def16..b1d97c6a 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -15,19 +15,14 @@ bool symex_slicet::get_symbols(const expr2tc &expr) // locationof only has heap_region as oprend // the location of heap_region is completely fresh // and is not being used in symbolic execution - if (is_locationof2t(expr)) return false; + if (is_locationof2t(expr) || is_heap_region2t(expr)) return false; - if (is_heap_region2t(expr)) - return get_symbols(to_heap_region2t(expr).flag); - else - { - // Recursively look if any of the operands has a inner symbol - expr->foreach_operand([this, &res](const expr2tc &e) { - if (!is_nil_expr(e)) - res |= get_symbols(e); - return res; - }); - } + // Recursively look if any of the operands has a inner symbol + expr->foreach_operand([this, &res](const expr2tc &e) { + if (!is_nil_expr(e)) + res |= get_symbols(e); + return res; + }); if (!is_symbol2t(expr)) return res; diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 8076f61a..c734ce2d 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -294,6 +294,7 @@ void goto_symext::symex_assign_rec( { log_status("symex_assign_symbol"); symex_assign_symbol(lhs, full_lhs, rhs, full_rhs, guard, hidden); + log_status("symex_assign_symbol done!!!"); } else if (is_index2t(lhs)) { @@ -349,10 +350,7 @@ void goto_symext::symex_assign_rec( { log_status("symex_assign_fieldof"); symex_assign_fieldof(lhs, full_lhs, rhs, full_rhs, guard, hidden); - } - else if (is_heap_region2t(lhs)) - { - log_status("symex_assign_heap_region"); + log_status("symex_assign_fieldof done!!!"); } else { @@ -397,6 +395,8 @@ void goto_symext::symex_assign_symbol( cur_state->assignment(renamed_lhs, rhs); + log_status("cur state assignment done!!!"); + // Special case when the lhs is an array access, we need to get the // right symbol for the index expr2tc new_lhs = full_lhs; @@ -906,18 +906,13 @@ void goto_symext::symex_assign_fieldof( assert(is_scalar_type(rhs)); const fieldof2t& fieldof = to_fieldof2t(lhs); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); + const expr2tc &heap_region = fieldof.source_heap; const expr2tc &field = fieldof.operand; expr2tc update_heap = - heap_update2tc(heap_region.type, fieldof.source_heap, field, rhs); + heap_update2tc(heap_region->type, heap_region, field, rhs); - symex_assign_rec( - heap_region.flag, - fieldof.source_heap, - update_heap, - update_heap, - guard, hidden); + symex_assign_rec(heap_region, full_lhs, update_heap, full_rhs, guard, hidden); } void goto_symext::replace_nondet(expr2tc &expr) diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 042314a4..8801d3c2 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -166,82 +166,56 @@ bool symex_dereference_statet::is_live_variable(const expr2tc &symbol) return false; } -void symex_dereference_statet::update_heap_type(const expr2tc &flag) +void symex_dereference_statet::update_heap_type(const intheap_type2t &type) { - if (!is_symbol2t(flag)) + if (is_nil_expr(to_intheap_type(type).location)) { - log_error("Wrong flag!!!!"); + log_error("Wrong type!!!!"); abort(); } - log_status("begin update heap type"); - flag->dump(); - - // Each heap region has a unique L0 name - expr2tc l0_flag = flag; - goto_symex.cur_state->get_original_name(l0_flag); - const symbol2t l0_sym = to_symbol2t(l0_flag); - - l0_flag->dump(); - // update value set value_sett& value_set = goto_symex.cur_state->value_set; unsigned int n = value_set.object_numbering.size(); for(unsigned int i = 0; i < n; i++) - update_heap_type_rec(value_set.object_numbering[i], l0_sym); - - - log_status("finishing update value set"); + update_heap_type_rec(value_set.object_numbering[i], type); // update eq system std::shared_ptr eq = std::dynamic_pointer_cast(goto_symex.target); for(auto& ssa_step : eq->SSA_steps) { - update_heap_type_rec(ssa_step.guard, l0_sym); - update_heap_type_rec(ssa_step.rhs, l0_sym); - update_heap_type_rec(ssa_step.cond, l0_sym); + update_heap_type_rec(ssa_step.guard, type); + update_heap_type_rec(ssa_step.rhs, type); + update_heap_type_rec(ssa_step.cond, type); } - - log_status("finishing replace"); } void symex_dereference_statet::update_heap_type_rec( - expr2tc &expr, const symbol2t &flag) + expr2tc &expr, const intheap_type2t &type) { if (is_nil_expr(expr)) return; - log_status("update type of :"); - expr->dump(); - if (is_symbol2t(expr)) + if (is_intheap_type(expr)) { - // update heap variable - expr2tc l0_sym = expr; - goto_symex.cur_state->get_original_name(l0_sym); + intheap_type2t &_type = to_intheap_type(expr->type); - if (flag.get_symbol_name() == to_symbol2t(l0_sym).get_symbol_name()) - expr->type = flag.type; - } - else if (is_heap_region2t(expr)) - { - heap_region2t &heap_region = to_heap_region2t(expr); - - expr2tc l0_flag = heap_region.flag; - goto_symex.cur_state->get_original_name(l0_flag); + if (is_nil_expr(_type.location)) return; - l0_flag->dump(); - - if (flag.get_symbol_name() == - to_symbol2t(l0_flag).get_symbol_name()) + if (to_symbol2t(_type.location).get_symbol_name() == + to_symbol2t(type.location).get_symbol_name()) + expr->type = intheap_type2tc(type); + + if (is_heap_region2t(expr)) { - heap_region.type = flag.type; - update_heap_type_rec(heap_region.flag, flag); + heap_region2t &heap_region = to_heap_region2t(expr); + update_heap_type_rec(heap_region.flag, type); } } else { - expr->Foreach_operand([this, &flag](expr2tc& e){ + expr->Foreach_operand([this, &type](expr2tc& e){ if (!is_nil_expr(e)) - update_heap_type_rec(e, flag); + update_heap_type_rec(e, type); }); } } diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index df99dbda..f68233c3 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1226,8 +1226,7 @@ void goto_symext::add_memory_leak_checks() log_status(" ----------- [memleak encoding]----------- "); for (auto const &it : dynamic_memory){ log_status("allocated object {}: ", it.name); - expr2tc obj_flag = flagof2tc(it.obj); - expr2tc deallocated = equality2tc(obj_flag, gen_emp()); + expr2tc deallocated = equality2tc(it.obj, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); cur_state->rename(cond); diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 601c5774..13a44369 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -107,7 +107,6 @@ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(heap_region, \ - BOOST_PP_LIST_CONS(flagof, \ BOOST_PP_LIST_CONS(locationof, \ BOOST_PP_LIST_CONS(fieldof, \ BOOST_PP_LIST_CONS(heap_update, \ @@ -154,7 +153,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index a49356a6..f293ef80 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -78,7 +78,6 @@ static const char *expr_names[] = { "uplus", "locadd", "heap_region", - "flagof", "locationof", "fieldof", "heap_update", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 4ef14c45..fe39b5e9 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1704,7 +1704,6 @@ irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); irep_typedefs(heap_region, heap_region_data); -irep_typedefs(flagof, heap_ops); irep_typedefs(locationof, heap_ops); irep_typedefs(fieldof, heap_1op); irep_typedefs(heap_update, heap_2ops); @@ -3231,18 +3230,6 @@ class heap_region2t : public heap_region_expr_methods static std::string field_names[esbmct::num_type_fields]; }; -class flagof2t : public flagof_expr_methods -{ -public: - flagof2t(const expr2tc &source_region) - : flagof_expr_methods(get_intheap_type(), flagof_id, source_region) - { - } - flagof2t(const flagof2t &ref) = default; - - static std::string field_names[esbmct::num_type_fields]; -}; - class locationof2t : public locationof_expr_methods { public: diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index 1b80546c..9332b103 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -208,22 +208,26 @@ class intheap_data : public type2t public: intheap_data( type2t::type_ids id, - const std::vector &ft, + const expr2tc &loc, unsigned int tb, bool ir, bool ia) - : type2t(id), field_types(ft), total_bytes(tb), + : type2t(id), + location(loc), total_bytes(tb), is_region(ir), is_aligned(ia) { } intheap_data(const intheap_data &ref) = default; + expr2tc location; std::vector field_types; unsigned int total_bytes; bool is_region; bool is_aligned; // Type mangling: + typedef esbmct::field_traits + location_field; typedef esbmct::field_traits, intheap_data, &intheap_data::field_types> field_types_field; typedef esbmct::field_traits @@ -233,6 +237,7 @@ class intheap_data : public type2t typedef esbmct::field_traits is_aligned_field; typedef esbmct::type2t_traits< + location_field, field_types_field, total_bytes_field, is_region_field, @@ -394,11 +399,14 @@ class intheap_type2t : public intheap_type_methods { public: intheap_type2t( - const std::vector &field_types, + const expr2tc &location, unsigned int total_bytes, bool is_region, bool is_aligned) - : intheap_type_methods(intheap_id, field_types, total_bytes, is_region, is_aligned) + : intheap_type_methods( + intheap_id, + location, total_bytes, + is_region, is_aligned) { if (is_region && this->field_types.empty()) this->field_types.push_back(empty_type2tc()); diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index bbf67151..054df6e0 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -12,7 +12,7 @@ std::string empty_type2t::field_names[esbmct::num_type_fields] = std::string intloc_type2t::field_names[esbmct::num_type_fields] = {"", "", "", "", ""}; std::string intheap_type2t::field_names[esbmct::num_type_fields] = - {"field_types", "total_bytes", "is_region", "is_aligned", ""}; + {"location", "field_types", "total_bytes", "is_region", "is_aligned", ""}; std::string symbol_type2t::field_names[esbmct::num_type_fields] = {"symbol_name", "", "", "", ""}; std::string struct_type2t::field_names[esbmct::num_type_fields] = @@ -170,8 +170,6 @@ std::string locadd2t::field_names[esbmct::num_type_fields] = {"location", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = {"flag", "source_location", "", "", ""}; -std::string flagof2t::field_names[esbmct::num_type_fields] = - {"source_region", "", "", "", ""}; std::string locationof2t::field_names[esbmct::num_type_fields] = {"source_region", "", "", "", ""}; std::string fieldof2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_ops.cpp b/src/irep2/templates/irep2_templates_expr_ops.cpp index 338cf3ef..fd7a2575 100644 --- a/src/irep2/templates/irep2_templates_expr_ops.cpp +++ b/src/irep2/templates/irep2_templates_expr_ops.cpp @@ -48,7 +48,6 @@ expr_typedefs1(isnan, bool_1op); expr_typedefs1(overflow_neg, overflow_ops); expr_typedefs1(locationof, heap_ops); -expr_typedefs1(flagof, heap_ops); expr_typedefs3(fieldof, heap_1op); expr_typedefs4(heap_update, heap_2ops); expr_typedefs2(heap_append, heap_1op); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 3ae141e1..a32e2391 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -852,31 +852,28 @@ expr2tc dereferencet::build_reference_to( lexical_offset->dump(); guardt tmp_guard(guard); - if (is_heap_region2t(value)) - { - heap_region2t& heap_region = to_heap_region2t(value); - - if (!is_free(mode) && !is_internal(mode)) - { - int access_sz = type->get_width() / 8; - // Do alignment - intheap_type2t &_type = to_intheap_type(heap_region.type); - bool has_changed = _type.do_alignment(access_sz); - if (has_changed) - { - to_symbol2t(heap_region.flag).type = heap_region.type; - dereference_callback.update_heap_type(heap_region.flag); - } - } - pointer_guard = same_object2tc(deref_expr, locationof2tc(value)); - tmp_guard.add(pointer_guard); - } - else + if (!is_intheap_type(value) || + !to_intheap_type(value->type).is_region) { log_error("Not heap region"); abort(); } + intheap_type2t &_type = to_intheap_type(value->type); + + if (!is_free(mode) && !is_internal(mode)) + { + int access_sz = type->get_width() / 8; + // Do alignment + bool has_changed = _type.do_alignment(access_sz); + if (has_changed) + dereference_callback.update_heap_type(_type); + } + pointer_guard = same_object2tc(deref_expr, locationof2tc(value)); + tmp_guard.add(pointer_guard); + + + log_status("generated pointer guard:"); pointer_guard->dump(); @@ -929,8 +926,7 @@ expr2tc dereferencet::build_reference_to( } // other checks may be added later - if (is_heap_region2t(value)) - check_heap_region_access(value, final_offset, type, tmp_guard, mode); + check_heap_region_access(value, final_offset, type, tmp_guard, mode); build_deref_slhv(value, final_offset, type, tmp_guard, mode, alignment); @@ -1268,9 +1264,11 @@ void dereferencet::build_deref_slhv( abort(); } - heap_region2t& heap_region = to_heap_region2t(value); + // value is the flag symbol of a heap region + expr2tc &heap_region = value; + unsigned int field = to_constant_int2t(offset).value.to_uint64(); - intheap_type2t &_type = to_intheap_type(heap_region.type); + intheap_type2t &_type = to_intheap_type(heap_region->type); unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); if (!_type.is_aligned) @@ -1297,10 +1295,7 @@ void dereferencet::build_deref_slhv( // update field type if (_type.set_field_type(field, type)) - { - heap_region.flag->type = heap_region.type; - dereference_callback.update_heap_type(heap_region.flag); - } + dereference_callback.update_heap_type(_type); log_status(" ----------------- build deref slhv ----------------- "); } @@ -2313,6 +2308,22 @@ void dereferencet::valid_check( // always "valid", shut up return; } + else if(is_intheap_type(symbol)) + { + log_status("guard : "); + guard.dump(); + expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); + log_status("not valid print:"); + not_valid_heap_region->dump(); + guardt tmp_guard(guard); + tmp_guard.add(not_valid_heap_region); + std::string foo = is_free(mode) ? "invalid free pointer" + : "invalid dereference pointer"; + // deref failure will replace heap region with heap contains + // that indicates the reigon is avaliable. + dereference_failure("pointer dereference", foo, tmp_guard); + return; + } else if (is_symbol2t(symbol)) { // Hacks, but as dereferencet object isn't persistent, necessary. Fix by @@ -2366,22 +2377,6 @@ void dereferencet::valid_check( } } } - else if(is_heap_region2t(symbol)) - { - log_status("guard : "); - guard.dump(); - expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); - log_status("not valid print:"); - not_valid_heap_region->dump(); - guardt tmp_guard(guard); - tmp_guard.add(not_valid_heap_region); - std::string foo = is_free(mode) ? "invalid free pointer" - : "invalid dereference pointer"; - // deref failure will replace heap region with heap contains - // that indicates the reigon is avaliable. - dereference_failure("pointer dereference", foo, tmp_guard); - return; - } } void dereferencet::bounds_check( diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index 5e1f8857..a5766e54 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -154,13 +154,13 @@ class dereference_callbackt virtual bool is_live_variable(const expr2tc &sym) = 0; - virtual void update_heap_type(const expr2tc &flag) + virtual void update_heap_type(const intheap_type2t &type) { log_error("Do not support"); abort(); } - virtual void update_heap_type_rec(expr2tc &expr, const symbol2t &flag) + virtual void update_heap_type_rec(expr2tc &expr, const intheap_type2t &type) { log_error("Do not support"); abort(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 34477f95..bbf3e3ab 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -566,10 +566,7 @@ void value_sett::get_value_set_rec( } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || - is_heap_append2t(expr) || is_heap_delete2t(expr) || - // heap_region as a constant - // deref a heap region use fieldof(region, 0) - is_heap_region2t(expr)) + is_heap_append2t(expr) || is_heap_delete2t(expr)) { expr2tc new_object = expr; insert(dest, new_object, BigInt(0)); @@ -609,7 +606,8 @@ void value_sett::get_value_set_rec( if (is_fieldof2t(expr)) { const fieldof2t &fieldof = to_fieldof2t(expr); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); + const expr2tc &heap_region = fieldof.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); expr2tc field = fieldof.operand; if (!is_constant_int2t(field)) @@ -621,7 +619,7 @@ void value_sett::get_value_set_rec( unsigned int _field = to_constant_int2t(field).value.to_uint64(); get_value_set_rec( - heap_region.flag, + _type.location, dest, "::field::" + std::to_string(_field) + "::" + suffix, original_type @@ -629,7 +627,8 @@ void value_sett::get_value_set_rec( return; } - if (is_heap_update2t(expr) || is_points_to2t(expr)) + if (is_heap_update2t(expr) || is_points_to2t(expr) || + is_heap_region2t(expr)) { expr->dump(); log_status("fini get_value_set_rec heap_update"); @@ -870,8 +869,7 @@ void value_sett::get_reference_set_rec(const expr2tc &expr, object_mapt &dest) { if ( is_symbol2t(expr) || is_dynamic_object2t(expr) || - is_constant_string2t(expr) || is_constant_array2t(expr) - || is_heap_region2t(expr)) + is_constant_string2t(expr) || is_constant_array2t(expr)) { // Any symbol we refer to, store into the destination object map. // Given that this is a simple symbol, we can be sure that the offset to @@ -1247,6 +1245,17 @@ void value_sett::assign( if (is_intheap_type(lhs_type)) { + if (is_heap_region2t(rhs)) + { + // heap region is created for encoding + // the heap variable lhs contains all information + expr2tc new_obj = to_heap_region2t(rhs).flag; + object_mapt values_rhs; + // flag contains all neccessary information + insert(values_rhs, new_obj, BigInt(0)); + assign_rec(lhs, values_rhs, "", add_to_sets); + return; + } if (to_intheap_type(lhs_type).is_region && is_heap_update2t(rhs)) { const heap_update2t &heap_upd = to_heap_update2t(rhs); @@ -1422,11 +1431,13 @@ void value_sett::assign_rec( } unsigned int _field = to_constant_int2t(field).value.to_uint64(); + const expr2tc &heap_region = fieldof.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); - + // TODO : fix + // use location to encoding field assign_rec( - heap_region.flag, + _type.location, values_rhs, "::field::" + std::to_string(_field) + "::" + suffix, add_to_sets); diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index efc37b22..39a92714 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -346,7 +346,6 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: case expr2t::heap_region_id: - case expr2t::flagof_id: case expr2t::locationof_id: case expr2t::fieldof_id: case expr2t::points_to_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 8df266bc..1c0d97db 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -237,36 +237,12 @@ z3_slhv_convt::convert_slhv_opts( } return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); } - case expr2t::flagof_id: - { - const flagof2t &flagof = to_flagof2t(expr); - - if (is_symbol2t(flagof.source_heap)) - { - if (!is_intheap_type(flagof.source_heap->type)) - { - log_error("Wrong intheap type"); - abort(); - } - return args[0]; - } - - if (!is_heap_region2t(flagof.source_heap)) - { - log_error("We can't get a location of a non-region heap"); - abort(); - } - return convert_ast(to_heap_region2t(flagof.source_heap).flag); - } case expr2t::locationof_id: { const locationof2t &locof = to_locationof2t(expr); - if (!is_heap_region2t(locof.source_heap)) - { - log_error("We can't get a location of a non-region heap"); - abort(); - } - return convert_ast(to_heap_region2t(locof.source_heap).source_location); + const expr2tc &heap_region = locof.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); + return convert_ast(_type.location); } case expr2t::points_to_id: { @@ -354,24 +330,18 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) mk_smt_bool(true), mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); - if (!is_heap_region2t(fieldof.source_heap)) - { - log_error("We can't get a location of a non-region heap"); - abort(); - } if (!is_constant_int2t(fieldof.operand)) { log_error("Wrong field"); abort(); } - const heap_region2t &heap_region = to_heap_region2t(fieldof.source_heap); - const intheap_type2t &_type = to_intheap_type(heap_region.type); + const expr2tc &heap_region = fieldof.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); const expr2tc &field = fieldof.operand; - unsigned int _field = to_constant_int2t(field).value.to_uint64(); - smt_astt source_loc = convert_ast(heap_region.source_location); + smt_astt source_loc = convert_ast(_type.location); smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, convert_ast(field)); @@ -390,31 +360,27 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) } smt_astt v1 = mk_fresh(s1, name); - smt_astt assert_expr = mk_subh(mk_pt(loc, v1), convert_ast(heap_region.flag)); + smt_astt assert_expr = mk_subh(mk_pt(loc, v1), convert_ast(heap_region)); return std::make_pair(assert_expr, v1); } case expr2t::heap_update_id: { const heap_update2t &heap_upd = to_heap_update2t(expr); - if (!is_heap_region2t(heap_upd.source_heap)) - { - log_error("Do not support heap update for other heap terms"); - abort(); - } if (!is_constant_int2t(heap_upd.operand_1)) { log_error("Wrong field"); abort(); } - const heap_region2t &heap_region = to_heap_region2t(heap_upd.source_heap); + const expr2tc &heap_region = heap_upd.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); const expr2tc &upd_field = heap_upd.operand_1; const expr2tc &upd_value = heap_upd.operand_2; unsigned int _field = to_constant_int2t(upd_field).value.to_uint64(); - smt_astt h = convert_ast(heap_region.flag); - smt_astt source_loc = convert_ast(heap_region.source_location); + smt_astt h = convert_ast(heap_region); + smt_astt source_loc = convert_ast(_type.location); smt_astt field = convert_ast(upd_field); smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, field); smt_astt val = convert_ast(upd_value); @@ -452,11 +418,14 @@ z3_slhv_convt::smt_ast_pair z3_slhv_convt::project(const expr2tc &expr) { if (is_symbol2t(expr)) + { + if (is_intheap_type(expr)) + { + const intheap_type2t &_type = to_intheap_type(expr->type); + return this->project(_type.location); + } return convert_opt_without_assert(expr); - else if (is_heap_region2t(expr)) - return this->project(to_heap_region2t(expr).source_location); - else if (is_flagof2t(expr)) - return this->project(to_flagof2t(expr).source_heap); + } else if (is_locationof2t(expr)) return this->project(to_locationof2t(expr).source_heap); else if (is_fieldof2t(expr)) diff --git a/src/util/c_types.cpp b/src/util/c_types.cpp index 51183b95..adb768c0 100644 --- a/src/util/c_types.cpp +++ b/src/util/c_types.cpp @@ -396,8 +396,7 @@ type2tc get_empty_type() type2tc get_intheap_type(unsigned int sz) { - std::vector field_types; - return intheap_type2tc(field_types, sz, sz != 0, false); + return intheap_type2tc(expr2tc(), sz, sz != 0, false); } type2tc get_intloc_type() { diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 56a54f74..f486183d 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2644,14 +2644,6 @@ exprt migrate_expr_back(const expr2tc &ref) region.copy_to_operands(migrate_expr_back(ref2.source_location)); return region; } - case expr2t::flagof_id: - { - const flagof2t &ref2 = to_flagof2t(ref); - typet thetype = migrate_type_back(ref->type); - exprt flagof("flagof", thetype); - flagof.copy_to_operands(migrate_expr_back(ref2.source_heap)); - return flagof; - } case expr2t::locationof_id: { const locationof2t &ref2 = to_locationof2t(ref); diff --git a/src/util/type_byte_size.cpp b/src/util/type_byte_size.cpp index 0d5be611..14a7eaa4 100644 --- a/src/util/type_byte_size.cpp +++ b/src/util/type_byte_size.cpp @@ -453,9 +453,6 @@ const expr2tc &get_base_object(const expr2tc &expr) if (is_dereference2t(expr)) return get_base_object(to_dereference2t(expr).value); - - if (is_flagof2t(expr)) - return get_base_object(to_flagof2t(expr).source_heap); if (is_locationof2t(expr)) return get_base_object(to_locationof2t(expr).source_heap); From 890837ed3f35b749841b42a6e2f9fb14e4967025 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 31 Aug 2024 15:20:24 +0800 Subject: [PATCH 062/126] fix heap_update assignment and encoding --- src/pointer-analysis/value_set.cpp | 36 +++++++++++++++++++++++----- src/solvers/z3-slhv/z3_slhv_conv.cpp | 9 ++++--- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index bbf3e3ab..adbd51d6 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -607,7 +607,6 @@ void value_sett::get_value_set_rec( { const fieldof2t &fieldof = to_fieldof2t(expr); const expr2tc &heap_region = fieldof.source_heap; - const intheap_type2t &_type = to_intheap_type(heap_region->type); expr2tc field = fieldof.operand; if (!is_constant_int2t(field)) @@ -619,7 +618,7 @@ void value_sett::get_value_set_rec( unsigned int _field = to_constant_int2t(field).value.to_uint64(); get_value_set_rec( - _type.location, + heap_region, dest, "::field::" + std::to_string(_field) + "::" + suffix, original_type @@ -1259,11 +1258,36 @@ void value_sett::assign( if (to_intheap_type(lhs_type).is_region && is_heap_update2t(rhs)) { const heap_update2t &heap_upd = to_heap_update2t(rhs); + const expr2tc &upd_heap = heap_upd.source_heap; const expr2tc &upd_field = heap_upd.operand_1; const expr2tc &upd_value = heap_upd.operand_2; - expr2tc lhs_field = - fieldof2tc(rhs->type, heap_upd.source_heap, upd_field); - assign(lhs_field, upd_value, add_to_sets); + + if (!is_constant_int2t(upd_field)) + { + log_error("Do not support dynamic field"); + abort(); + } + unsigned int field = to_constant_int2t(upd_field).value.to_uint64(); + + const intheap_type2t &_type = to_intheap_type(upd_heap->type); + for (unsigned int i = 0; i < _type.field_types.size(); i++) + { + expr2tc lhs_field; + expr2tc val; + if (i == field) + { + lhs_field = fieldof2tc(rhs->type, upd_heap, upd_field); + val = upd_value; + } + else + { + lhs_field = fieldof2tc(_type.field_types[i], upd_heap, gen_ulong(i)); + val = lhs_field; + add_to_sets = false; + } + assign(lhs_field, upd_value, add_to_sets); + } + return; } } @@ -1437,7 +1461,7 @@ void value_sett::assign_rec( // TODO : fix // use location to encoding field assign_rec( - _type.location, + heap_region, values_rhs, "::field::" + std::to_string(_field) + "::" + suffix, add_to_sets); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 1c0d97db..b5bcef7e 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -389,11 +389,14 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); // current heap state - smt_astt h_state = mk_uplus(h1, mk_pt(loc, v1)); - smt_astt assert_expr = mk_eq(h, h_state); + smt_astt old_state = mk_uplus(h1, mk_pt(loc, v1)); + smt_astt assert_expr = mk_eq(h, old_state); // new heap state - return std::make_pair(assert_expr, h_state); + smt_astt new_state = mk_uplus(h1, mk_pt(loc, val)); + + // new heap state + return std::make_pair(assert_expr, new_state); } case expr2t::heap_delete_id: { From 9433615092878f7d052c678c38666af836bc9668 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 1 Sep 2024 22:06:40 +0800 Subject: [PATCH 063/126] convert struct type to heap region type --- src/goto-symex/builtin_functions.cpp | 66 ++------ src/goto-symex/goto_symex.h | 41 +++++ src/goto-symex/goto_symex_state.cpp | 7 +- src/goto-symex/slice.cpp | 4 +- src/goto-symex/symex_assign.cpp | 158 +++++++++++++++++- src/goto-symex/symex_main.cpp | 9 +- src/irep2/irep2.h | 4 +- src/irep2/irep2_expr.cpp | 4 +- src/irep2/irep2_expr.h | 20 +-- src/irep2/irep2_utils.h | 4 +- src/irep2/templates/irep2_templates.cpp | 4 +- .../templates/irep2_templates_expr_ops.cpp | 4 +- src/pointer-analysis/dereference.cpp | 16 +- src/pointer-analysis/value_set.cpp | 31 ++-- src/solvers/smt/smt_conv.cpp | 6 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 26 +-- src/util/base_type.cpp | 3 + src/util/c_types.cpp | 2 +- src/util/migrate.cpp | 22 +-- src/util/type_byte_size.cpp | 8 +- 20 files changed, 295 insertions(+), 144 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 9422f210..b5f34069 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -244,86 +244,42 @@ expr2tc goto_symext::symex_mem( } else { log_status("create heap symbol for allocation"); - // value + // create a intheap symbol for heap region symbolt symbol; symbol.name = "dynamic_heap_"+ i2string(dynamic_counter); - - symbol.id = std::string("symex_dynamic::") + (!is_malloc ? "alloca::" : "") + - id2string(symbol.name); + symbol.id = std::string("symex_dynamic::") + id2string(symbol.name); symbol.lvalue = true; - symbol.type = typet(typet::t_intheap); - - expr2tc _total_bytes = code.operand; - do_simplify(_total_bytes); - if (!is_constant_int2t(_total_bytes)) - { - log_status("Do not support dynamic size"); - abort(); - } - unsigned int bytes = to_constant_int2t(_total_bytes).value.to_uint64(); - - type2tc heap_type = get_intheap_type(bytes); - intheap_type2t &_heap_type = to_intheap_type(heap_type); - _heap_type.is_region = true; - if (is_struct_type(type)) - { - struct_type2t &_type = to_struct_type(type); - _heap_type.is_aligned = true; - _heap_type.field_types.clear(); - for(auto inner_type : _type.get_structure_members()) - _heap_type.field_types.push_back( - is_pointer_type(inner_type) ? get_intloc_type() : get_int64_type() - ); - } - symbol.type.dynamic(true); symbol.mode = "C"; new_context.add(symbol); - // create a new location for new heap region - symbolt heap_region_loc; - heap_region_loc.name = "heap_region_loc_"+ i2string(dynamic_counter); - - heap_region_loc.id = std::string("symex_dynamic::") + id2string(heap_region_loc.name); - heap_region_loc.lvalue = true; - - heap_region_loc.type = typet(typet::t_intheap); - - heap_region_loc.mode = "C"; - new_context.add(heap_region_loc); - - expr2tc rhs_base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); - // rhs_base_loc do not change during its lifetime - // use l2 symbol, do not need to be renamed - cur_state->rename(rhs_base_loc); - - // store base location in intheap type - _heap_type.location = rhs_base_loc; - - expr2tc rhs_heap = symbol2tc(heap_type, symbol.id); + expr2tc rhs_heap = symbol2tc(get_intheap_type(), symbol.id); + expr2tc rhs_region = create_heap_region(code, rhs_heap); + expr2tc rhs_base_loc = to_heap_region2t(rhs_region).source_location; guardt rhs_guard = cur_state->guard; - - expr2tc rhs_region = heap_region2tc(heap_type, rhs_heap, rhs_base_loc); log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); // link pointer variable and heap variable + log_status("track new pointer - {}", to_symbol2t(rhs_base_loc).get_symbol_name()); track_new_pointer( rhs_base_loc, get_intheap_type(), - gen_ulong(to_intheap_type(heap_type).total_bytes)); + gen_ulong(to_intheap_type(rhs_region->type).total_bytes)); + log_status("use dynamic memory to track malloc heap - {}", + to_symbol2t(rhs_heap).get_symbol_name()); dynamic_memory.emplace_back( rhs_heap, rhs_guard, !is_malloc, - symbol.name.as_string() + to_symbol2t(rhs_heap).get_symbol_name() ); log_status("create valueset base loc symbol and assign"); - symex_assign(code_assign2tc(lhs, locationof2tc(rhs_heap))); + symex_assign(code_assign2tc(lhs, location_of2tc(rhs_heap))); return expr2tc(); } diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 71b248ab..cda5f450 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -811,6 +811,47 @@ class goto_symext */ void replace_pointer_airth(expr2tc &expr); + /** + * @brief Replace addressof by location_of + * @param expr + */ + void replace_address_of(expr2tc &expr); + + /** + * @brief Replace all struct/array variable by heap variable + * @param expr + */ + void replace_tuple(expr2tc &expr); + + /** + * @brief Create a heap type object + * + * @param type + * @param loc + * @return type2tc + */ + type2tc create_heap_region_type( + const type2tc &type, + unsigned int bytes, + const expr2tc &loc); + + /** + * @brief Create a heap region object + * + * @param sideeffect + * @param flag + * @return expr2tc + */ + expr2tc create_heap_region(const sideeffect2t &effect, expr2tc &flag); + + /** + * @brief In SLHV, struct/array are heap variable + * + * @param lhs + * @param effect + */ + void symex_nondet(const expr2tc &lhs, const expr2tc &effect); + /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 92f179f9..cd990cc3 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -77,8 +77,8 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const constant_propagation(locadd.offset); } - if (is_locationof2t(expr)) - return constant_propagation(to_locationof2t(expr).source_heap); + if (is_location_of2t(expr)) + return constant_propagation(to_location_of2t(expr).source_heap); if (is_array_type(expr)) { @@ -104,6 +104,8 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const if (is_symbol2t(expr)) { + if (is_intheap_type(expr)) return true; + symbol2t s = to_symbol2t(expr); // Null is also essentially a constant. @@ -208,6 +210,7 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) expr2tc l1_lhs = lhs; expr2tc const_value = constant_propagation(rhs) ? rhs : expr2tc(); + log_status("is constant - {}", !is_nil_expr(const_value)); level2.make_assignment(lhs, const_value, rhs); if (use_value_set) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index b1d97c6a..0a93a365 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -12,10 +12,10 @@ bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - // locationof only has heap_region as oprend + // location_of only has heap_region as oprend // the location of heap_region is completely fresh // and is not being used in symbolic execution - if (is_locationof2t(expr) || is_heap_region2t(expr)) return false; + if (is_location_of2t(expr) || is_heap_region2t(expr)) return false; // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index c734ce2d..512db7a9 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -192,16 +192,29 @@ void goto_symext::symex_assign( replace_pointer_airth(lhs); replace_pointer_airth(rhs); + + replace_address_of(lhs); + replace_address_of(rhs); + + replace_tuple(lhs); + replace_tuple(rhs); + + if (is_sideeffect2t(rhs) && + to_sideeffect2t(rhs).kind == sideeffect2t::nondet) + { + symex_nondet(lhs, rhs); + return; + } } + replace_nondet(lhs); + replace_nondet(rhs); + log_status("symex assign lhs : ------------- "); lhs->dump(); log_status("symex assign rhs : ------------- "); rhs->dump(); - replace_nondet(lhs); - replace_nondet(rhs); - intrinsic_races_check_dereference(lhs); log_status("dereference lhs write"); dereference(lhs, dereferencet::WRITE); @@ -346,7 +359,7 @@ void goto_symext::symex_assign_rec( log_status("symex_assign_bitfield"); symex_assign_bitfield(lhs, full_lhs, rhs, full_rhs, guard, hidden); } - else if (is_fieldof2t(lhs)) + else if (is_field_of2t(lhs)) { log_status("symex_assign_fieldof"); symex_assign_fieldof(lhs, full_lhs, rhs, full_rhs, guard, hidden); @@ -905,9 +918,9 @@ void goto_symext::symex_assign_fieldof( { assert(is_scalar_type(rhs)); - const fieldof2t& fieldof = to_fieldof2t(lhs); - const expr2tc &heap_region = fieldof.source_heap; - const expr2tc &field = fieldof.operand; + const field_of2t& field_of = to_field_of2t(lhs); + const expr2tc &heap_region = field_of.source_heap; + const expr2tc &field = field_of.operand; expr2tc update_heap = heap_update2tc(heap_region->type, heap_region, field, rhs); @@ -920,6 +933,7 @@ void goto_symext::replace_nondet(expr2tc &expr) if ( is_sideeffect2t(expr) && to_sideeffect2t(expr).kind == sideeffect2t::nondet) { + unsigned int &nondet_count = get_dynamic_counter(); expr = symbol2tc(expr->type, "nondet$symex::nondet" + i2string(nondet_count++)); @@ -980,13 +994,139 @@ void goto_symext::replace_pointer_airth(expr2tc &expr) if (is_member2t(expr)) { - // replaced by fieldof + // replaced by field_of const member2t &member = to_member2t(expr); const struct_type2t &struct_type = to_struct_type(member.source_value->type); expr2tc field = gen_ulong(struct_type.get_component_number(member.member)); - expr = fieldof2tc(member.type, member.source_value, field); + expr = field_of2tc(member.type, member.source_value, field); } +} + +void goto_symext::replace_address_of(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + + expr->Foreach_operand([this](expr2tc &e) { replace_pointer_airth(e); }); + + if (is_address_of2t(expr)) + { + expr = location_of2tc(to_address_of2t(expr).ptr_obj); + } +} + +void goto_symext::replace_tuple(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + + expr->Foreach_operand([this](expr2tc &e) { replace_tuple(e); }); + + if (is_symbol2t(expr) && is_struct_type(expr->type)) + { + log_status("found struct?"); + unsigned int bytes = type_byte_size(expr->type, &ns).to_uint64(); + expr->type = create_heap_region_type(expr->type, bytes, expr); + } +} + +type2tc goto_symext::create_heap_region_type( + const type2tc &type, + unsigned int bytes, + const expr2tc &loc) +{ + expr2tc l1_loc = loc; + cur_state->top().level1.rename(l1_loc); + + type2tc heap_type = get_intheap_type(); + intheap_type2t &_heap_type = to_intheap_type(heap_type); + _heap_type.location = l1_loc; + _heap_type.total_bytes = bytes; + _heap_type.is_region = true; + + if (is_struct_type(type)) + { + _heap_type.is_aligned = true; + _heap_type.total_bytes = bytes; + const struct_type2t &_type = to_struct_type(type); + _heap_type.field_types.clear(); + for(auto inner_type : _type.get_structure_members()) + _heap_type.field_types.push_back( + is_pointer_type(inner_type) ? get_intloc_type() : get_int64_type() + ); + } + + return heap_type; +} + +expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &flag) +{ + log_status(" ======= create a heap region ========== "); + + type2tc type; + if (effect.kind == sideeffect2t::nondet) + { + // alloc a heap region in stack + type = effect.type; + } + else + { + // malloc a heap region + type = effect.alloctype; + if (is_nil_type(type)) type = char_type2(); + } + + // create a new location + symbolt heap_region_loc; + heap_region_loc.name = + id2string(to_symbol2t(flag).get_symbol_name()) + std::string("_loc"); + heap_region_loc.id = + std::string("symex_location::") + id2string(heap_region_loc.name); + heap_region_loc.lvalue = true; + heap_region_loc.type = typet(typet::t_intloc); + heap_region_loc.mode = "C"; + new_context.add(heap_region_loc); + + expr2tc base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); + unsigned int bytes; + + if (is_struct_type(type)) + { + bytes = type_byte_size(type, &ns).to_uint64(); + } + else + { + expr2tc op = effect.operand; + do_simplify(op); + if (!is_constant_int2t(op)) + { + log_error("Do not support dynamic size"); + abort(); + } + bytes = to_constant_int2t(op).value.to_uint64(); + } + + type2tc heap_type = create_heap_region_type(type, bytes, base_loc); + flag->type = heap_type; + + log_status(" ======= create a heap region ========== "); + + return heap_region2tc(heap_type, flag, base_loc); +} + +void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) +{ + log_status(" ======== symex nondet ===== "); + lhs->dump(); + effect->dump(); + + expr2tc l1_lhs = lhs; + + expr2tc heap_region = + create_heap_region(to_sideeffect2t(effect), l1_lhs); + + symex_assign(code_assign2tc(lhs, heap_region)); + + log_status(" ======== symex nondet ===== "); } \ No newline at end of file diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index f68233c3..57f25efa 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -138,6 +138,8 @@ goto_symext::symex_resultt goto_symext::get_symex_result() return goto_symext::symex_resultt(target, total_claims, remaining_claims); } +#include + void goto_symext::symex_step(reachability_treet &art) { log_status(" ======= goto_symext symex_step"); @@ -168,14 +170,19 @@ void goto_symext::symex_step(reachability_treet &art) case END_FUNCTION: log_status(" ======= goto symex: END_FUNCTION"); + + this->cur_state->level2.print(std::cout); + symex_end_of_function(); + this->cur_state->level2.print(std::cout); + // Potentially skip to run another function ptr target; if not, // continue if (!run_next_function_ptr_target(false)) cur_state->source.pc++; - break; + break; case GOTO: { log_status(" ======= goto symex: GOTO"); diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 13a44369..941cb1c5 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -107,8 +107,8 @@ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(heap_region, \ - BOOST_PP_LIST_CONS(locationof, \ - BOOST_PP_LIST_CONS(fieldof, \ + BOOST_PP_LIST_CONS(location_of, \ + BOOST_PP_LIST_CONS(field_of, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_delete, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index f293ef80..562fd061 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -78,8 +78,8 @@ static const char *expr_names[] = { "uplus", "locadd", "heap_region", - "locationof", - "fieldof", + "location_of", + "field_of", "heap_update", "heap_append", "heap_delete", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index fe39b5e9..77422fd8 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1704,8 +1704,8 @@ irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); irep_typedefs(heap_region, heap_region_data); -irep_typedefs(locationof, heap_ops); -irep_typedefs(fieldof, heap_1op); +irep_typedefs(location_of, heap_ops); +irep_typedefs(field_of, heap_1op); irep_typedefs(heap_update, heap_2ops); irep_typedefs(heap_append, heap_1op); irep_typedefs(heap_delete, heap_1op); @@ -3230,29 +3230,29 @@ class heap_region2t : public heap_region_expr_methods static std::string field_names[esbmct::num_type_fields]; }; -class locationof2t : public locationof_expr_methods +class location_of2t : public location_of_expr_methods { public: - locationof2t(const expr2tc &source_region) - : locationof_expr_methods(get_intloc_type(), locationof_id, source_region) + location_of2t(const expr2tc &source_region) + : location_of_expr_methods(get_intloc_type(), location_of_id, source_region) { } - locationof2t(const locationof2t &ref) = default; + location_of2t(const location_of2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; }; -class fieldof2t : public fieldof_expr_methods +class field_of2t : public field_of_expr_methods { public: - fieldof2t( + field_of2t( const type2tc &type, const expr2tc &heap_region, const expr2tc &field) - : fieldof_expr_methods(type, fieldof_id, heap_region, field) + : field_of_expr_methods(type, field_of_id, heap_region, field) { } - fieldof2t(const fieldof2t &ref) = default; + field_of2t(const field_of2t &ref) = default; static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/irep2/irep2_utils.h b/src/irep2/irep2_utils.h index 0bc2624f..91315f9d 100644 --- a/src/irep2/irep2_utils.h +++ b/src/irep2/irep2_utils.h @@ -200,8 +200,8 @@ inline bool is_slhv_expr(const expr2tc &expr) is_heap_delete2t(expr) || is_heap_region2t(expr) || is_heap_update2t(expr) || - is_locationof2t(expr) || - is_fieldof2t(expr); + is_location_of2t(expr) || + is_field_of2t(expr); } /** Test if expr is true. First checks whether the expr is a constant bool, and diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 054df6e0..e4cf28b9 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -170,9 +170,9 @@ std::string locadd2t::field_names[esbmct::num_type_fields] = {"location", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = {"flag", "source_location", "", "", ""}; -std::string locationof2t::field_names[esbmct::num_type_fields] = +std::string location_of2t::field_names[esbmct::num_type_fields] = {"source_region", "", "", "", ""}; -std::string fieldof2t::field_names[esbmct::num_type_fields] = +std::string field_of2t::field_names[esbmct::num_type_fields] = {"heap_region", "field", "", "", ""}; std::string heap_update2t::field_names[esbmct::num_type_fields] = {"source_region", "update_field", "update_val", "", ""}; diff --git a/src/irep2/templates/irep2_templates_expr_ops.cpp b/src/irep2/templates/irep2_templates_expr_ops.cpp index fd7a2575..fd8dcff0 100644 --- a/src/irep2/templates/irep2_templates_expr_ops.cpp +++ b/src/irep2/templates/irep2_templates_expr_ops.cpp @@ -47,8 +47,8 @@ expr_typedefs2(concat, bit_2ops); expr_typedefs1(isnan, bool_1op); expr_typedefs1(overflow_neg, overflow_ops); -expr_typedefs1(locationof, heap_ops); -expr_typedefs3(fieldof, heap_1op); +expr_typedefs1(location_of, heap_ops); +expr_typedefs3(field_of, heap_1op); expr_typedefs4(heap_update, heap_2ops); expr_typedefs2(heap_append, heap_1op); expr_typedefs2(heap_delete, heap_1op); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index a32e2391..18112c47 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -173,7 +173,7 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) expr = result; break; } - case expr2t::fieldof_id: + case expr2t::field_of_id: case expr2t::index_id: case expr2t::member_id: { @@ -438,22 +438,22 @@ expr2tc dereferencet::dereference_expr_nonscalar( u.datatype_members.front(), guard, mode, base); } - if (is_fieldof2t(expr)) + if (is_field_of2t(expr)) { - fieldof2t &fieldof = to_fieldof2t(expr); + field_of2t &field_of = to_field_of2t(expr); - if (!is_dereference2t(fieldof.source_heap)) + if (!is_dereference2t(field_of.source_heap)) { log_error("Do not support struct in struct yet"); abort(); } - dereference2t &deref = to_dereference2t(fieldof.source_heap); + dereference2t &deref = to_dereference2t(field_of.source_heap); // Get the heap region dereference_expr(deref.value, guard, dereferencet::READ); - expr2tc offset_to_scalar = fieldof.operand; + expr2tc offset_to_scalar = field_of.operand; simplify(offset_to_scalar); return dereference(deref.value, base->type, guard, mode, offset_to_scalar); @@ -869,7 +869,7 @@ expr2tc dereferencet::build_reference_to( if (has_changed) dereference_callback.update_heap_type(_type); } - pointer_guard = same_object2tc(deref_expr, locationof2tc(value)); + pointer_guard = same_object2tc(deref_expr, location_of2tc(value)); tmp_guard.add(pointer_guard); @@ -1291,7 +1291,7 @@ void dereferencet::build_deref_slhv( return; } else - value = fieldof2tc(type, value, gen_ulong(field)); + value = field_of2tc(type, value, gen_ulong(field)); // update field type if (_type.set_field_type(field, type)) diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index adbd51d6..1b2694b2 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -558,11 +558,13 @@ void value_sett::get_value_set_rec( if (v_it != values.end()) { make_union(dest, v_it->second.object_map); - log_status("points_to somthing"); + log_status("points to somthing"); for (auto obj : dest) object_numbering[obj.first]->dump(); return; } + else + log_status("nothing"); } // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || @@ -594,20 +596,20 @@ void value_sett::get_value_set_rec( return; } - if (is_locationof2t(expr)) + if (is_location_of2t(expr)) { get_value_set_rec( - to_locationof2t(expr).source_heap, + to_location_of2t(expr).source_heap, dest, suffix, original_type ); return; } - if (is_fieldof2t(expr)) + if (is_field_of2t(expr)) { - const fieldof2t &fieldof = to_fieldof2t(expr); - const expr2tc &heap_region = fieldof.source_heap; - expr2tc field = fieldof.operand; + const field_of2t &field_of = to_field_of2t(expr); + const expr2tc &heap_region = field_of.source_heap; + expr2tc field = field_of.operand; if (!is_constant_int2t(field)) { @@ -1276,16 +1278,15 @@ void value_sett::assign( expr2tc val; if (i == field) { - lhs_field = fieldof2tc(rhs->type, upd_heap, upd_field); + lhs_field = field_of2tc(rhs->type, upd_heap, upd_field); val = upd_value; } else { - lhs_field = fieldof2tc(_type.field_types[i], upd_heap, gen_ulong(i)); + lhs_field = field_of2tc(_type.field_types[i], upd_heap, gen_ulong(i)); val = lhs_field; - add_to_sets = false; } - assign(lhs_field, upd_value, add_to_sets); + assign(lhs_field, val, false); } return; @@ -1443,11 +1444,11 @@ void value_sett::assign_rec( "." + component_name + suffix, add_to_sets); } - else if (is_fieldof2t(lhs)) + else if (is_field_of2t(lhs)) { - const fieldof2t &fieldof = to_fieldof2t(lhs); + const field_of2t &field_of = to_field_of2t(lhs); - expr2tc field = fieldof.operand; + expr2tc field = field_of.operand; if (!is_constant_int2t(field)) { log_error("Do not support dynamic offset yet"); @@ -1455,7 +1456,7 @@ void value_sett::assign_rec( } unsigned int _field = to_constant_int2t(field).value.to_uint64(); - const expr2tc &heap_region = fieldof.source_heap; + const expr2tc &heap_region = field_of.source_heap; const intheap_type2t &_type = to_intheap_type(heap_region->type); // TODO : fix diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 39a92714..17687f1e 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -316,7 +316,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::pointer_object_id: case expr2t::pointer_capability_id: - case expr2t::fieldof_id: + case expr2t::field_of_id: case expr2t::heap_update_id: case expr2t::heap_delete_id: break; // Don't convert their operands @@ -346,8 +346,8 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: case expr2t::heap_region_id: - case expr2t::locationof_id: - case expr2t::fieldof_id: + case expr2t::location_of_id: + case expr2t::field_of_id: case expr2t::points_to_id: case expr2t::uplus_id: case expr2t::locadd_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index b5bcef7e..80b7a115 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -237,9 +237,9 @@ z3_slhv_convt::convert_slhv_opts( } return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); } - case expr2t::locationof_id: + case expr2t::location_of_id: { - const locationof2t &locof = to_locationof2t(expr); + const location_of2t &locof = to_location_of2t(expr); const expr2tc &heap_region = locof.source_heap; const intheap_type2t &_type = to_intheap_type(heap_region->type); return convert_ast(_type.location); @@ -289,7 +289,7 @@ z3_slhv_convt::convert_slhv_opts( } return mk_subh(args[1], args[0]); } - case expr2t::fieldof_id: + case expr2t::field_of_id: case expr2t::heap_update_id: case expr2t::heap_delete_id: { @@ -321,24 +321,24 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) { switch (expr->expr_id) { - case expr2t::fieldof_id: + case expr2t::field_of_id: { - const fieldof2t &fieldof = to_fieldof2t(expr); + const field_of2t &field_of = to_field_of2t(expr); - if (is_constant_intheap2t(fieldof.source_heap)) + if (is_constant_intheap2t(field_of.source_heap)) return std::make_pair( mk_smt_bool(true), - mk_fresh(convert_sort(fieldof.type), mk_fresh_name("invalid_loc_"))); + mk_fresh(convert_sort(field_of.type), mk_fresh_name("invalid_loc_"))); - if (!is_constant_int2t(fieldof.operand)) + if (!is_constant_int2t(field_of.operand)) { log_error("Wrong field"); abort(); } - const expr2tc &heap_region = fieldof.source_heap; + const expr2tc &heap_region = field_of.source_heap; const intheap_type2t &_type = to_intheap_type(heap_region->type); - const expr2tc &field = fieldof.operand; + const expr2tc &field = field_of.operand; unsigned int _field = to_constant_int2t(field).value.to_uint64(); smt_astt source_loc = convert_ast(_type.location); @@ -429,9 +429,9 @@ z3_slhv_convt::project(const expr2tc &expr) } return convert_opt_without_assert(expr); } - else if (is_locationof2t(expr)) - return this->project(to_locationof2t(expr).source_heap); - else if (is_fieldof2t(expr)) + else if (is_location_of2t(expr)) + return this->project(to_location_of2t(expr).source_heap); + else if (is_field_of2t(expr)) return convert_opt_without_assert(expr); else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); diff --git a/src/util/base_type.cpp b/src/util/base_type.cpp index 55bcf56b..cb1e0371 100644 --- a/src/util/base_type.cpp +++ b/src/util/base_type.cpp @@ -93,6 +93,9 @@ bool base_type_eqt::base_type_eq_rec(const type2tc &type1, const type2tc &type2) { if (type1 == type2) return true; + + if (is_struct_type(type1) && is_intheap_type(type2)) + return true; // loop avoidance if (is_symbol_type(type1) && is_symbol_type(type2)) diff --git a/src/util/c_types.cpp b/src/util/c_types.cpp index adb768c0..f10dd765 100644 --- a/src/util/c_types.cpp +++ b/src/util/c_types.cpp @@ -396,7 +396,7 @@ type2tc get_empty_type() type2tc get_intheap_type(unsigned int sz) { - return intheap_type2tc(expr2tc(), sz, sz != 0, false); + return intheap_type2tc(expr2tc(), sz, false, false); } type2tc get_intloc_type() { diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index f486183d..c429d4a7 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2644,22 +2644,22 @@ exprt migrate_expr_back(const expr2tc &ref) region.copy_to_operands(migrate_expr_back(ref2.source_location)); return region; } - case expr2t::locationof_id: + case expr2t::location_of_id: { - const locationof2t &ref2 = to_locationof2t(ref); + const location_of2t &ref2 = to_location_of2t(ref); typet thetype = migrate_type_back(ref->type); - exprt locationof("locationof", thetype); - locationof.copy_to_operands(migrate_expr_back(ref2.source_heap)); - return locationof; + exprt location_of("location_of", thetype); + location_of.copy_to_operands(migrate_expr_back(ref2.source_heap)); + return location_of; } - case expr2t::fieldof_id: + case expr2t::field_of_id: { - const fieldof2t &ref2 = to_fieldof2t(ref); + const field_of2t &ref2 = to_field_of2t(ref); typet thetype = migrate_type_back(ref->type); - exprt fieldof("fieldof", thetype); - fieldof.copy_to_operands(migrate_expr_back(ref2.source_heap)); - fieldof.copy_to_operands(migrate_expr_back(ref2.operand)); - return fieldof; + exprt field_of("field_of", thetype); + field_of.copy_to_operands(migrate_expr_back(ref2.source_heap)); + field_of.copy_to_operands(migrate_expr_back(ref2.operand)); + return field_of; } case expr2t::heap_update_id: { diff --git a/src/util/type_byte_size.cpp b/src/util/type_byte_size.cpp index 14a7eaa4..2dd370a2 100644 --- a/src/util/type_byte_size.cpp +++ b/src/util/type_byte_size.cpp @@ -454,11 +454,11 @@ const expr2tc &get_base_object(const expr2tc &expr) if (is_dereference2t(expr)) return get_base_object(to_dereference2t(expr).value); - if (is_locationof2t(expr)) - return get_base_object(to_locationof2t(expr).source_heap); + if (is_location_of2t(expr)) + return get_base_object(to_location_of2t(expr).source_heap); - if (is_fieldof2t(expr)) - return get_base_object(to_fieldof2t(expr).source_heap); + if (is_field_of2t(expr)) + return get_base_object(to_field_of2t(expr).source_heap); return expr; } From 62bcea3eb680a771e6a6912b96348a19819c7c18 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 2 Sep 2024 14:50:37 +0800 Subject: [PATCH 064/126] set base loc for each heap variable --- src/goto-symex/goto_symex.h | 8 +++ src/goto-symex/goto_symex_state.cpp | 3 -- src/goto-symex/slice.cpp | 7 +-- src/goto-symex/symex_assign.cpp | 63 ++++++++++++++++-------- src/goto-symex/symex_other.cpp | 3 ++ src/pointer-analysis/value_set.cpp | 75 +++++++++++++++++++++-------- 6 files changed, 109 insertions(+), 50 deletions(-) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index cda5f450..217a66cf 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -823,6 +823,14 @@ class goto_symext */ void replace_tuple(expr2tc &expr); + /** + * @brief Create a heap region intloc + * + * @param expr + * @return expr2tc + */ + expr2tc create_heap_region_loc(const expr2tc &expr); + /** * @brief Create a heap type object * diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index cd990cc3..13dfc1be 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -104,8 +104,6 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const if (is_symbol2t(expr)) { - if (is_intheap_type(expr)) return true; - symbol2t s = to_symbol2t(expr); // Null is also essentially a constant. @@ -210,7 +208,6 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) expr2tc l1_lhs = lhs; expr2tc const_value = constant_propagation(rhs) ? rhs : expr2tc(); - log_status("is constant - {}", !is_nil_expr(const_value)); level2.make_assignment(lhs, const_value, rhs); if (use_value_set) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 0a93a365..88aae453 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -11,11 +11,8 @@ template bool symex_slicet::get_symbols(const expr2tc &expr) { bool res = false; - - // location_of only has heap_region as oprend - // the location of heap_region is completely fresh - // and is not being used in symbolic execution - if (is_location_of2t(expr) || is_heap_region2t(expr)) return false; + + if (is_heap_region2t(expr)) return false; // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 512db7a9..2c081f61 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -1027,8 +1027,37 @@ void goto_symext::replace_tuple(expr2tc &expr) { log_status("found struct?"); unsigned int bytes = type_byte_size(expr->type, &ns).to_uint64(); - expr->type = create_heap_region_type(expr->type, bytes, expr); + + // use l1 name and suffix "loc" to create base loc + expr2tc base_loc = create_heap_region_loc(expr); + + expr->type = create_heap_region_type(expr->type, bytes, base_loc); + } +} + +expr2tc goto_symext::create_heap_region_loc(const expr2tc &expr) +{ + if (!is_symbol2t(expr)) + { + log_error("Wrong symbol"); + abort(); } + expr2tc l1_sym = expr; + cur_state->level2.get_original_name(l1_sym); + + symbolt loc_sym; + loc_sym.name = + id2string(to_symbol2t(l1_sym).get_symbol_name()) + std::string("_loc"); + loc_sym.id = std::string("symex_location::") + id2string(loc_sym.name); + loc_sym.lvalue = true; + loc_sym.type = typet(typet::t_intloc); + loc_sym.mode = "C"; + new_context.add(loc_sym); + + expr2tc base_loc = symbol2tc(get_intloc_type(), loc_sym.id); + cur_state->rename(base_loc); + + return base_loc; } type2tc goto_symext::create_heap_region_type( @@ -1036,12 +1065,9 @@ type2tc goto_symext::create_heap_region_type( unsigned int bytes, const expr2tc &loc) { - expr2tc l1_loc = loc; - cur_state->top().level1.rename(l1_loc); - type2tc heap_type = get_intheap_type(); intheap_type2t &_heap_type = to_intheap_type(heap_type); - _heap_type.location = l1_loc; + _heap_type.location = loc; _heap_type.total_bytes = bytes; _heap_type.is_region = true; @@ -1077,20 +1103,9 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla if (is_nil_type(type)) type = char_type2(); } - // create a new location - symbolt heap_region_loc; - heap_region_loc.name = - id2string(to_symbol2t(flag).get_symbol_name()) + std::string("_loc"); - heap_region_loc.id = - std::string("symex_location::") + id2string(heap_region_loc.name); - heap_region_loc.lvalue = true; - heap_region_loc.type = typet(typet::t_intloc); - heap_region_loc.mode = "C"; - new_context.add(heap_region_loc); - - expr2tc base_loc = symbol2tc(get_intloc_type(), heap_region_loc.id); - unsigned int bytes; + expr2tc base_loc = create_heap_region_loc(flag); + unsigned int bytes; if (is_struct_type(type)) { bytes = type_byte_size(type, &ns).to_uint64(); @@ -1120,13 +1135,19 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) log_status(" ======== symex nondet ===== "); lhs->dump(); effect->dump(); - - expr2tc l1_lhs = lhs; + expr2tc new_lhs = lhs; expr2tc heap_region = - create_heap_region(to_sideeffect2t(effect), l1_lhs); + create_heap_region(to_sideeffect2t(effect), new_lhs); symex_assign(code_assign2tc(lhs, heap_region)); + + const intheap_type2t &_type = to_intheap_type(new_lhs->type); + + track_new_pointer( + _type.location, + get_intheap_type(), + gen_ulong(_type.total_bytes)); log_status(" ======== symex nondet ===== "); } \ No newline at end of file diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index cdaba808..63a35620 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -140,6 +140,9 @@ void goto_symext::symex_dead(const expr2tc code) // Call free on alloca'd objects if (identifier.as_string().find("return_value$_alloca") != std::string::npos) symex_free(code_free2tc(l1_sym)); + + // TODO : SLHV free variable like struct + // set its heap variable to be emp // Erase from level 1 propagation cur_state->value_set.erase(to_symbol2t(l1_sym).get_symbol_name()); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 1b2694b2..a457934d 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -1244,7 +1244,7 @@ void value_sett::assign( return; } - if (is_intheap_type(lhs_type)) + if (is_intheap_type(lhs_type) && !is_constant_intheap2t(rhs)) { if (is_heap_region2t(rhs)) { @@ -1257,36 +1257,69 @@ void value_sett::assign( assign_rec(lhs, values_rhs, "", add_to_sets); return; } - if (to_intheap_type(lhs_type).is_region && is_heap_update2t(rhs)) + if (to_intheap_type(lhs_type).is_region) { - const heap_update2t &heap_upd = to_heap_update2t(rhs); - const expr2tc &upd_heap = heap_upd.source_heap; - const expr2tc &upd_field = heap_upd.operand_1; - const expr2tc &upd_value = heap_upd.operand_2; - - if (!is_constant_int2t(upd_field)) + if (!is_intheap_type(rhs->type) || + !to_intheap_type(rhs->type).is_region) { - log_error("Do not support dynamic field"); + log_error("Wrong assignment for heap variable"); abort(); } - unsigned int field = to_constant_int2t(upd_field).value.to_uint64(); - const intheap_type2t &_type = to_intheap_type(upd_heap->type); - for (unsigned int i = 0; i < _type.field_types.size(); i++) + unsigned int _field = -1; + expr2tc rhs_heap; + type2tc rhs_type; + + if (is_heap_update2t(rhs)) { - expr2tc lhs_field; - expr2tc val; - if (i == field) + const heap_update2t &heap_upd = to_heap_update2t(rhs); + rhs_heap = heap_upd.source_heap; + rhs_type = rhs_heap->type; + const expr2tc &upd_field = heap_upd.operand_1; + const expr2tc &upd_value = heap_upd.operand_2; + + if (!is_constant_int2t(upd_field)) { - lhs_field = field_of2tc(rhs->type, upd_heap, upd_field); - val = upd_value; + log_error("Do not support dynamic field"); + abort(); } - else + + _field = to_constant_int2t(upd_field).value.to_uint64(); + const intheap_type2t &_type = to_intheap_type(rhs_type); + expr2tc lhs_field = + field_of2tc(_type.field_types[_field], rhs_heap, upd_field); + + assign(lhs_field, upd_value, false); + } + else if (is_symbol2t(rhs)) + { + rhs_heap = rhs; + rhs_type = rhs->type; + } + else + { + log_error("Some wrong"); + abort(); + } + + const intheap_type2t &_lhs_type = to_intheap_type(lhs->type); + const intheap_type2t &_rhs_type = to_intheap_type(rhs_type); + + for (unsigned int i = 0; i < _lhs_type.field_types.size(); i++) + { + if (i == _field) continue; + if (_lhs_type.field_types[i] != _rhs_type.field_types[i]) { - lhs_field = field_of2tc(_type.field_types[i], upd_heap, gen_ulong(i)); - val = lhs_field; + log_error("Type does not match!!!"); + abort(); } - assign(lhs_field, val, false); + + expr2tc lhs_field = + field_of2tc(_lhs_type.field_types[i], lhs, gen_ulong(i)); + expr2tc rhs_field = + field_of2tc(_rhs_type.field_types[i], rhs_heap, gen_ulong(i)); + + assign(lhs_field, rhs_field, false); } return; From 77631e5fd6bf4a2dc694ce2b87d333c441a07ef6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 4 Sep 2024 09:24:01 +0800 Subject: [PATCH 065/126] fix symex nondet --- src/goto-symex/symex_assign.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 2c081f61..1c4e5109 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -1137,17 +1137,26 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) effect->dump(); expr2tc new_lhs = lhs; - expr2tc heap_region = - create_heap_region(to_sideeffect2t(effect), new_lhs); + expr2tc new_rhs = effect; - symex_assign(code_assign2tc(lhs, heap_region)); + const sideeffect2t &_effect = to_sideeffect2t(effect); - const intheap_type2t &_type = to_intheap_type(new_lhs->type); + if (!is_nil_type(_effect.alloctype) && is_struct_type(_effect.alloctype)) + new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); + else + replace_nondet(new_rhs); + + symex_assign(code_assign2tc(lhs, new_rhs)); + + if (is_intheap_type(new_lhs->type)) + { + const intheap_type2t &_type = to_intheap_type(new_lhs->type); + + track_new_pointer( + _type.location, + get_intheap_type(), + gen_ulong(_type.total_bytes)); + } - track_new_pointer( - _type.location, - get_intheap_type(), - gen_ulong(_type.total_bytes)); - log_status(" ======== symex nondet ===== "); } \ No newline at end of file From 759023b1ddcac7a6e98f3edcaaa5adf5023d8791 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 4 Sep 2024 13:53:39 +0800 Subject: [PATCH 066/126] fix object offset when dereferencing and project --- src/goto-symex/dynamic_allocation.cpp | 1 - src/goto-symex/goto_symex_state.cpp | 8 ++++- src/goto-symex/symex_assign.cpp | 3 ++ src/goto-symex/symex_main.cpp | 5 ++- src/pointer-analysis/dereference.cpp | 28 +++-------------- src/pointer-analysis/value_set.cpp | 28 +++++++++++++---- src/solvers/smt/smt_conv.cpp | 1 - src/solvers/z3-slhv/z3_slhv_conv.cpp | 44 +++++++++------------------ src/solvers/z3-slhv/z3_slhv_conv.h | 2 +- 9 files changed, 55 insertions(+), 65 deletions(-) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 02ea409c..a2b06e14 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -53,7 +53,6 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) points_to2tc(_type.location, size) ); expr = heap_contain; - log_status(" --- generate cond for checking heap region --- "); } } else if (is_invalid_pointer2t(expr)) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 13dfc1be..2b8516fc 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -78,7 +78,13 @@ bool goto_symex_statet::constant_propagation(const expr2tc &expr) const } if (is_location_of2t(expr)) - return constant_propagation(to_location_of2t(expr).source_heap); + { + // Similar to address_of + if (is_symbol2t(to_location_of2t(expr).source_heap)) + return true; // always return true + + // TODO + } if (is_array_type(expr)) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 1c4e5109..9e074bea 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -1113,6 +1113,9 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla else { expr2tc op = effect.operand; + cur_state->rename(op); + log_status("malloc size:"); + op->dump(); do_simplify(op); if (!is_constant_int2t(op)) { diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 57f25efa..047eb8c6 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -176,7 +176,7 @@ void goto_symext::symex_step(reachability_treet &art) symex_end_of_function(); this->cur_state->level2.print(std::cout); - + // Potentially skip to run another function ptr target; if not, // continue if (!run_next_function_ptr_target(false)) @@ -188,7 +188,10 @@ void goto_symext::symex_step(reachability_treet &art) log_status(" ======= goto symex: GOTO"); expr2tc tmp(instruction.guard); if (options.get_bool_option("z3-slhv")) + { replace_null(tmp); + replace_pointer_airth(tmp); + } replace_nondet(tmp); dereference(tmp, dereferencet::READ); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 18112c47..367ee684 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -522,32 +522,13 @@ expr2tc dereferencet::dereference( expr2tc value; if (!known_exhaustive) value = make_failed_symbol(type); - - // TODO : fix - // Extract base location ad offset from locadd - // In SLHV, all offset is in word-level - expr2tc new_src = src; - // TODO : rename new_src by constant to get offset - expr2tc offset = lexical_offset; - if (is_locadd2t(src)) - { - new_src = to_locadd2t(src).get_base_location(); - expr2tc off_from_src = to_locadd2t(src).get_offset(); - if (is_nil_expr(offset)) - offset = off_from_src; - else - offset = add2tc(offset->type, offset, off_from_src); - expr2tc simp = offset->simplify(); - if (!is_nil_expr(simp)) - offset = simp; - } for (const expr2tc &target : points_to_set) { expr2tc new_value, pointer_guard; new_value = build_reference_to( - target, mode, new_src, type, guard, offset, pointer_guard); + target, mode, src, type, guard, lexical_offset, pointer_guard); if (is_nil_expr(new_value)) continue; @@ -798,6 +779,8 @@ expr2tc dereferencet::build_reference_to( // that to be a dereference of foo + extra_offset, resulting in an integer. if (!is_nil_expr(lexical_offset)) final_offset = add2tc(final_offset->type, final_offset, lexical_offset); + + final_offset->dump(); // If we're in internal mode, collect all of our data into one struct, insert // it into the list of internal data, and then bail. The caller does not want @@ -871,8 +854,6 @@ expr2tc dereferencet::build_reference_to( } pointer_guard = same_object2tc(deref_expr, location_of2tc(value)); tmp_guard.add(pointer_guard); - - log_status("generated pointer guard:"); pointer_guard->dump(); @@ -893,8 +874,7 @@ expr2tc dereferencet::build_reference_to( // Final offset computations start here expr2tc final_offset = o.offset; - if (!is_constant_int2t(final_offset) || - to_constant_int2t(final_offset).value.to_uint64() != 0) + if (!is_constant_int2t(final_offset)) { log_error("Wrong offset for object"); abort(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index a457934d..95b1addc 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -566,6 +566,7 @@ void value_sett::get_value_set_rec( else log_status("nothing"); } + // SLHV: if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || is_heap_append2t(expr) || is_heap_delete2t(expr)) @@ -579,20 +580,35 @@ void value_sett::get_value_set_rec( { expr2tc simp = expr; - if (!is_symbol2t(to_locadd2t(simp).location) || - !is_constant_int2t(to_locadd2t(simp).offset)) + if (!is_constant_int2t(to_locadd2t(simp).offset)) simp = simp->simplify(); - - if (!is_symbol2t(to_locadd2t(simp).location) || - !is_constant_int2t(to_locadd2t(simp).offset)) + if (!is_constant_int2t(to_locadd2t(simp).offset)) { log_error("Do not support dynamic pointer arithmetic"); abort(); } const locadd2t &locadd = to_locadd2t(simp); + BigInt off = to_constant_int2t(locadd.offset).value; + + object_mapt pointer_expr_set; + get_value_set_rec(locadd.location, pointer_expr_set, suffix, original_type); + + for (const auto &it : pointer_expr_set) + { + objectt object = it.second; + + // TODO : Do more analysis + + if (object.offset_is_set) + object.offset += off; // may be useless + else + object.offset = off; + + // Once updated, store object reference into destination map. + insert(dest, it.first, object); + } - get_value_set_rec(locadd.location, dest, suffix, original_type); return; } diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 17687f1e..8e1b4f05 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -337,7 +337,6 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) log_status("begin convert expr"); expr->dump(); - log_status("done"); smt_astt a; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 80b7a115..9c96e8bf 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -301,13 +301,10 @@ z3_slhv_convt::convert_slhv_opts( { // Do project for SLHV const same_object2t& same = to_same_object2t(expr); - z3_slhv_convt::smt_ast_pair p1 = this->project(same.side_1); - z3_slhv_convt::smt_ast_pair p2 = this->project(same.side_2); - - smt_astt cond = mk_and(p1.first, p2.first); - smt_astt eq = mk_eq(p1.second, p2.second); - - return mk_and(cond, eq); + smt_astt p1 = this->project(same.side_1); + smt_astt p2 = this->project(same.side_2); + smt_astt eq = mk_eq(p1, p2); + return eq; } default: { log_status("Invalid SLHV operations!!!"); @@ -417,8 +414,7 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) } } -z3_slhv_convt::smt_ast_pair -z3_slhv_convt::project(const expr2tc &expr) +smt_astt z3_slhv_convt::project(const expr2tc &expr) { if (is_symbol2t(expr)) { @@ -427,34 +423,22 @@ z3_slhv_convt::project(const expr2tc &expr) const intheap_type2t &_type = to_intheap_type(expr->type); return this->project(_type.location); } - return convert_opt_without_assert(expr); + return convert_opt_without_assert(expr).second; } else if (is_location_of2t(expr)) return this->project(to_location_of2t(expr).source_heap); else if (is_field_of2t(expr)) - return convert_opt_without_assert(expr); + return convert_opt_without_assert(expr).second; else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); - else if (is_locadd2t(expr) || is_add2t(expr) || is_sub2t(expr)) + else if (is_locadd2t(expr)) + return this->project(to_locadd2t(expr).location); + else { - // TODO : fix - expr2tc ptr; - if (is_locadd2t(expr)) - ptr = to_locadd2t(expr).location; - else if (is_add2t(expr)) - ptr = (is_pointer_type(to_add2t(expr).side_1) || is_intloc_type(to_add2t(expr).side_1))? - to_add2t(expr).side_1 : to_add2t(expr).side_2; - else if (is_sub2t(expr)) - ptr = (is_pointer_type(to_sub2t(expr).side_1) || is_intloc_type(to_sub2t(expr).side_1))? - to_sub2t(expr).side_1 : to_sub2t(expr).side_2; - return this->project(ptr); - } -else -{ - log_error("Do not support project"); - expr->dump(); - abort(); -} + log_error("Do not support project"); + expr->dump(); + abort(); + } } void z3_slhv_convt::dump_smt() { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 0ed5f49d..5ab9d3d7 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -46,7 +46,7 @@ class z3_slhv_convt : public z3_convt { smt_ast_pair convert_opt_without_assert(const expr2tc &expr); - smt_ast_pair project(const expr2tc &expr); + smt_astt project(const expr2tc &expr); void dump_smt() override; From f1d0b4554c825bd74da932b07af401f107291ee6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 4 Sep 2024 14:01:51 +0800 Subject: [PATCH 067/126] add script --- scripts/x.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 scripts/x.py diff --git a/scripts/x.py b/scripts/x.py new file mode 100755 index 00000000..c90b51af --- /dev/null +++ b/scripts/x.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +if __name__ == '__main__': + import os + import sys + + esbmc_slhv_root = "./esbmc/" + esbmc_slhv_build = esbmc_slhv_root + "build/" + esbmc_slhv = esbmc_slhv_build + "src/esbmc/esbmc" + + if sys.argv[1] == "--compile": + os.system(f"cd {esbmc_slhv_build } && cmake --build .") + elif sys.argv[1] == "--run": + cprog = sys.argv[2] + assert(os.path.exists(cprog)) + + output_file = "vcc.log" + + args = [ + cprog, + "--no-library", + "--ir", + "--force-malloc-success", + "--memory-leak-check", + "--ssa-smt-trace", + "--result-only", + "--show-vcc", + "--output", + output_file + ] + + if "--bv" not in sys.argv : args.append("--z3-slhv") + if "--multi" in sys.argv : args.append("--multi-property") + if "--no-slice" in sys.argv : args.append("--no-slice") + + os.system(esbmc_slhv + " " + " ".join(args)) + elif sys.argv[1] == "--help": + os.system(f"{esbmc_slhv} -h") + else: + assert(False) From 5a12ee745a159a89b23621be9ca89e13654281bd Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 4 Sep 2024 17:24:28 +0800 Subject: [PATCH 068/126] fix compute offset by from locadd --- src/goto-symex/symex_assign.cpp | 4 +- src/goto-symex/symex_main.cpp | 5 +++ src/goto-symex/symex_other.cpp | 7 +-- src/pointer-analysis/dereference.cpp | 64 ++++++++++++++-------------- src/pointer-analysis/value_set.cpp | 23 +++++----- 5 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 9e074bea..c8328ef2 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -972,6 +972,8 @@ void goto_symext::replace_pointer_airth(expr2tc &expr) if (is_add2t(expr) || is_sub2t(expr)) { + if (!is_pointer_type(expr) && !is_intloc_type(expr)) return; + expr2tc side_1 = is_add2t(expr) ? to_add2t(expr).side_1 : to_sub2t(expr).side_1; expr2tc side_2 = is_add2t(expr) ? to_add2t(expr).side_2 : to_sub2t(expr).side_2; @@ -988,7 +990,7 @@ void goto_symext::replace_pointer_airth(expr2tc &expr) expr2tc locadd = locadd2tc(side_1, side_2); do_simplify(locadd); - + expr = locadd; } diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 047eb8c6..910a7fc5 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -194,6 +194,8 @@ void goto_symext::symex_step(reachability_treet &art) } replace_nondet(tmp); + tmp->dump(); + dereference(tmp, dereferencet::READ); replace_dynamic_allocation(tmp); @@ -409,7 +411,10 @@ void goto_symext::symex_assume() expr2tc cond = cur_state->source.pc->guard; if (options.get_bool_option("z3-slhv")) + { replace_null(cond); + replace_pointer_airth(cond); + } replace_nondet(cond); dereference(cond, dereferencet::READ); replace_dynamic_allocation(cond); diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index 63a35620..a9e3dcac 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -8,8 +8,11 @@ void goto_symext::symex_other(const expr2tc code) { expr2tc code2 = code; if (options.get_bool_option("z3-slhv")) + { replace_null(code2); - + replace_pointer_airth(code2); + } + code2->dump(); if (is_code_expression2t(code2)) @@ -116,8 +119,6 @@ void goto_symext::symex_dead(const expr2tc code) assert(is_code_dead2t(code)); expr2tc code2 = code; - if (options.get_bool_option("z3-slhv")) - replace_null(code2); replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::INTERNAL); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 367ee684..57b6d36a 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -779,8 +779,6 @@ expr2tc dereferencet::build_reference_to( // that to be a dereference of foo + extra_offset, resulting in an integer. if (!is_nil_expr(lexical_offset)) final_offset = add2tc(final_offset->type, final_offset, lexical_offset); - - final_offset->dump(); // If we're in internal mode, collect all of our data into one struct, insert // it into the list of internal data, and then bail. The caller does not want @@ -876,15 +874,25 @@ expr2tc dereferencet::build_reference_to( if (!is_constant_int2t(final_offset)) { - log_error("Wrong offset for object"); - abort(); + if (is_locadd2t(deref_expr)) + { + log_status("get offset from locadd by renaming"); + expr2tc locadd = deref_expr; + dereference_callback.rename(locadd); + expr2tc off = to_locadd2t(locadd).get_offset(); + off->dump(); + log_status("after renaming"); + off->dump(); + + final_offset = to_locadd2t(off).get_offset(); + } + else + { + log_error("Wrong offset"); + abort(); + } } - #if 0 - // FIXME: benchmark this, on tacas. - dereference_callback.rename(final_offset); - #endif - // maybe used later unsigned int alignment = o.alignment; @@ -892,6 +900,16 @@ expr2tc dereferencet::build_reference_to( final_offset = add2tc(final_offset->type, final_offset, lexical_offset); simplify(final_offset); + log_status("final offset : "); + final_offset->dump(); + + if (!is_constant_int2t(final_offset) && + !is_symbol2t(final_offset)) + { + log_error("Wrong offset, support later"); + abort(); + } + // If we're in internal mode, collect all of our data into one struct, insert // it into the list of internal data, and then bail. The caller does not want // to have a reference built at all. @@ -2538,10 +2556,7 @@ void dereferencet::check_heap_region_access( const guardt &guard, modet mode) { - // This check is in byte-level; - // Since we construct offset in word level and store total bytes - // of region in heap_alloc_size, offset should be transfered to - // byte-level. + // This check is in word-level; log_status(" ------------------ check heap region access ------------------ "); value->dump(); @@ -2549,13 +2564,6 @@ void dereferencet::check_heap_region_access( type->dump(); guard.dump(); - if (!is_constant_int2t(offset)) - { - // TODO : support - log_error("Do not support non-constant offset"); - abort(); - } - const heap_region2t& heap_region = to_heap_region2t(value); const intheap_type2t &_type = to_intheap_type(heap_region.type); @@ -2565,22 +2573,14 @@ void dereferencet::check_heap_region_access( abort(); } - unsigned int _offset_bytes = - to_constant_int2t(offset).value.to_uint64() * 8; - expr2tc offset_bytes = gen_ulong(_offset_bytes); - - expr2tc total_bytes = gen_ulong(_type.total_bytes); - - expr2tc access_sz = gen_ulong(type_byte_size(type, &ns).to_uint64()); - expr2tc l = offset_bytes; - expr2tc r = add2tc(l->type, l, access_sz); - simplify(r); + expr2tc size = gen_ulong(_type.field_types.size()); expr2tc offset_cond = and2tc( - greaterthanequal2tc(l, gen_ulong(0)), - lessthanequal2tc(r, total_bytes) + greaterthanequal2tc(offset, gen_ulong(0)), + lessthanequal2tc(offset, size) ); + log_status("offset condition:"); offset_cond->dump(); expr2tc bound_check = not2tc(offset_cond); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 95b1addc..f6a538bc 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -578,18 +578,15 @@ void value_sett::get_value_set_rec( if (is_locadd2t(expr)) { - expr2tc simp = expr; + const locadd2t &locadd = to_locadd2t(expr); - if (!is_constant_int2t(to_locadd2t(simp).offset)) - simp = simp->simplify(); - if (!is_constant_int2t(to_locadd2t(simp).offset)) + bool is_const = false; + BigInt off; + if (is_constant_int2t(locadd.offset)) { - log_error("Do not support dynamic pointer arithmetic"); - abort(); + off = to_constant_int2t(locadd.offset).value; + is_const = true; } - - const locadd2t &locadd = to_locadd2t(simp); - BigInt off = to_constant_int2t(locadd.offset).value; object_mapt pointer_expr_set; get_value_set_rec(locadd.location, pointer_expr_set, suffix, original_type); @@ -600,10 +597,10 @@ void value_sett::get_value_set_rec( // TODO : Do more analysis - if (object.offset_is_set) - object.offset += off; // may be useless - else - object.offset = off; + if (is_const && object.offset_is_set) + object.offset += off; + else if (!is_const) + object.offset_is_set = false; // Once updated, store object reference into destination map. insert(dest, it.first, object); From cc9210b87e58db12fb56220c023baf50ac98466f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 5 Sep 2024 14:30:02 +0800 Subject: [PATCH 069/126] fix build deref for a whole region and fix project for field_of --- benchmark/case_3.c | 8 +-- src/goto-symex/symex_target_equation.cpp | 7 ++- src/pointer-analysis/dereference.cpp | 18 +++--- src/solvers/smt/smt_conv.cpp | 19 +++--- src/solvers/z3-slhv/z3_slhv_conv.cpp | 74 ++++++++++-------------- src/solvers/z3-slhv/z3_slhv_conv.h | 4 -- 6 files changed, 58 insertions(+), 72 deletions(-) diff --git a/benchmark/case_3.c b/benchmark/case_3.c index b80f5896..8a3aa9ed 100644 --- a/benchmark/case_3.c +++ b/benchmark/case_3.c @@ -2,8 +2,8 @@ int main(){ - int num = 5; - int *j = (int*)malloc(num*sizeof(int)); - *(j+6) = num + (-1); - free(j); + int **p = malloc(sizeof(int*)); + *p = malloc(sizeof(int)); + free(*p); + free(p); } \ No newline at end of file diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 6929b399..62be9118 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -169,9 +169,10 @@ void symex_target_equationt::convert_internal_step( step.dump(); log_status(" ============================== step ======================== "); - log_status("convert step guard ast: "); - step.guard_ast = smt_conv.convert_ast(step.guard); - step.guard_ast->dump(); + // log_status("convert step guard ast: "); + // guard_ast is used for generating witness + // not used now + // step.guard_ast = smt_conv.convert_ast(step.guard); if (step.is_assume() || step.is_assert()) { diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 57b6d36a..ea797cf5 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -532,12 +532,12 @@ expr2tc dereferencet::dereference( if (is_nil_expr(new_value)) continue; - - log_status("after building reference to : not nill"); - new_value->dump(); assert(!is_nil_expr(pointer_guard)); + new_value->dump(); + type->dump(); + if (!dereference_type_compare(new_value, type)) { guardt new_guard(guard); @@ -915,6 +915,7 @@ expr2tc dereferencet::build_reference_to( // to have a reference built at all. if (is_internal(mode)) { + log_status("collect objects for doing free"); dereference_callbackt::internal_item internal; internal.object = value; internal.offset = final_offset; // offset for SLHV @@ -1274,10 +1275,8 @@ void dereferencet::build_deref_slhv( log_error("heap region must be aligned"); abort(); } - - // heap region as a value - if (field == 0 && access_sz == _type.total_bytes) return; + bool is_field = true; if (field >= _type.field_types.size() || access_sz != _type.total_bytes / _type.field_types.size()) { @@ -1286,15 +1285,18 @@ void dereferencet::build_deref_slhv( type, dereference_callback.get_nondet_id("undefined_behavior_var")); value = sym; - return; + is_field = false; } else value = field_of2tc(type, value, gen_ulong(field)); // update field type - if (_type.set_field_type(field, type)) + if (is_field && _type.set_field_type(field, type)) dereference_callback.update_heap_type(_type); + log_status("return dereference --->"); + value->dump(); + log_status(" ----------------- build deref slhv ----------------- "); } diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 8e1b4f05..c50cd3ef 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -252,6 +252,8 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) return (cache_result->ast); } + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + /* Vectors! * * Here we need special attention for Vectors, because of the way @@ -262,7 +264,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) * for some reason we would like to run ESBMC without simplifications * then we need to apply it here. */ - if (!options.get_bool_option("z3-slhv") && is_vector_type(expr)) + if (use_old_encoding && is_vector_type(expr)) { if (is_neg2t(expr)) { @@ -317,12 +319,15 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::pointer_capability_id: case expr2t::field_of_id: + case expr2t::heap_region_id: case expr2t::heap_update_id: case expr2t::heap_delete_id: break; // Don't convert their operands default: { + if (is_same_object2t(expr) && !use_old_encoding) break; + // Convert all the arguments and store them in 'args'. unsigned int i = 0; expr->foreach_operand( @@ -365,8 +370,6 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::symbol_id: { a = convert_terminal(expr); - log_status("convert_terminal result: "); - a->dump(); break; } case expr2t::constant_string_id: @@ -455,7 +458,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) is_pointer_type(expr->type) || is_pointer_type(add.side_1) || is_pointer_type(add.side_2)) { - a = this->solver_text() == "Z3-slhv" ? + a = !use_old_encoding ? convert_slhv_opts(expr, args) : convert_pointer_arith(expr, expr->type); } @@ -476,7 +479,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || is_pointer_type(sub.side_2)) { - a = this->solver_text() == "Z3-slhv" ? + a = !use_old_encoding ? convert_slhv_opts(expr, args) : convert_pointer_arith(expr, expr->type); } @@ -742,7 +745,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) { const same_object2t& so = to_same_object2t(expr); // Two projects, then comparison. - if (this->solver_text() != "Z3-slhv") { + if (use_old_encoding) { args[0] = args[0]->project(this, 0); args[1] = args[1]->project(this, 0); a = mk_eq(args[0], args[1]); @@ -760,7 +763,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) ptr = &to_typecast2t(*ptr).from; args[0] = convert_ast(*ptr); - a = this->solver_text() == "Z3-slhv" ? args[0] : args[0]->project(this, 0); + a = !use_old_encoding ? args[0] : args[0]->project(this, 0); break; } case expr2t::pointer_object_id: @@ -772,7 +775,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) ptr = &to_typecast2t(*ptr).from; args[0] = convert_ast(*ptr); - a = this->solver_text() == "Z3-slhv" ? args[0] : args[0]->project(this, 0); + a = !use_old_encoding ? args[0] : args[0]->project(this, 0); break; } case expr2t::pointer_capability_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 9c96e8bf..452b6393 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -206,13 +206,15 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::heap_region_id: { const intheap_type2t &_type = to_intheap_type(expr->type); + + smt_astt base_loc = convert_ast(_type.location); std::vector pt_vec; if (_type.is_aligned) { for (unsigned i = 0; i < _type.field_types.size(); i++) { - smt_astt loc = i == 0 ? args[1] : mk_locadd(args[1], mk_smt_int(BigInt(i))); + smt_astt loc = i == 0 ? base_loc : mk_locadd(base_loc, mk_smt_int(BigInt(i))); smt_sortt sort = is_intloc_type(_type.field_types[i]) ? mk_intloc_sort() : mk_int_sort(); @@ -229,7 +231,7 @@ z3_slhv_convt::convert_slhv_opts( // Default sort is intloc pt_vec.push_back( mk_pt( - args[1], + base_loc, mk_fresh(mk_intloc_sort(), mk_fresh_name("tmp_loc::") ) ) @@ -289,43 +291,12 @@ z3_slhv_convt::convert_slhv_opts( } return mk_subh(args[1], args[0]); } - case expr2t::field_of_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: - { - z3_slhv_convt::smt_ast_pair sap = convert_opt_without_assert(expr); - assert_ast(sap.first); - return sap.second; - } - case expr2t::same_object_id: - { - // Do project for SLHV - const same_object2t& same = to_same_object2t(expr); - smt_astt p1 = this->project(same.side_1); - smt_astt p2 = this->project(same.side_2); - smt_astt eq = mk_eq(p1, p2); - return eq; - } - default: { - log_status("Invalid SLHV operations!!!"); - abort(); - } - } -} - -z3_slhv_convt::smt_ast_pair -z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) -{ - switch (expr->expr_id) - { case expr2t::field_of_id: { const field_of2t &field_of = to_field_of2t(expr); if (is_constant_intheap2t(field_of.source_heap)) - return std::make_pair( - mk_smt_bool(true), - mk_fresh(convert_sort(field_of.type), mk_fresh_name("invalid_loc_"))); + return mk_fresh(convert_sort(field_of.type), mk_fresh_name("invalid_fieldof_")); if (!is_constant_int2t(field_of.operand)) { @@ -357,8 +328,8 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) } smt_astt v1 = mk_fresh(s1, name); - smt_astt assert_expr = mk_subh(mk_pt(loc, v1), convert_ast(heap_region)); - return std::make_pair(assert_expr, v1); + assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region))); + return v1; } case expr2t::heap_update_id: { @@ -387,13 +358,11 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) // current heap state smt_astt old_state = mk_uplus(h1, mk_pt(loc, v1)); - smt_astt assert_expr = mk_eq(h, old_state); + assert_ast(mk_eq(h, old_state)); // new heap state smt_astt new_state = mk_uplus(h1, mk_pt(loc, val)); - - // new heap state - return std::make_pair(assert_expr, new_state); + return new_state; } case expr2t::heap_delete_id: { @@ -404,12 +373,22 @@ z3_slhv_convt::convert_opt_without_assert(const expr2tc &expr) smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - smt_astt assert_expr = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); - return std::make_pair(assert_expr, h1); + assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); + return h1; + } + case expr2t::same_object_id: + { + // Do project for SLHV + const same_object2t& same = to_same_object2t(expr); + smt_astt p1 = this->project(same.side_1); + smt_astt p2 = this->project(same.side_2); + smt_astt eq = mk_eq(p1, p2); + return eq; } default: { - return std::make_pair(mk_smt_bool(true), convert_ast(expr)); + log_status("Invalid SLHV operations!!!"); + abort(); } } } @@ -423,12 +402,17 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) const intheap_type2t &_type = to_intheap_type(expr->type); return this->project(_type.location); } - return convert_opt_without_assert(expr).second; + + if (is_intloc_type(expr) || is_pointer_type(expr)) + return convert_ast(expr); + + log_error("Wrong symbol for projection"); + expr->dump(); } else if (is_location_of2t(expr)) return this->project(to_location_of2t(expr).source_heap); else if (is_field_of2t(expr)) - return convert_opt_without_assert(expr).second; + return convert_ast(expr); else if (is_typecast2t(expr)) return this->project(to_typecast2t(expr).from); else if (is_locadd2t(expr)) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 5ab9d3d7..611096fa 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -42,10 +42,6 @@ class z3_slhv_convt : public z3_convt { smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; - typedef std::pair smt_ast_pair; - - smt_ast_pair convert_opt_without_assert(const expr2tc &expr); - smt_astt project(const expr2tc &expr); void dump_smt() override; From cc18ad81613a840ec2cf13a01e21b06d4824c5f5 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 6 Sep 2024 10:22:01 +0800 Subject: [PATCH 070/126] fix pointer analysis --- benchmark/case_4.c | 45 +++--- src/goto-symex/dynamic_allocation.cpp | 19 ++- src/goto-symex/goto_symex.h | 8 + src/goto-symex/goto_symex_state.cpp | 6 + src/goto-symex/symex_assign.cpp | 32 +++- src/goto-symex/symex_main.cpp | 9 ++ src/goto-symex/symex_other.cpp | 1 + src/irep2/irep2_expr.cpp | 2 + src/pointer-analysis/dereference.cpp | 202 +++++++++++++------------- src/pointer-analysis/value_set.cpp | 68 ++++----- src/solvers/z3-slhv/z3_slhv_conv.cpp | 39 ++++- src/util/simplify_expr2.cpp | 4 + 12 files changed, 268 insertions(+), 167 deletions(-) diff --git a/benchmark/case_4.c b/benchmark/case_4.c index 0d4c9e8d..73f23414 100644 --- a/benchmark/case_4.c +++ b/benchmark/case_4.c @@ -1,19 +1,28 @@ #include -int *a, *b; -int n; - -int main(){ - n = 128; - a = malloc (n * sizeof(*a)); - b = malloc (n * sizeof(*b)); - *b++ = 0; - int i; - for (i = 0; i < n; i++) - a[i] = -1; - for (i = 0; i < 128 - 1; i++) - b[i] = -1; - if (b[-2]) /* invalid deref */ - { free(a); free(b-1); } - else - { free(a); free(b-1); } -} \ No newline at end of file +extern int __VERIFIER_nondet_int(void); +struct item { + struct item *next; + struct item *data; +}; +static void append(struct item **plist) +{ + struct item *item = malloc(sizeof *item); + item->next = *plist; + item->data = (item->next) + ? item->next->data + : malloc(sizeof *item); + *plist = item; +} +int main() +{ + struct item *list = ((void *)0); + int i = 0; + append(&list); + if (list) { + struct item *next = list->next; + free(list->data); + free(list); + list = next; + } + return 0; +} diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index a2b06e14..5ad473ed 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -31,7 +31,6 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr = index_expr; } else { // Checking that the object is valid by heap_alloc_size - log_status(" --- generate cond for checking heap region --- "); const valid_object2t &obj = to_valid_object2t(expr); const expr2tc &heap_region = obj.value; if (!is_intheap_type(heap_region->type) || @@ -96,12 +95,24 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { - // TODO : support - log_error("Dot not support invalid pointer yet"); - abort(); + log_status("replace invalid pointer"); + obj_expr->dump(); expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); + + unsigned int &nondet_counter = get_nondet_counter(); + nondet_counter++; + expr2tc size_sym = + symbol2tc( + get_int64_type(), + std::string("INVALID_SIZE_") + std::to_string(nondet_counter) + ); + expr2tc pt = points_to2tc(obj_expr, size_sym); + + expr2tc heap_ct = heap_contain2tc(alloc_size_heap, pt); + + expr = not2tc(heap_ct); } } else if (is_deallocated_obj2t(expr)) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 217a66cf..830eb3d8 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -817,6 +817,14 @@ class goto_symext */ void replace_address_of(expr2tc &expr); + /** + * @brief Eliminate typecast from intloc to pointer and + * replace casting from pointer to bool by equation + * + * @param expr + */ + void replace_typecast(expr2tc &expr); + /** * @brief Replace all struct/array variable by heap variable * @param expr diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 2b8516fc..36123281 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -279,6 +279,12 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } + else if (is_location_of2t(expr)) + { + location_of2t &loc_of = to_location_of2t(expr); + // Only do l1 rename + rename_address(loc_of.source_heap); + } else { // do this recursively diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index c8328ef2..b1f35e30 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -199,6 +199,9 @@ void goto_symext::symex_assign( replace_tuple(lhs); replace_tuple(rhs); + replace_typecast(lhs); + replace_typecast(rhs); + if (is_sideeffect2t(rhs) && to_sideeffect2t(rhs).kind == sideeffect2t::nondet) { @@ -1019,6 +1022,28 @@ void goto_symext::replace_address_of(expr2tc &expr) } } +void goto_symext::replace_typecast(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + + expr->Foreach_operand([this](expr2tc &e) { replace_typecast(e); }); + + if (is_typecast2t(expr)) + { + const typecast2t &typecast = to_typecast2t(expr); + + // Oly replace bool typecast + if ((is_pointer_type(typecast.from) || is_intloc_type(typecast.from)) + && is_bool_type(typecast.type)) + { + log_status("replace typecast to bool"); + expr->dump(); + + expr = notequal2tc(typecast.from, gen_nil()); + } + } +} + void goto_symext::replace_tuple(expr2tc &expr) { if (is_nil_expr(expr)) return; @@ -1146,10 +1171,11 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) const sideeffect2t &_effect = to_sideeffect2t(effect); - if (!is_nil_type(_effect.alloctype) && is_struct_type(_effect.alloctype)) - new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); - else + if (_effect.kind == sideeffect2t::nondet && + !is_struct_type(_effect.type)) replace_nondet(new_rhs); + else + new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); symex_assign(code_assign2tc(lhs, new_rhs)); diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 910a7fc5..81aeb228 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -191,6 +191,7 @@ void goto_symext::symex_step(reachability_treet &art) { replace_null(tmp); replace_pointer_airth(tmp); + replace_typecast(tmp); } replace_nondet(tmp); @@ -199,6 +200,7 @@ void goto_symext::symex_step(reachability_treet &art) dereference(tmp, dereferencet::READ); replace_dynamic_allocation(tmp); + log_status("herer"); symex_goto(tmp); } break; @@ -226,7 +228,10 @@ void goto_symext::symex_step(reachability_treet &art) } if (options.get_bool_option("z3-slhv")) + { replace_null(thecode); + replace_typecast(thecode); + } symex_return(thecode); } @@ -414,6 +419,7 @@ void goto_symext::symex_assume() { replace_null(cond); replace_pointer_airth(cond); + replace_typecast(cond); } replace_nondet(cond); dereference(cond, dereferencet::READ); @@ -440,7 +446,10 @@ void goto_symext::symex_assert() expr2tc tmp = instruction.guard; if (options.get_bool_option("z3-slhv")) + { replace_null(tmp); + replace_typecast(tmp); + } replace_nondet(tmp); intrinsic_races_check_dereference(tmp); diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index a9e3dcac..981b5801 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -11,6 +11,7 @@ void goto_symext::symex_other(const expr2tc code) { replace_null(code2); replace_pointer_airth(code2); + replace_typecast(code2); } code2->dump(); diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 562fd061..252ea1d5 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -449,6 +449,8 @@ const expr2tc &object_descriptor2t::get_root_object() const tmp = &to_member2t(*tmp).source_value; else if (is_index2t(*tmp)) tmp = &to_index2t(*tmp).source_value; + else if (is_field_of2t(*tmp)) + tmp = &to_field_of2t(*tmp).source_heap; else return *tmp; } while (1); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index ea797cf5..43fce212 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -384,7 +384,11 @@ expr2tc dereferencet::dereference_expr_nonscalar( } // Determine offset accumulated to this point (in bits) - expr2tc offset_to_scalar = compute_pointer_offset_bits(base, &ns); + expr2tc offset_to_scalar; + if (is_field_of2t(base)) + offset_to_scalar = to_field_of2t(base).operand; + else + offset_to_scalar = compute_pointer_offset_bits(base, &ns); simplify(offset_to_scalar); dereference2t &deref = to_dereference2t(expr); @@ -442,21 +446,7 @@ expr2tc dereferencet::dereference_expr_nonscalar( { field_of2t &field_of = to_field_of2t(expr); - if (!is_dereference2t(field_of.source_heap)) - { - log_error("Do not support struct in struct yet"); - abort(); - } - - dereference2t &deref = to_dereference2t(field_of.source_heap); - - // Get the heap region - dereference_expr(deref.value, guard, dereferencet::READ); - - expr2tc offset_to_scalar = field_of.operand; - simplify(offset_to_scalar); - - return dereference(deref.value, base->type, guard, mode, offset_to_scalar); + return dereference_expr_nonscalar(field_of.source_heap, guard, mode, base); } // there should be no sudden transition back to scalars, except through @@ -480,7 +470,11 @@ expr2tc dereferencet::dereference( { log_status("--------------- dereferencing pointer ---------"); orig_src->dump(); - + if (!is_nil_expr(lexical_offset)) + { + log_status("with lexical offset : "); + lexical_offset->dump(); + } internal_items.clear(); // Awkwardly, the pointer might not be of pointer type, for example with @@ -503,10 +497,7 @@ expr2tc dereferencet::dereference( src->dump(); dereference_callback.get_value_set(src, points_to_set); log_status("---- value set: {} items", points_to_set.size()); - for(expr2tc e : points_to_set) { - e->dump(); - log_status("----"); - } + log_status("get value set done --------------------"); /* If the value-set contains unknown or invalid, we cannot be sure it contains * all possible values and we have to add a fallback symbol in case all guards @@ -535,9 +526,6 @@ expr2tc dereferencet::dereference( assert(!is_nil_expr(pointer_guard)); - new_value->dump(); - type->dump(); - if (!dereference_type_compare(new_value, type)) { guardt new_guard(guard); @@ -658,8 +646,10 @@ expr2tc dereferencet::build_reference_to( expr2tc &pointer_guard) { log_status(" =================== build reference to =================== "); - what->dump(); deref_expr->dump(); + log_status("|------------ points to -------------> "); + what->dump(); + log_status("--------------------"); expr2tc value; pointer_guard = gen_false_expr(); @@ -683,23 +673,16 @@ expr2tc dereferencet::build_reference_to( bool use_old_encoding = !options.get_bool_option("z3-slhv"); - if ((is_constant_intloc2t(object) || - is_constant_intheap2t(object) || - is_null_object2t(root_object)) && - !is_free(mode) && !is_internal(mode)) + if (is_null_object2t(root_object) &&!is_free(mode) && !is_internal(mode)) { expr2tc pointer_guard; + type2tc nullptrtype = pointer_type2tc(type); + expr2tc null_ptr = symbol2tc(nullptrtype, "NULL"); + if (use_old_encoding) - { - type2tc nullptrtype = pointer_type2tc(type); - expr2tc null_ptr = symbol2tc(nullptrtype, "NULL"); pointer_guard = same_object2tc(deref_expr, null_ptr); - } else - { pointer_guard = same_object2tc(deref_expr, gen_nil()); - } - guardt tmp_guard(guard); tmp_guard.add(pointer_guard); @@ -709,10 +692,8 @@ expr2tc dereferencet::build_reference_to( // solver will only get confused. return value; } - if ((is_constant_intloc2t(object) || - is_constant_intheap2t(object) || - is_null_object2t(root_object)) && - (is_free(mode) || is_internal(mode))) + + if (is_null_object2t(root_object) && (is_free(mode) || is_internal(mode))) { // Freeing NULL is completely legit according to C return value; @@ -833,23 +814,29 @@ expr2tc dereferencet::build_reference_to( lexical_offset->dump(); guardt tmp_guard(guard); - if (!is_intheap_type(value) || - !to_intheap_type(value->type).is_region) + if (!is_intheap_type(value) && + !is_pointer_type(value) && + !is_intloc_type(value)) { - log_error("Not heap region"); + log_error("Do not support this tpye"); + value->dump(); abort(); } - intheap_type2t &_type = to_intheap_type(value->type); - - if (!is_free(mode) && !is_internal(mode)) + if (is_intheap_type(value)) { - int access_sz = type->get_width() / 8; - // Do alignment - bool has_changed = _type.do_alignment(access_sz); - if (has_changed) - dereference_callback.update_heap_type(_type); + intheap_type2t &_type = to_intheap_type(value->type); + + if (!is_free(mode) && !is_internal(mode)) + { + int access_sz = type->get_width() / 8; + // Do alignment + bool has_changed = _type.do_alignment(access_sz); + if (has_changed) + dereference_callback.update_heap_type(_type); + } } + pointer_guard = same_object2tc(deref_expr, location_of2tc(value)); tmp_guard.add(pointer_guard); @@ -883,7 +870,6 @@ expr2tc dereferencet::build_reference_to( off->dump(); log_status("after renaming"); off->dump(); - final_offset = to_locadd2t(off).get_offset(); } else @@ -1247,9 +1233,9 @@ void dereferencet::build_deref_slhv( { log_status(" ----------------- build deref slhv ----------------- "); value->dump(); - guard.dump(); - offset->dump(); - type->dump(); + // guard.dump(); + // offset->dump(); + // type->dump(); if (!is_scalar_type(type)) { @@ -1263,36 +1249,43 @@ void dereferencet::build_deref_slhv( abort(); } - // value is the flag symbol of a heap region - expr2tc &heap_region = value; + if (is_intheap_type(value)) + { + expr2tc &heap_region = value; - unsigned int field = to_constant_int2t(offset).value.to_uint64(); - intheap_type2t &_type = to_intheap_type(heap_region->type); - unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); + unsigned int field = to_constant_int2t(offset).value.to_uint64(); + intheap_type2t &_type = to_intheap_type(heap_region->type); + unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); - if (!_type.is_aligned) - { - log_error("heap region must be aligned"); - abort(); + if (!_type.is_aligned) + { + log_error("heap region must be aligned"); + abort(); + } + + bool is_field = true; + if (field >= _type.field_types.size() || + access_sz != _type.total_bytes / _type.field_types.size()) + { + // Out of bound or unaligned - undefined behavior + expr2tc sym = symbol2tc( + type, + dereference_callback.get_nondet_id("undefined_behavior_var")); + value = sym; + is_field = false; + } + else + value = field_of2tc(type, value, gen_ulong(field)); + + // update field type + if (is_field && _type.set_field_type(field, type)) + dereference_callback.update_heap_type(_type); } - - bool is_field = true; - if (field >= _type.field_types.size() || - access_sz != _type.total_bytes / _type.field_types.size()) + else { - // Out of bound or unaligned - undefined behavior - expr2tc sym = symbol2tc( - type, - dereference_callback.get_nondet_id("undefined_behavior_var")); - value = sym; - is_field = false; + // pointer - return itself } - else - value = field_of2tc(type, value, gen_ulong(field)); - - // update field type - if (is_field && _type.set_field_type(field, type)) - dereference_callback.update_heap_type(_type); + log_status("return dereference --->"); value->dump(); @@ -2560,30 +2553,39 @@ void dereferencet::check_heap_region_access( { // This check is in word-level; - log_status(" ------------------ check heap region access ------------------ "); - value->dump(); - offset->dump(); - type->dump(); - guard.dump(); + // log_status(" ------------------ check heap region access ------------------ "); + // value->dump(); + // offset->dump(); + // type->dump(); + // guard.dump(); - const heap_region2t& heap_region = to_heap_region2t(value); - const intheap_type2t &_type = to_intheap_type(heap_region.type); + expr2tc offset_cond; + if (is_intheap_type(value)) + { + const heap_region2t& heap_region = to_heap_region2t(value); + const intheap_type2t &_type = to_intheap_type(heap_region.type); - if (!_type.is_aligned) + if (!_type.is_aligned) + { + log_error("heap region must be aligned"); + abort(); + } + + expr2tc size = gen_ulong(_type.field_types.size()); + offset_cond = + and2tc( + greaterthanequal2tc(offset, gen_ulong(0)), + lessthanequal2tc(offset, size) + ); + } + else { - log_error("heap region must be aligned"); - abort(); + // pointer + offset_cond = equality2tc(offset, gen_ulong(0)); } - expr2tc size = gen_ulong(_type.field_types.size()); - expr2tc offset_cond = - and2tc( - greaterthanequal2tc(offset, gen_ulong(0)), - lessthanequal2tc(offset, size) - ); - - log_status("offset condition:"); - offset_cond->dump(); + // log_status("offset condition:"); + // offset_cond->dump(); expr2tc bound_check = not2tc(offset_cond); if(!options.get_bool_option("no-bounds-check")) @@ -2597,7 +2599,7 @@ void dereferencet::check_heap_region_access( ); } - log_status(" ------------------ check heap region access ------------------ "); + // log_status(" ------------------ check heap region access ------------------ "); } void dereferencet::check_alignment( diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index f6a538bc..1fc0c747 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -559,8 +559,12 @@ void value_sett::get_value_set_rec( { make_union(dest, v_it->second.object_map); log_status("points to somthing"); + int i = 0; for (auto obj : dest) + { + log_status("item - {} : ", i++); object_numbering[obj.first]->dump(); + } return; } else @@ -568,11 +572,21 @@ void value_sett::get_value_set_rec( } // SLHV: - if (is_constant_intloc2t(expr) || is_constant_intheap2t(expr) || + + + if (is_heap_update2t(expr) || is_points_to2t(expr) || + is_heap_region2t(expr) || is_constant_intheap2t(expr) || is_heap_append2t(expr) || is_heap_delete2t(expr)) { - expr2tc new_object = expr; - insert(dest, new_object, BigInt(0)); + log_status("do not support get_value_set_rec"); + expr->dump(); + abort(); + } + + if (is_constant_intloc2t(expr) ) + { + expr2tc null_obj = null_object2tc(get_intloc_type()); + insert(dest, null_obj, BigInt(0)); return; } @@ -611,10 +625,11 @@ void value_sett::get_value_set_rec( if (is_location_of2t(expr)) { - get_value_set_rec( - to_location_of2t(expr).source_heap, - dest, suffix, original_type - ); + // TODO : maybe we should introduce reference + const location_of2t &loc_of = to_location_of2t(expr); + expr2tc new_obj = loc_of.source_heap; + + insert(dest, new_obj, BigInt(0)); return; } @@ -641,14 +656,6 @@ void value_sett::get_value_set_rec( return; } - if (is_heap_update2t(expr) || is_points_to2t(expr) || - is_heap_region2t(expr)) - { - expr->dump(); - log_status("fini get_value_set_rec heap_update"); - abort(); - } - if (is_add2t(expr) || is_sub2t(expr)) { // Consider pointer arithmetic. This takes takes the form of finding the @@ -827,7 +834,6 @@ void value_sett::get_value_set_rec( get_expr_id(expr), get_type_id(expr->type)); expr2tc tmp = unknown2tc(original_type); - expr->dump(); insert(dest, tmp, BigInt(0)); } @@ -1257,28 +1263,14 @@ void value_sett::assign( return; } - if (is_intheap_type(lhs_type) && !is_constant_intheap2t(rhs)) + if (is_intheap_type(lhs_type)) { - if (is_heap_region2t(rhs)) - { - // heap region is created for encoding - // the heap variable lhs contains all information - expr2tc new_obj = to_heap_region2t(rhs).flag; - object_mapt values_rhs; - // flag contains all neccessary information - insert(values_rhs, new_obj, BigInt(0)); - assign_rec(lhs, values_rhs, "", add_to_sets); - return; - } - if (to_intheap_type(lhs_type).is_region) - { - if (!is_intheap_type(rhs->type) || - !to_intheap_type(rhs->type).is_region) - { - log_error("Wrong assignment for heap variable"); - abort(); - } + // Heap varialbes perform as array variable. + // We only update its fields that are pointers + if ((is_heap_update2t(rhs) || is_symbol2t(rhs)) + && to_intheap_type(rhs->type).is_region) + { unsigned int _field = -1; expr2tc rhs_heap; type2tc rhs_type; @@ -1318,6 +1310,7 @@ void value_sett::assign( const intheap_type2t &_lhs_type = to_intheap_type(lhs->type); const intheap_type2t &_rhs_type = to_intheap_type(rhs_type); + // copy other fields for (unsigned int i = 0; i < _lhs_type.field_types.size(); i++) { if (i == _field) continue; @@ -1334,9 +1327,8 @@ void value_sett::assign( assign(lhs_field, rhs_field, false); } - - return; } + return; } // basic type diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 452b6393..8ebb94f4 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -242,9 +242,30 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::location_of_id: { const location_of2t &locof = to_location_of2t(expr); - const expr2tc &heap_region = locof.source_heap; - const intheap_type2t &_type = to_intheap_type(heap_region->type); - return convert_ast(_type.location); + + smt_astt loc; + if (is_intheap_type(locof.source_heap)) + { + const expr2tc &heap_region = locof.source_heap; + const intheap_type2t &_type = to_intheap_type(heap_region->type); + loc = convert_ast(_type.location); + } + else if (is_pointer_type(locof.source_heap) || + is_intloc_type(locof.source_heap)) + { + if (!is_symbol2t(locof.source_heap)) + { + log_error("Do not support yet"); + locof.source_heap->dump(); + abort(); + } + + std::string loc_name = + to_symbol2t(locof.source_heap).get_symbol_name() + std::string("_LOC_"); + + loc = mk_smt_symbol(loc_name, mk_intloc_sort()); + } + return loc; } case expr2t::points_to_id: { @@ -395,7 +416,9 @@ z3_slhv_convt::convert_slhv_opts( smt_astt z3_slhv_convt::project(const expr2tc &expr) { - if (is_symbol2t(expr)) + if (is_constant_intloc2t(expr)) + return mk_nil(); + else if (is_symbol2t(expr)) { if (is_intheap_type(expr)) { @@ -417,6 +440,14 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) return this->project(to_typecast2t(expr).from); else if (is_locadd2t(expr)) return this->project(to_locadd2t(expr).location); + else if (is_if2t(expr)) + { + const if2t &_if = to_if2t(expr); + smt_astt cond = convert_ast(_if.cond); + smt_astt t = this->project(_if.true_value); + smt_astt f = this->project(_if.true_value); + return mk_ite(cond, t, f); + } else { log_error("Do not support project"); diff --git a/src/util/simplify_expr2.cpp b/src/util/simplify_expr2.cpp index 88eaa554..3780b28a 100644 --- a/src/util/simplify_expr2.cpp +++ b/src/util/simplify_expr2.cpp @@ -23,6 +23,10 @@ expr2tc expr2t::simplify() const if (expr_id == address_of_id) // unlikely return expr2tc(); + // Similar to addressof + if (expr_id == location_of_id) + return expr2tc(); + // And overflows too. We don't wish an add to distribute itself, for example, // when we're trying to work out whether or not it's going to overflow. if (expr_id == overflow_id) From ec34794cc6dc122049ea327fd235873e188a488a Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 7 Sep 2024 14:58:24 +0800 Subject: [PATCH 071/126] fix offset for object field_of --- benchmark/case_2.c | 4 +- src/goto-symex/symex_assign.cpp | 28 +- src/goto-symex/symex_dereference.cpp | 6 - src/irep2/irep2_expr.h | 13 +- src/irep2/templates/irep2_templates.cpp | 2 +- .../templates/irep2_templates_expr_data.cpp | 2 +- src/pointer-analysis/dereference.cpp | 32 -- src/pointer-analysis/value_set.cpp | 16 +- src/solvers/smt/smt_casts.cpp | 4 + src/solvers/smt/smt_conv.cpp | 6 +- src/solvers/smt/smt_conv.h | 4 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 284 +++++++++++++++++- src/solvers/z3-slhv/z3_slhv_conv.h | 8 + src/util/migrate.cpp | 1 - 14 files changed, 317 insertions(+), 93 deletions(-) diff --git a/benchmark/case_2.c b/benchmark/case_2.c index cc2ee261..011b937a 100644 --- a/benchmark/case_2.c +++ b/benchmark/case_2.c @@ -1,7 +1,7 @@ #include typedef struct { void *lo; - int hi; + void *hi; } TData; int main(){ @@ -12,7 +12,7 @@ int main(){ pdata->lo = malloc(16); pdata->hi = malloc(24); void *lo = pdata->lo; - int hi = pdata->hi; + void *hi = pdata->hi; if(lo == hi){ free(lo); free(hi); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index b1f35e30..fafa6507 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -213,11 +213,6 @@ void goto_symext::symex_assign( replace_nondet(lhs); replace_nondet(rhs); - log_status("symex assign lhs : ------------- "); - lhs->dump(); - log_status("symex assign rhs : ------------- "); - rhs->dump(); - intrinsic_races_check_dereference(lhs); log_status("dereference lhs write"); dereference(lhs, dereferencet::WRITE); @@ -229,7 +224,7 @@ void goto_symext::symex_assign( replace_dynamic_allocation(rhs); log_status("replace done"); - log_status("after deref and replace : =-===="); + log_status("after deref and replace -------------"); lhs->dump(); rhs->dump(); @@ -289,10 +284,6 @@ void goto_symext::symex_assign( } } - log_status("before symex assign rec : =-===="); - lhs->dump(); - rhs->dump(); - guardt g(guard); // NOT the state guard! symex_assign_rec(lhs, original_lhs, rhs, expr2tc(), g, hidden_ssa); log_status("xxxxxxxxxxxx symex assign: done for this step"); @@ -1104,10 +1095,16 @@ type2tc goto_symext::create_heap_region_type( _heap_type.total_bytes = bytes; const struct_type2t &_type = to_struct_type(type); _heap_type.field_types.clear(); - for(auto inner_type : _type.get_structure_members()) + const std::vector &inner_types = _type.get_structure_members(); + const std::vector &inner_field_names = _type.get_structure_member_names(); + for (unsigned int i = 0; i < inner_field_names.size(); i++) + { + const std::string &field_name = inner_field_names[i].as_string(); + if (field_name.find("anon_pad") != std::string::npos) continue; _heap_type.field_types.push_back( - is_pointer_type(inner_type) ? get_intloc_type() : get_int64_type() + is_pointer_type(inner_types[i]) ? get_intloc_type() : get_int64_type() ); + } } return heap_type; @@ -1141,8 +1138,6 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla { expr2tc op = effect.operand; cur_state->rename(op); - log_status("malloc size:"); - op->dump(); do_simplify(op); if (!is_constant_int2t(op)) { @@ -1152,12 +1147,13 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla bytes = to_constant_int2t(op).value.to_uint64(); } + log_status("malloc size : {}", bytes); + type2tc heap_type = create_heap_region_type(type, bytes, base_loc); flag->type = heap_type; log_status(" ======= create a heap region ========== "); - - return heap_region2tc(heap_type, flag, base_loc); + return heap_region2tc(heap_type, base_loc); } void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 8801d3c2..d5e28b7a 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -204,12 +204,6 @@ void symex_dereference_statet::update_heap_type_rec( if (to_symbol2t(_type.location).get_symbol_name() == to_symbol2t(type.location).get_symbol_name()) expr->type = intheap_type2tc(type); - - if (is_heap_region2t(expr)) - { - heap_region2t &heap_region = to_heap_region2t(expr); - update_heap_type_rec(heap_region.flag, type); - } } else { diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 77422fd8..a5d12c6e 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -987,22 +987,18 @@ class heap_region_data : public expr2t heap_region_data( const type2tc &t, datatype_ops::expr_ids id, - const expr2tc &f, - const expr2tc &sl) - : expr2t(t, id), flag(f), source_location(sl) + const expr2tc &l) + : expr2t(t, id), source_location(l) { } heap_region_data(const heap_region_data& ref) = default; - expr2tc flag; expr2tc source_location; // Type mangling: - typedef esbmct::field_traits - flag_field; typedef esbmct::field_traits source_location_field; - typedef esbmct::expr2t_traits traits; + typedef esbmct::expr2t_traits traits; }; class heap_ops : public expr2t @@ -3220,9 +3216,8 @@ class heap_region2t : public heap_region_expr_methods public: heap_region2t( const type2tc &type, - const expr2tc &flag, const expr2tc &source_location) - : heap_region_expr_methods(type, heap_region_id, flag, source_location) + : heap_region_expr_methods(type, heap_region_id, source_location) { } heap_region2t(const heap_region2t &ref) = default; diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index e4cf28b9..7d095045 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -169,7 +169,7 @@ std::string uplus2t::field_names[esbmct::num_type_fields] = std::string locadd2t::field_names[esbmct::num_type_fields] = {"location", "offset", "", "", ""}; std::string heap_region2t::field_names[esbmct::num_type_fields] = - {"flag", "source_location", "", "", ""}; + {"source_location", "", "", "", ""}; std::string location_of2t::field_names[esbmct::num_type_fields] = {"source_region", "", "", "", ""}; std::string field_of2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 014f26c8..c0d743ef 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -60,4 +60,4 @@ expr_typedefs3(extract, extract_data); expr_typedefs2(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); -expr_typedefs3(heap_region, heap_region_data); \ No newline at end of file +expr_typedefs2(heap_region, heap_region_data); \ No newline at end of file diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 43fce212..8e1f3be5 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -141,8 +141,6 @@ const expr2tc &dereferencet::get_symbol(const expr2tc &expr) void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) { - log_status("deref expr:"); - expr->dump(); if (!has_dereference(expr)) return; @@ -158,8 +156,6 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) break; case expr2t::dereference_id: { - log_status("dereference expr: dereference id"); - expr->dump(); /* Interpret an actual dereference expression. First dereferences the * pointer expression, then dereferences the pointer itself, and stores the * result in 'expr'. */ @@ -363,8 +359,6 @@ expr2tc dereferencet::dereference_expr_nonscalar( modet mode, const expr2tc &base) { - log_status("deref expr nonscalar"); - expr->dump(); if (is_dereference2t(expr)) { /* The first expression we're called with is index2t, member2t or non-scalar @@ -487,8 +481,6 @@ expr2tc dereferencet::dereference( src = typecast2tc(pointer_type2tc(get_empty_type()), src); type2tc type = ns.follow(to_type); - log_status("dereference type:"); - type->dump(); // collect objects dest may point to value_setst::valuest points_to_set; @@ -496,7 +488,6 @@ expr2tc dereferencet::dereference( log_status("---- value set for "); src->dump(); dereference_callback.get_value_set(src, points_to_set); - log_status("---- value set: {} items", points_to_set.size()); log_status("get value set done --------------------"); /* If the value-set contains unknown or invalid, we cannot be sure it contains @@ -806,10 +797,6 @@ expr2tc dereferencet::build_reference_to( } else { value = object; - log_status("before building pointer guard"); - value->dump(); - deref_expr->dump(); - type->dump(); if (!is_nil_expr(lexical_offset)) lexical_offset->dump(); @@ -840,15 +827,10 @@ expr2tc dereferencet::build_reference_to( pointer_guard = same_object2tc(deref_expr, location_of2tc(value)); tmp_guard.add(pointer_guard); - log_status("generated pointer guard:"); - pointer_guard->dump(); - // Check that the object we're accessing is actually alive and valid for this // mode. valid_check(value, tmp_guard, mode); - log_status("finish checking"); - // Don't do anything further if we're freeing things if (is_free(mode)) return expr2tc(); @@ -863,13 +845,9 @@ expr2tc dereferencet::build_reference_to( { if (is_locadd2t(deref_expr)) { - log_status("get offset from locadd by renaming"); expr2tc locadd = deref_expr; dereference_callback.rename(locadd); expr2tc off = to_locadd2t(locadd).get_offset(); - off->dump(); - log_status("after renaming"); - off->dump(); final_offset = to_locadd2t(off).get_offset(); } else @@ -886,9 +864,6 @@ expr2tc dereferencet::build_reference_to( final_offset = add2tc(final_offset->type, final_offset, lexical_offset); simplify(final_offset); - log_status("final offset : "); - final_offset->dump(); - if (!is_constant_int2t(final_offset) && !is_symbol2t(final_offset)) { @@ -2281,9 +2256,6 @@ void dereferencet::valid_check( const guardt &guard, modet mode) { - log_status("entering valid check"); - object->dump(); - const expr2tc &symbol = get_symbol(object); if (is_constant_string2t(symbol)) @@ -2303,11 +2275,7 @@ void dereferencet::valid_check( } else if(is_intheap_type(symbol)) { - log_status("guard : "); - guard.dump(); expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); - log_status("not valid print:"); - not_valid_heap_region->dump(); guardt tmp_guard(guard); tmp_guard.add(not_valid_heap_region); std::string foo = is_free(mode) ? "invalid free pointer" diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 1fc0c747..02ffee12 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -626,10 +626,18 @@ void value_sett::get_value_set_rec( if (is_location_of2t(expr)) { // TODO : maybe we should introduce reference - const location_of2t &loc_of = to_location_of2t(expr); - expr2tc new_obj = loc_of.source_heap; - - insert(dest, new_obj, BigInt(0)); + const location_of2t &locof = to_location_of2t(expr); + expr2tc new_obj = locof.source_heap; + BigInt off(0); + + if (is_field_of2t(locof.source_heap)) + { + const field_of2t &fieldof = to_field_of2t(locof.source_heap); + new_obj = fieldof.source_heap; + off = to_constant_int2t(fieldof.operand).value; + } + + insert(dest, new_obj, off); return; } diff --git a/src/solvers/smt/smt_casts.cpp b/src/solvers/smt/smt_casts.cpp index 6e82338d..24031213 100644 --- a/src/solvers/smt/smt_casts.cpp +++ b/src/solvers/smt/smt_casts.cpp @@ -650,6 +650,10 @@ smt_astt smt_convt::convert_typecast(const expr2tc &expr) { const typecast2t &cast = to_typecast2t(expr); + if (is_intloc_type(cast.from->type) && is_pointer_type(cast.type) || + is_pointer_type(cast.from->type) && is_intloc_type(cast.type)) + return convert_ast(cast.from); + if ( int_encoding && is_floatbv_type(cast.from->type) && is_floatbv_type(cast.type)) diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index c50cd3ef..8a4985ec 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -232,11 +232,6 @@ smt_astt smt_convt::convert_assign(const expr2tc &expr) smt_cache_entryt e = {eq.side_1, side2, ctx_level}; smt_cache.insert(e); - log_status(" ----------------- assignment result ----------------- "); - side1->dump(); - side2->dump(); - log_status(" ----------------- assignment result ----------------- "); - return side2; } @@ -318,6 +313,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) case expr2t::pointer_object_id: case expr2t::pointer_capability_id: + case expr2t::location_of_id: case expr2t::field_of_id: case expr2t::heap_region_id: case expr2t::heap_update_id: diff --git a/src/solvers/smt/smt_conv.h b/src/solvers/smt/smt_conv.h index 25c67352..5eb3e0e5 100644 --- a/src/solvers/smt/smt_conv.h +++ b/src/solvers/smt/smt_conv.h @@ -187,7 +187,7 @@ class smt_convt * * @param expr The expression to convert into the SMT solver * @return The resulting handle to the SMT value. */ - smt_astt convert_ast(const expr2tc &expr); + virtual smt_astt convert_ast(const expr2tc &expr); /** Interface to specifig SMT conversion. * Takes one expression, and converts it into the underlying SMT solver, @@ -204,7 +204,7 @@ class smt_convt smt_astt const *args, struct expr_op_convert ops); - smt_astt convert_assign(const expr2tc &expr); + virtual smt_astt convert_assign(const expr2tc &expr); smt_astt make_n_ary_and(const ast_vec &v); smt_astt make_n_ary_or(const ast_vec &v); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 8ebb94f4..a803cbdc 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -43,7 +43,7 @@ smt_convt *create_new_z3_slhv_solver( } z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) - : z3_convt(_ns, _options) { + : z3_convt(_ns, _options), heap_state(mk_smt_bool(true)) { // initialize the z3 based slhv converter here int_encoding = true; solver = z3::solver(z3_ctx, "SLHV"); @@ -193,6 +193,238 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { } } +void z3_slhv_convt::collect_heap_state(smt_astt &a) +{ + if (to_solver_smt_ast(heap_state)->a.is_true()) + return; + smt_astt simp = + new_ast( + to_solver_smt_ast(heap_state)->a.simplify(), + mk_bool_sort() + ); + a = mk_and(simp, a); + heap_state = mk_smt_bool(true); +} + +smt_astt z3_slhv_convt::convert_assign(const expr2tc &expr) +{ + const equality2t &eq = to_equality2t(expr); + smt_astt side1 = convert_ast(eq.side_1); // LHS + smt_astt side2 = convert_ast(eq.side_2); // RHS + + smt_astt a = mk_eq(side1, side2); + collect_heap_state(a); + assert_ast(a); + + // Put that into the smt cache, thus preserving the value of the assigned symbols. + // IMPORTANT: the cache is now a fundamental part of how some flatteners work, + // in that one can choose to create a set of expressions and their ASTs, then + // store them in the cache, rather than have a more sophisticated conversion. + smt_cache_entryt e = {eq.side_1, a, ctx_level}; + smt_cache.insert(e); + + return side2; +} + +smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) +{ + log_status("------------------------------- convert ast -----------------------------"); + expr->dump(); + log_status("-------------------------------------------------------------------------"); + + smt_cachet::const_iterator cache_result = smt_cache.find(expr); + if (cache_result != smt_cache.end()) { + log_status("found!!!!!!!!"); + cache_result->ast->dump(); + return (cache_result->ast); + } + + std::vector args; + args.reserve(expr->get_num_sub_exprs()); + + switch (expr->expr_id) + { + case expr2t::pointer_object_id: + case expr2t::same_object_id: + + case expr2t::constant_intloc_id: + case expr2t::constant_intheap_id: + case expr2t::location_of_id: + case expr2t::field_of_id: + case expr2t::heap_region_id: + case expr2t::heap_update_id: + case expr2t::heap_delete_id: + break; // Don't convert their operands + + default: + { + // Convert all the arguments and store them in 'args'. + unsigned int i = 0; + expr->foreach_operand( + [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); + log_status(" -------------- convert args finished ------------ "); + for (int i = 0; i < expr->get_num_sub_exprs(); i++) { + args[i]->dump(); + } + log_status(" -------------- convert args finished ------------ "); + } + } + + log_status("begin convert expr"); + expr->dump(); + + smt_astt a; + switch (expr->expr_id) + { + case expr2t::constant_intheap_id: + case expr2t::constant_intloc_id: + case expr2t::heap_region_id: + case expr2t::location_of_id: + case expr2t::field_of_id: + case expr2t::points_to_id: + case expr2t::uplus_id: + case expr2t::locadd_id: + case expr2t::heap_update_id: + case expr2t::heap_contain_id: + case expr2t::heap_append_id: + case expr2t::heap_delete_id: + { + a = convert_slhv_opts(expr, args); + break; + } + + case expr2t::constant_int_id: + case expr2t::constant_bool_id: + case expr2t::symbol_id: + { + a = convert_terminal(expr); + break; + } + case expr2t::add_id: + { + const add2t &add = to_add2t(expr); + a = mk_add(args[0], args[1]); + break; + } + case expr2t::sub_id: + { + const sub2t &sub = to_sub2t(expr); + a = mk_sub(args[0], args[1]); + break; + } + case expr2t::same_object_id: + { + const same_object2t& so = to_same_object2t(expr); + args[0] = this->project(so.side_1); + args[1] = this->project(so.side_2); + a = mk_eq(args[0], args[1]); + break; + } + case expr2t::pointer_object_id: + { + const pointer_object2t &obj = to_pointer_object2t(expr); + const expr2tc *ptr = &obj.ptr_obj; + + args[0] = convert_ast(*ptr); + a = args[0]; + break; + } + case expr2t::typecast_id: + { + a = convert_typecast(expr); + break; + } + case expr2t::if_id: + { + // Only attempt to handle struct.s + const if2t &if_ref = to_if2t(expr); + args[0] = convert_ast(if_ref.cond); + args[1] = convert_ast(if_ref.true_value); + args[2] = convert_ast(if_ref.false_value); + a = args[1]->ite(this, args[0], args[2]); + break; + } + case expr2t::equality_id: + { + auto eq = to_equality2t(expr); + a = args[0]->eq(this, args[1]); + break; + } + case expr2t::notequal_id: + { + auto neq = to_notequal2t(expr); + a = args[0]->eq(this, args[1]); + a = mk_not(a); + break; + } + case expr2t::lessthan_id: + { + const lessthan2t < = to_lessthan2t(expr); + a = mk_lt(args[0], args[1]); + break; + } + case expr2t::lessthanequal_id: + { + const lessthanequal2t <e = to_lessthanequal2t(expr); + a = mk_le(args[0], args[1]); + break; + } + case expr2t::greaterthan_id: + { + const greaterthan2t > = to_greaterthan2t(expr); + a = mk_gt(args[0], args[1]); + break; + } + case expr2t::greaterthanequal_id: + { + const greaterthanequal2t >e = to_greaterthanequal2t(expr); + // Pointer relation: + a = mk_ge(args[0], args[1]); + break; + } + case expr2t::implies_id: + { + a = mk_implies(args[0], args[1]); + break; + } + case expr2t::not_id: + { + assert(is_bool_type(expr)); + a = mk_not(args[0]); + break; + } + case expr2t::neg_id: + { + const neg2t &neg = to_neg2t(expr); + a = mk_neg(args[0]); + break; + } + case expr2t::and_id: + { + a = mk_and(args[0], args[1]); + break; + } + case expr2t::or_id: + { + a = mk_or(args[0], args[1]); + break; + } + default: + log_error("Couldn't convert expression in unrecognised format\n{}", *expr); + abort(); + } + + if (is_bool_type(expr->type)) collect_heap_state(a); + + struct smt_cache_entryt entry = {expr, a, ctx_level}; + smt_cache.insert(entry); + + log_status("==== converted reuslt: "); + a->dump(); + log_status("===="); + return a; +} + smt_astt z3_slhv_convt::convert_slhv_opts( const expr2tc &expr, const std::vector& args) @@ -250,21 +482,38 @@ z3_slhv_convt::convert_slhv_opts( const intheap_type2t &_type = to_intheap_type(heap_region->type); loc = convert_ast(_type.location); } - else if (is_pointer_type(locof.source_heap) || - is_intloc_type(locof.source_heap)) + else if (is_symbol2t(locof.source_heap) && + (is_pointer_type(locof.source_heap) || + is_intloc_type(locof.source_heap))) { - if (!is_symbol2t(locof.source_heap)) - { - log_error("Do not support yet"); - locof.source_heap->dump(); - abort(); - } - std::string loc_name = to_symbol2t(locof.source_heap).get_symbol_name() + std::string("_LOC_"); - loc = mk_smt_symbol(loc_name, mk_intloc_sort()); } + else if (is_field_of2t(locof.source_heap)) + { + const field_of2t &fieldof = to_field_of2t(locof.source_heap); + if(!is_intheap_type(fieldof.source_heap->type) || + !to_intheap_type(fieldof.source_heap->type).is_region || + is_nil_expr(to_intheap_type(fieldof.source_heap->type).location)) + { + log_status("Incomplete intheap type for field of"); + fieldof.dump(); + abort(); + } + + const intheap_type2t &_type = to_intheap_type(fieldof.source_heap->type); + loc = mk_locadd( + convert_ast(_type.location), + convert_ast(fieldof.operand) + ); + } + else + { + log_error("Do not support yet"); + locof.source_heap->dump(); + abort(); + } return loc; } case expr2t::points_to_id: @@ -349,7 +598,12 @@ z3_slhv_convt::convert_slhv_opts( } smt_astt v1 = mk_fresh(s1, name); - assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region))); + // assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region))); + heap_state = + mk_and( + heap_state, + mk_subh(mk_pt(loc, v1), convert_ast(heap_region)) + ); return v1; } case expr2t::heap_update_id: @@ -379,7 +633,8 @@ z3_slhv_convt::convert_slhv_opts( // current heap state smt_astt old_state = mk_uplus(h1, mk_pt(loc, v1)); - assert_ast(mk_eq(h, old_state)); + // assert_ast(mk_eq(h, old_state)); + heap_state = mk_and(heap_state, mk_eq(h, old_state)); // new heap state smt_astt new_state = mk_uplus(h1, mk_pt(loc, val)); @@ -395,7 +650,8 @@ z3_slhv_convt::convert_slhv_opts( smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); + // assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); + heap_state = mk_and(heap_state, mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); return h1; } case expr2t::same_object_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 611096fa..583e616c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -39,6 +39,11 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_smt_symbol(const std::string &name, smt_sortt s) override; smt_sortt convert_slhv_sorts(const type2tc &type) override; + + // To support encoding heap state, we override default convert + smt_astt convert_ast(const expr2tc &expr) override; + smt_astt convert_assign(const expr2tc &expr); + smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; @@ -47,8 +52,11 @@ class z3_slhv_convt : public z3_convt { void dump_smt() override; private: + void collect_heap_state(smt_astt &a); void print_smt_formulae(std::ostream& dest); + std::vector assertions; + smt_astt heap_state; }; #endif \ No newline at end of file diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index c429d4a7..61510cf2 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2640,7 +2640,6 @@ exprt migrate_expr_back(const expr2tc &ref) const heap_region2t &ref2 = to_heap_region2t(ref); typet thetype = migrate_type_back(ref->type); exprt region("heap_region", thetype); - region.copy_to_operands(migrate_expr_back(ref2.flag)); region.copy_to_operands(migrate_expr_back(ref2.source_location)); return region; } From eeb61f152ecc156179232ae133daf7d98ebf36ba Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 7 Sep 2024 17:10:53 +0800 Subject: [PATCH 072/126] fix symex free ptr(not finish) --- src/goto-symex/builtin_functions.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index b5f34069..f06bbb29 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -362,10 +362,6 @@ void goto_symext::symex_free(const expr2tc &expr) for (auto const &item : internal_deref_items) { - log_status("internal deref item: "); - item.object->dump(); - log_status("offset: "); - item.offset->dump(); guardt g = cur_state->guard; g.add(item.guard); @@ -414,19 +410,24 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(valid_index_expr, falsity), true); } else { expr2tc free_ptr = code.operand; + dereference(free_ptr, dereferencet::READ); + expr2tc when = gen_false_expr(); - // set each heap region to empty, guarded by item.gurad for(auto const& item : internal_deref_items) { - assert(is_intheap_type(item.object)); - log_status("free object guard"); - item.guard->dump(); + if (!is_intheap_type(item.object)) + { + log_status("Wrong object to be freed"); + item.object->dump(); + abort(); + } + // Maybe not ok to set emp for a freed object guardt g; g.add(item.guard); symex_assign(code_assign2tc(item.object, gen_emp()), false, g); // collect guards for deleting heap alloc size - when = or2tc(when, item.guard); + when = or2tc(when, guard); } // delete the pointer in alloc_size heap expr2tc alloc_size_heap = symbol2tc(get_intheap_type(), alloc_size_heap_name); From f152f9bc6a170b8a4b6e610f935aa2edc6bc9681 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 9 Sep 2024 20:42:50 +0800 Subject: [PATCH 073/126] use heapvar = emp to encode valid object --- src/goto-symex/builtin_functions.cpp | 12 +++++++++++- src/goto-symex/dynamic_allocation.cpp | 15 ++------------- src/goto-symex/symex_assign.cpp | 3 +-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index f06bbb29..c4b381c0 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -262,6 +262,7 @@ expr2tc goto_symext::symex_mem( log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); + // only used for invalid pointer // link pointer variable and heap variable log_status("track new pointer - {}", to_symbol2t(rhs_base_loc).get_symbol_name()); track_new_pointer( @@ -369,6 +370,14 @@ void goto_symext::symex_free(const expr2tc &expr) expr2tc offset = item.offset; expr2tc eq = equality2tc(offset, gen_ulong(0)); g.guard_expr(eq); + + log_status("check freed pointer offset"); + item.object->dump(); + item.offset->dump(); + eq->dump(); + g.as_expr()->dump(); + log_status("-------------"); + claim(eq, "Operand of free must have zero pointer offset"); // Check if we are not freeing an dynamic object allocated using alloca @@ -427,8 +436,9 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(item.object, gen_emp()), false, g); // collect guards for deleting heap alloc size - when = or2tc(when, guard); + when = or2tc(when, item.guard); } + // only used for invalid pointer // delete the pointer in alloc_size heap expr2tc alloc_size_heap = symbol2tc(get_intheap_type(), alloc_size_heap_name); expr2tc new_heap = heap_delete2tc(alloc_size_heap, free_ptr); diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 5ad473ed..5b02f3d7 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -40,18 +40,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) abort(); } - const intheap_type2t &_type = to_intheap_type(heap_region->type); - // get alloc size heap - expr2tc alloc_size_heap; - migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); - - expr2tc size = gen_ulong(_type.total_bytes); - expr2tc heap_contain = - heap_contain2tc( - alloc_size_heap, - points_to2tc(_type.location, size) - ); - expr = heap_contain; + expr = not2tc(equality2tc(heap_region, gen_emp())); } } else if (is_invalid_pointer2t(expr)) @@ -95,7 +84,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { - log_status("replace invalid pointer"); + log_status("replace invalid pointer"); obj_expr->dump(); expr2tc alloc_size_heap; diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index fafa6507..f7f885a4 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -153,8 +153,7 @@ void goto_symext::symex_assign( if( (to_symbol2t(assign_target).get_symbol_name().compare(alloc_size_arr_name.as_string()) == 0) && is_constant_array_of2t(assign_source)) { - // construct the initialization code of allocsize heap in slhv - // and do the symbolic execution for it + // used to track valid pointer symbolt allocsize_heap; allocsize_heap.name = alloc_size_heap_name; allocsize_heap.id = alloc_size_heap_name; From caeeb897bdd98ec3ae73e3a907d0376ce124565f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 10 Sep 2024 14:02:41 +0800 Subject: [PATCH 074/126] turn assign with subh to disj --- src/goto-symex/builtin_functions.cpp | 8 --- src/goto-symex/goto_symex.h | 20 +++++++ src/goto-symex/slice.cpp | 20 +++++++ src/goto-symex/symex_assign.cpp | 73 ++++++++++++++++++++---- src/goto-symex/symex_target.h | 4 +- src/goto-symex/symex_target_equation.cpp | 16 +++++- src/goto-symex/symex_target_equation.h | 7 ++- 7 files changed, 122 insertions(+), 26 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index c4b381c0..470eccf8 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -370,14 +370,6 @@ void goto_symext::symex_free(const expr2tc &expr) expr2tc offset = item.offset; expr2tc eq = equality2tc(offset, gen_ulong(0)); g.guard_expr(eq); - - log_status("check freed pointer offset"); - item.object->dump(); - item.offset->dump(); - eq->dump(); - g.as_expr()->dump(); - log_status("-------------"); - claim(eq, "Operand of free must have zero pointer offset"); // Check if we are not freeing an dynamic object allocated using alloca diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 830eb3d8..5ad203dc 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -868,6 +868,26 @@ class goto_symext */ void symex_nondet(const expr2tc &lhs, const expr2tc &effect); + /** + * @brief Check whether an expr has field_of, heap_update or heap_delete + * + * @param expr + * @return true + * @return false + */ + bool has_cond_expr(const expr2tc &expr); + + /** + * @brief Transfer v = (ite cond v1 v2) to (ite cond (= v v1) (= v v2) + * where has_cond_expr(v1) || has_cond_expr(v2) holds. + * + * @param expr + * @param cond + * @param lhs + * @return expr2tc + */ + expr2tc transfer_to_assume(const expr2tc &expr, const expr2tc &cond, const expr2tc &lhs); + /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 88aae453..477c0ecc 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -40,6 +40,26 @@ void symex_slicet::run_on_assert(symex_target_equationt::SSA_stept &SSA_step) void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) { + if (SSA_step.is_assign_to_assume) + { + if (!get_symbols(SSA_step.lhs)) + { + // we don't really need it + SSA_step.ignore = true; + ++sliced; + log_debug( + "slice", + "slice ignoring assignment to symbol {}", + to_symbol2t(SSA_step.lhs).get_symbol_name()); + } + else + { + get_symbols(SSA_step.cond); + depends.erase(to_symbol2t(SSA_step.lhs).get_symbol_name()); + } + return; + } + if (!slice_assumes) { get_symbols(SSA_step.guard); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index f7f885a4..053c4435 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -377,11 +377,6 @@ void goto_symext::symex_assign_symbol( if (!guard.is_true()) rhs = if2tc(rhs->type, guard.as_expr(), rhs, lhs); - log_status("lhs:"); - lhs->dump(); - log_status("rhs:"); - rhs->dump(); - cur_state->rename(rhs); do_simplify(rhs); @@ -394,15 +389,8 @@ void goto_symext::symex_assign_symbol( expr2tc renamed_lhs = lhs; cur_state->rename_type(renamed_lhs); - log_status("renamed lhs:"); - renamed_lhs->dump(); - log_status("renamed rhs:"); - rhs->dump(); - cur_state->assignment(renamed_lhs, rhs); - log_status("cur state assignment done!!!"); - // Special case when the lhs is an array access, we need to get the // right symbol for the index expr2tc new_lhs = full_lhs; @@ -412,6 +400,22 @@ void goto_symext::symex_assign_symbol( guardt tmp_guard(cur_state->guard); tmp_guard.append(guard); + if (has_cond_expr(rhs)) + { + // Transfer assignment to assume + expr2tc new_cond = transfer_to_assume(rhs, expr2tc(), renamed_lhs); + + target->assumption( + tmp_guard.as_expr(), + new_cond, + cur_state->source, + first_loop, + renamed_lhs, + true + ); + return; + } + // do the assignment target->assignment( tmp_guard.as_expr(), @@ -1185,4 +1189,49 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) } log_status(" ======== symex nondet ===== "); +} + +bool goto_symext::has_cond_expr(const expr2tc &expr) +{ + if (is_nil_expr(expr)) return false; + if (is_field_of2t(expr) || is_heap_update2t(expr) || + is_heap_delete2t(expr)) + return true; + + bool has_cond = false; + expr->foreach_operand([this, &has_cond](const expr2tc &e) { + has_cond |= has_cond_expr(e); + }); + + return has_cond; +} + +expr2tc goto_symext::transfer_to_assume( + const expr2tc &expr, const expr2tc &cond, const expr2tc &lhs) +{ + if (is_if2t(expr)) + { + const if2t &_if = to_if2t(expr); + + expr2tc true_cond, false_cond; + if (!is_nil_expr(cond)) + { + true_cond = and2tc(cond, _if.cond); + false_cond = and2tc(cond, not2tc(_if.cond)); + } + else + { + true_cond = _if.cond; + false_cond = not2tc(_if.cond); + } + + return or2tc( + transfer_to_assume(_if.true_value, true_cond, lhs), + transfer_to_assume(_if.false_value, false_cond, lhs) + ); + } + + // find the terminal valuew + expr2tc eq = equality2tc(lhs, expr); + return is_nil_expr(cond) ? eq : and2tc(cond, eq); } \ No newline at end of file diff --git a/src/goto-symex/symex_target.h b/src/goto-symex/symex_target.h index 643a85bc..4da2ac8f 100644 --- a/src/goto-symex/symex_target.h +++ b/src/goto-symex/symex_target.h @@ -59,7 +59,9 @@ class symex_targett const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number) = 0; + unsigned loop_number, + const expr2tc &lhs = expr2tc(), // use to assign-to_assume + const bool is_assign_to_assume = false) = 0; // record an assertion // cond is destroyed diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 62be9118..e3c2c829 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -73,7 +73,9 @@ void symex_target_equationt::assumption( const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number) + unsigned loop_number, + const expr2tc &lhs, + const bool is_assign_to_assume) { SSA_steps.emplace_back(); SSA_stept &SSA_step = SSA_steps.back(); @@ -83,6 +85,9 @@ void symex_target_equationt::assumption( SSA_step.type = goto_trace_stept::ASSUME; SSA_step.source = source; SSA_step.loop_number = loop_number; + SSA_step.is_assign_to_assume = is_assign_to_assume; + + if (is_assign_to_assume) SSA_step.lhs = lhs; if (debug_print) debug_print_step(SSA_step); @@ -226,7 +231,12 @@ void symex_target_equationt::convert_internal_step( assert(0 && "Unexpected SSA step type in conversion"); } - if (step.is_assert()) + if (step.is_assign_to_assume) + { + log_status("step is assign to assume"); + smt_conv.assert_ast(step.cond_ast); + } + else if (step.is_assert()) { log_status("step is_assert"); step.cond_ast = smt_conv.imply_ast(assumpt_ast, step.cond_ast); @@ -240,7 +250,7 @@ void symex_target_equationt::convert_internal_step( step.cond_ast->dump(); } - log_status("-------------- over -----------------"); + log_status("-------------- over -----------------"); } void symex_target_equationt::output(std::ostream &out) const diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index d6a669aa..b7673f3c 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -54,7 +54,9 @@ class symex_target_equationt : public symex_targett const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number) override; + unsigned loop_number, + const expr2tc &lhs = expr2tc(), + const bool is_assign_to_assume = false) override; // record an assertion // cond is destroyed @@ -129,6 +131,7 @@ class symex_target_equationt : public symex_targett // for ASSUME/ASSERT expr2tc cond; std::string comment; + bool is_assign_to_assume; // for OUTPUT std::string format_string; @@ -147,7 +150,7 @@ class symex_target_equationt : public symex_targett // for bidirectional search unsigned loop_number; - SSA_stept() : ignore(false), hidden(false) + SSA_stept() : ignore(false), hidden(false), is_assign_to_assume(false) { } From 58bc1574f37b1a288d3fe14c19f8352919b79646 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Tue, 10 Sep 2024 14:33:24 +0800 Subject: [PATCH 075/126] output truncate --- benchmark/case_0.c | 14 ++++++++++---- benchmark/case_1.c | 12 ++++++------ src/esbmc/bmc.cpp | 6 ++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index adaefcfb..d1fc3784 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -1,10 +1,16 @@ #include int main(){ - int * data = malloc(sizeof(int)); - int * data2 = malloc(2*sizeof(int)); - free(data); - int i = *(data + 1); + // int * data = malloc(sizeof(int)); + // int * data2 = malloc(2*sizeof(int)); + // free(data); + // int i = *(data + 1); + int *q = malloc(sizeof(int)); + int ** p = malloc(sizeof(int*)); + + *p = q; + **p = 100; + return 0; // int* j = NULL; // int* i = j; // // *(data + 1) = whatever; diff --git a/benchmark/case_1.c b/benchmark/case_1.c index 6d1a862e..da969dec 100644 --- a/benchmark/case_1.c +++ b/benchmark/case_1.c @@ -9,10 +9,10 @@ int main() { TData * p1 = malloc(sizeof(TData)); p1->lo = malloc(12); p1->hi = malloc(12); - void * p2; - int x; - if (x) p2 = p1->hi; - else p2 = p1->lo; - free(p2); - return 0; + // void * p2; + // int x; + // if (x) p2 = p1->hi; + // else p2 = p1->lo; + // free(p2); + // return 0; } diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 0d637092..42bd7486 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -628,8 +628,10 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) // show_vcc(*eq); // return smt_convt::P_SMTLIB; const std::string &output_file = options.get_option("output"); - if (!output_file.empty() && output_file != "-") - std::ofstream(output_file.c_str()) << ""; + if (!output_file.empty() && output_file != "-"){ + truncate(output_file.c_str(), 0); + } + // std::ofstream(output_file.c_str()) << ""; } if (result.remaining_claims == 0) From b110e855e46f9c8c4a007006f7a652e2653afe1c Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 10 Sep 2024 15:04:10 +0800 Subject: [PATCH 076/126] delete some debug info --- benchmark/case_0.c | 21 +- benchmark/case_1.c | 14 +- src/esbmc/bmc.cpp | 4 +- src/goto-symex/goto_symex_state.cpp | 6 - src/goto-symex/symex_target_equation.cpp | 16 +- src/pointer-analysis/value_set.cpp | 5 - src/solvers/smt/smt_conv.cpp | 1728 +++++++++++----------- src/solvers/z3-slhv/z3_slhv_conv.cpp | 60 +- 8 files changed, 897 insertions(+), 957 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index d1fc3784..b23948d9 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -1,21 +1,8 @@ #include int main(){ - // int * data = malloc(sizeof(int)); - // int * data2 = malloc(2*sizeof(int)); - // free(data); - // int i = *(data + 1); - int *q = malloc(sizeof(int)); - int ** p = malloc(sizeof(int*)); - - *p = q; - **p = 100; - return 0; - // int* j = NULL; - // int* i = j; - // // *(data + 1) = whatever; - // int n = *(data+1); - // if(i > 0) { - // free(data); - // } + int * data = malloc(sizeof(int)); + int * data2 = malloc(2*sizeof(int)); + free(data); + int i = *(data + 1); } diff --git a/benchmark/case_1.c b/benchmark/case_1.c index da969dec..1b3db220 100644 --- a/benchmark/case_1.c +++ b/benchmark/case_1.c @@ -9,10 +9,10 @@ int main() { TData * p1 = malloc(sizeof(TData)); p1->lo = malloc(12); p1->hi = malloc(12); - // void * p2; - // int x; - // if (x) p2 = p1->hi; - // else p2 = p1->lo; - // free(p2); - // return 0; -} + void * p2; + int x; + if (x) p2 = p1->hi; + else p2 = p1->lo; + free(p2); + return 0; +} \ No newline at end of file diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 42bd7486..b5e6c972 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -628,10 +628,8 @@ smt_convt::resultt bmct::run_thread(std::shared_ptr &eq) // show_vcc(*eq); // return smt_convt::P_SMTLIB; const std::string &output_file = options.get_option("output"); - if (!output_file.empty() && output_file != "-"){ + if (!output_file.empty() && output_file != "-") truncate(output_file.c_str(), 0); - } - // std::ofstream(output_file.c_str()) << ""; } if (result.remaining_claims == 0) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 36123281..9ac76f27 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -221,13 +221,7 @@ void goto_symex_statet::assignment(expr2tc &lhs, const expr2tc &rhs) // update value sets expr2tc l1_rhs = rhs; // rhs is const; Rename into new container. level2.get_original_name(l1_rhs); - log_status("##### begin value set assignment from"); - l1_rhs->dump(); - log_status("##### to"); - l1_lhs->dump(); - log_status("#####"); value_set.assign(l1_lhs, l1_rhs); - log_status("update value set done!!!!"); } } diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index e3c2c829..818e1be7 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -142,14 +142,11 @@ void symex_target_equationt::convert(smt_convt &smt_conv) smt_convt::ast_vec assertions; smt_astt assumpt_ast = smt_conv.convert_ast(gen_true_expr()); - log_status("============= begin converting ssa steps"); for (auto &SSA_step : SSA_steps) convert_internal_step(smt_conv, assumpt_ast, assertions, SSA_step); - log_status("convert internal step done"); if (!assertions.empty()) smt_conv.assert_ast(smt_conv.make_n_ary_or(assertions)); - log_status("final convert result ============= "); } void symex_target_equationt::convert_internal_step( @@ -158,7 +155,6 @@ void symex_target_equationt::convert_internal_step( smt_convt::ast_vec &assertions, SSA_stept &step) { - log_status("------ convert internal step ------ "); static unsigned output_count = 0; // Temporary hack; should become scoped. smt_astt true_val = smt_conv.convert_ast(gen_true_expr()); smt_astt false_val = smt_conv.convert_ast(gen_false_expr()); @@ -172,17 +168,13 @@ void symex_target_equationt::convert_internal_step( log_status(" ============================== step ======================== "); step.dump(); - log_status(" ============================== step ======================== "); - // log_status("convert step guard ast: "); // guard_ast is used for generating witness - // not used now // step.guard_ast = smt_conv.convert_ast(step.guard); if (step.is_assume() || step.is_assert()) { // step.cond_ast = false_val; - log_status("step is_assume || step is_assert"); expr2tc tmp(step.cond); step.cond_ast = smt_conv.convert_ast(tmp); if (ssa_smt_trace) @@ -192,7 +184,6 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_assignment()) { - log_status("step is_assignment"); smt_astt assign = smt_conv.convert_assign(step.cond); if (ssa_smt_trace) { @@ -201,7 +192,6 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_output()) { - log_status("step is_output"); for (std::list::const_iterator o_it = step.output_args.begin(); o_it != step.output_args.end(); o_it++) @@ -223,7 +213,6 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_renumber()) { - log_status("step is_renumber"); smt_conv.renumber_symbol_address(step.guard, step.lhs, step.rhs); } else if (!step.is_skip()) @@ -233,24 +222,21 @@ void symex_target_equationt::convert_internal_step( if (step.is_assign_to_assume) { - log_status("step is assign to assume"); smt_conv.assert_ast(step.cond_ast); } else if (step.is_assert()) { - log_status("step is_assert"); step.cond_ast = smt_conv.imply_ast(assumpt_ast, step.cond_ast); assertions.push_back(smt_conv.invert_ast(step.cond_ast)); smt_conv.invert_ast(step.cond_ast)->dump(); } else if (step.is_assume()) { - log_status("step is_assume"); assumpt_ast = smt_conv.mk_and(assumpt_ast, step.cond_ast); step.cond_ast->dump(); } - log_status("-------------- over -----------------"); + log_status(" ============================== step ======================== "); } void symex_target_equationt::output(std::ostream &out) const diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 02ffee12..92d56bca 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -212,9 +212,6 @@ void value_sett::get_value_set_rec( const type2tc &original_type, bool under_deref) const { - log_status("get value set rec for: "); - expr->dump(); - if (is_unknown2t(expr) || is_invalid2t(expr)) { log_status("is unknown expr or invalid expr"); @@ -1138,7 +1135,6 @@ void value_sett::assign( if (is_if2t(rhs)) { - log_status("value set assign: rhs is_if2t"); // If the rhs could be either side of this if, perform the assigment of // either side. In case it refers to itself, assign to a temporary first, // then assign back. @@ -1163,7 +1159,6 @@ void value_sett::assign( if (is_struct_type(lhs_type) || is_union_type(lhs_type)) { - log_status("value set assign: lhs struct or union"); if (lhs_type->type_id == rhs->type->type_id) { /* either both union or both struct */ diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index 8a4985ec..c643795c 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -237,15 +237,9 @@ smt_astt smt_convt::convert_assign(const expr2tc &expr) smt_astt smt_convt::convert_ast(const expr2tc &expr) { - log_status("------------------------------- convert ast "); - expr->dump(); - log_status("-------------------------------"); smt_cachet::const_iterator cache_result = smt_cache.find(expr); - if (cache_result != smt_cache.end()) { - log_status("found!!!!!!!!"); - cache_result->ast->dump(); - return (cache_result->ast); - } + if (cache_result != smt_cache.end()) + return cache_result->ast; bool use_old_encoding = !options.get_bool_option("z3-slhv"); @@ -295,1010 +289,1002 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) switch (expr->expr_id) { - case expr2t::with_id: - case expr2t::constant_array_id: - case expr2t::constant_vector_id: - case expr2t::constant_array_of_id: - case expr2t::constant_intloc_id: - case expr2t::constant_intheap_id: - case expr2t::index_id: - case expr2t::address_of_id: - case expr2t::ieee_add_id: - case expr2t::ieee_sub_id: - case expr2t::ieee_mul_id: - case expr2t::ieee_div_id: - case expr2t::ieee_fma_id: - case expr2t::ieee_sqrt_id: - case expr2t::pointer_offset_id: - case expr2t::pointer_object_id: - case expr2t::pointer_capability_id: - - case expr2t::location_of_id: - case expr2t::field_of_id: - case expr2t::heap_region_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: - break; // Don't convert their operands + case expr2t::with_id: + case expr2t::constant_array_id: + case expr2t::constant_vector_id: + case expr2t::constant_array_of_id: + case expr2t::constant_intloc_id: + case expr2t::constant_intheap_id: + case expr2t::index_id: + case expr2t::address_of_id: + case expr2t::ieee_add_id: + case expr2t::ieee_sub_id: + case expr2t::ieee_mul_id: + case expr2t::ieee_div_id: + case expr2t::ieee_fma_id: + case expr2t::ieee_sqrt_id: + case expr2t::pointer_offset_id: + case expr2t::pointer_object_id: + case expr2t::pointer_capability_id: + + case expr2t::location_of_id: + case expr2t::field_of_id: + case expr2t::heap_region_id: + case expr2t::heap_update_id: + case expr2t::heap_delete_id: + break; // Don't convert their operands + + default: + { + if (is_same_object2t(expr) && !use_old_encoding) break; + + // Convert all the arguments and store them in 'args'. + unsigned int i = 0; + expr->foreach_operand( + [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); + } + } + + smt_astt a; - default: + switch (expr->expr_id) { - if (is_same_object2t(expr) && !use_old_encoding) break; - - // Convert all the arguments and store them in 'args'. - unsigned int i = 0; - expr->foreach_operand( - [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); - log_status(" -------------- convert args finished ------------ "); - for (int i = 0; i < expr->get_num_sub_exprs(); i++) { - args[i]->dump(); + case expr2t::constant_intheap_id: + case expr2t::constant_intloc_id: + case expr2t::heap_region_id: + case expr2t::location_of_id: + case expr2t::field_of_id: + case expr2t::points_to_id: + case expr2t::uplus_id: + case expr2t::locadd_id: + case expr2t::heap_update_id: + case expr2t::heap_contain_id: + case expr2t::heap_append_id: + case expr2t::heap_delete_id: + { + a = convert_slhv_opts(expr, args); + break; } - log_status(" -------------- convert args finished ------------ "); - } - } - log_status("begin convert expr"); - expr->dump(); + case expr2t::constant_int_id: + case expr2t::constant_fixedbv_id: + case expr2t::constant_floatbv_id: + case expr2t::constant_bool_id: + case expr2t::symbol_id: + { + a = convert_terminal(expr); + break; + } + case expr2t::constant_string_id: + { + const constant_string2t &str = to_constant_string2t(expr); + expr2tc newarr = str.to_array(); + a = convert_ast(newarr); + break; + } + case expr2t::constant_struct_id: + { + a = tuple_api->tuple_create(expr); + break; + } + case expr2t::constant_union_id: + { + // Get size + const constant_union2t &cu = to_constant_union2t(expr); + const std::vector &dt_memb = cu.datatype_members; + expr2tc src_expr = + dt_memb.empty() ? gen_zero(get_uint_type(0)) : dt_memb[0]; + #ifndef NDEBUG + if (!cu.init_field.empty()) + { + const union_type2t &ut = to_union_type(expr->type); + unsigned c = ut.get_component_number(cu.init_field); + /* Can only initialize unions by expressions of same type as init_field */ + assert(src_expr->type->type_id == ut.members[c]->type_id); + } + #endif + a = convert_ast(typecast2tc( + get_uint_type(type_byte_size_bits(expr->type).to_uint64()), + bitcast2tc( + get_uint_type(type_byte_size_bits(src_expr->type).to_uint64()), + src_expr))); + break; + } + case expr2t::constant_vector_id: + { + a = array_create(expr); + break; + } + case expr2t::constant_array_id: + case expr2t::constant_array_of_id: + { + const array_type2t &arr = to_array_type(expr->type); + if (!array_api->can_init_infinite_arrays && arr.size_is_infinite) + { + smt_sortt sort = convert_sort(expr->type); + + // Don't honour inifinite sized array initializers. Modelling only. + // If we have an array of tuples and no tuple support, use tuple_fresh. + // Otherwise, mk_fresh. + if (is_tuple_ast_type(arr.subtype)) + a = tuple_api->tuple_fresh(sort); + else + a = mk_fresh( + sort, + "inf_array", + convert_sort(get_flattened_array_subtype(expr->type))); + break; + } - smt_astt a; + expr2tc flat_expr = expr; + if ( + is_array_type(get_array_subtype(expr->type)) && is_constant_array2t(expr)) + flat_expr = flatten_array_body(expr); - switch (expr->expr_id) - { - case expr2t::constant_intheap_id: - case expr2t::constant_intloc_id: - case expr2t::heap_region_id: - case expr2t::location_of_id: - case expr2t::field_of_id: - case expr2t::points_to_id: - case expr2t::uplus_id: - case expr2t::locadd_id: - case expr2t::heap_update_id: - case expr2t::heap_contain_id: - case expr2t::heap_append_id: - case expr2t::heap_delete_id: { - a = convert_slhv_opts(expr, args); - break; - } + if (is_struct_type(arr.subtype) || is_pointer_type(arr.subtype)) + { + // Domain sort may be mesed with: + smt_sortt domain = mk_int_bv_sort( + int_encoding ? config.ansi_c.int_width + : calculate_array_domain_width(arr)); - case expr2t::constant_int_id: - case expr2t::constant_fixedbv_id: - case expr2t::constant_floatbv_id: - case expr2t::constant_bool_id: - case expr2t::symbol_id: - { - a = convert_terminal(expr); - break; - } - case expr2t::constant_string_id: - { - const constant_string2t &str = to_constant_string2t(expr); - expr2tc newarr = str.to_array(); - a = convert_ast(newarr); - break; - } - case expr2t::constant_struct_id: - { - a = tuple_api->tuple_create(expr); - break; - } - case expr2t::constant_union_id: - { - // Get size - const constant_union2t &cu = to_constant_union2t(expr); - const std::vector &dt_memb = cu.datatype_members; - expr2tc src_expr = - dt_memb.empty() ? gen_zero(get_uint_type(0)) : dt_memb[0]; -#ifndef NDEBUG - if (!cu.init_field.empty()) + a = tuple_array_create_despatch(flat_expr, domain); + } + else + a = array_create(flat_expr); + break; + } + case expr2t::add_id: + { + const add2t &add = to_add2t(expr); + if ( + is_pointer_type(expr->type) || is_pointer_type(add.side_1) || + is_pointer_type(add.side_2)) + { + a = !use_old_encoding ? + convert_slhv_opts(expr, args) : + convert_pointer_arith(expr, expr->type); + } + else if (int_encoding) + { + a = mk_add(args[0], args[1]); + } + else + { + a = mk_bvadd(args[0], args[1]); + } + break; + } + case expr2t::sub_id: { - const union_type2t &ut = to_union_type(expr->type); - unsigned c = ut.get_component_number(cu.init_field); - /* Can only initialize unions by expressions of same type as init_field */ - assert(src_expr->type->type_id == ut.members[c]->type_id); + const sub2t &sub = to_sub2t(expr); + if ( + is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || + is_pointer_type(sub.side_2)) + { + a = !use_old_encoding ? + convert_slhv_opts(expr, args) : + convert_pointer_arith(expr, expr->type); + } + else if (int_encoding) + { + a = mk_sub(args[0], args[1]); + } + else + { + a = mk_bvsub(args[0], args[1]); + } + break; } -#endif - a = convert_ast(typecast2tc( - get_uint_type(type_byte_size_bits(expr->type).to_uint64()), - bitcast2tc( - get_uint_type(type_byte_size_bits(src_expr->type).to_uint64()), - src_expr))); - break; - } - case expr2t::constant_vector_id: - { - a = array_create(expr); - break; - } - case expr2t::constant_array_id: - case expr2t::constant_array_of_id: - { - const array_type2t &arr = to_array_type(expr->type); - if (!array_api->can_init_infinite_arrays && arr.size_is_infinite) + case expr2t::mul_id: { - smt_sortt sort = convert_sort(expr->type); + // Fixedbvs are handled separately + if (is_fixedbv_type(expr) && !int_encoding) + { + auto mul = to_mul2t(expr); + auto fbvt = to_fixedbv_type(mul.type); + + unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; + + args[0] = mk_sign_ext(convert_ast(mul.side_1), fraction_bits); + args[1] = mk_sign_ext(convert_ast(mul.side_2), fraction_bits); - // Don't honour inifinite sized array initializers. Modelling only. - // If we have an array of tuples and no tuple support, use tuple_fresh. - // Otherwise, mk_fresh. - if (is_tuple_ast_type(arr.subtype)) - a = tuple_api->tuple_fresh(sort); + a = mk_bvmul(args[0], args[1]); + a = mk_extract(a, fbvt.width + fraction_bits - 1, fraction_bits); + } + else if (int_encoding) + { + a = mk_mul(args[0], args[1]); + } else - a = mk_fresh( - sort, - "inf_array", - convert_sort(get_flattened_array_subtype(expr->type))); + { + a = mk_bvmul(args[0], args[1]); + } break; } + case expr2t::div_id: + { + auto d = to_div2t(expr); - expr2tc flat_expr = expr; - if ( - is_array_type(get_array_subtype(expr->type)) && is_constant_array2t(expr)) - flat_expr = flatten_array_body(expr); + // Fixedbvs are handled separately + if (is_fixedbv_type(expr) && !int_encoding) + { + auto fbvt = to_fixedbv_type(d.type); - if (is_struct_type(arr.subtype) || is_pointer_type(arr.subtype)) - { - // Domain sort may be mesed with: - smt_sortt domain = mk_int_bv_sort( - int_encoding ? config.ansi_c.int_width - : calculate_array_domain_width(arr)); + unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; + + args[1] = mk_sign_ext(convert_ast(d.side_2), fraction_bits); + + smt_astt zero = mk_smt_bv(BigInt(0), fraction_bits); + smt_astt op0 = convert_ast(d.side_1); + + args[0] = mk_concat(op0, zero); - a = tuple_array_create_despatch(flat_expr, domain); + // Sorts. + a = mk_bvsdiv(args[0], args[1]); + a = mk_extract(a, fbvt.width - 1, 0); + } + else if (int_encoding) + { + a = mk_div(args[0], args[1]); + } + else if (is_unsignedbv_type(d.side_1) && is_unsignedbv_type(d.side_2)) + { + a = mk_bvudiv(args[0], args[1]); + } + else + { + assert(is_signedbv_type(d.side_1) && is_signedbv_type(d.side_2)); + a = mk_bvsdiv(args[0], args[1]); + } + break; } - else - a = array_create(flat_expr); - break; - } - case expr2t::add_id: - { - const add2t &add = to_add2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(add.side_1) || - is_pointer_type(add.side_2)) + case expr2t::ieee_add_id: { - a = !use_old_encoding ? - convert_slhv_opts(expr, args) : - convert_pointer_arith(expr, expr->type); + if (int_encoding) + { + a = mk_add( + convert_ast(to_ieee_add2t(expr).side_1), + convert_ast(to_ieee_add2t(expr).side_2)); + } + else + { + assert(is_floatbv_type(expr)); + a = fp_api->mk_smt_fpbv_add( + convert_ast(to_ieee_add2t(expr).side_1), + convert_ast(to_ieee_add2t(expr).side_2), + convert_rounding_mode(to_ieee_add2t(expr).rounding_mode)); + } + break; } - else if (int_encoding) + case expr2t::ieee_sub_id: { - a = mk_add(args[0], args[1]); + assert(is_floatbv_type(expr)); + if (int_encoding) + { + a = mk_sub( + convert_ast(to_ieee_sub2t(expr).side_1), + convert_ast(to_ieee_sub2t(expr).side_2)); + } + else + { + a = fp_api->mk_smt_fpbv_sub( + convert_ast(to_ieee_sub2t(expr).side_1), + convert_ast(to_ieee_sub2t(expr).side_2), + convert_rounding_mode(to_ieee_sub2t(expr).rounding_mode)); + } + break; } - else + case expr2t::ieee_mul_id: { - a = mk_bvadd(args[0], args[1]); + assert(is_floatbv_type(expr)); + if (int_encoding) + { + a = mk_mul( + convert_ast(to_ieee_mul2t(expr).side_1), + convert_ast(to_ieee_mul2t(expr).side_2)); + } + else + { + a = fp_api->mk_smt_fpbv_mul( + convert_ast(to_ieee_mul2t(expr).side_1), + convert_ast(to_ieee_mul2t(expr).side_2), + convert_rounding_mode(to_ieee_mul2t(expr).rounding_mode)); + } + break; } - break; - } - case expr2t::sub_id: - { - const sub2t &sub = to_sub2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || - is_pointer_type(sub.side_2)) + case expr2t::ieee_div_id: { - a = !use_old_encoding ? - convert_slhv_opts(expr, args) : - convert_pointer_arith(expr, expr->type); + assert(is_floatbv_type(expr)); + if (int_encoding) + { + a = mk_div( + convert_ast(to_ieee_div2t(expr).side_1), + convert_ast(to_ieee_div2t(expr).side_2)); + } + else + { + a = fp_api->mk_smt_fpbv_div( + convert_ast(to_ieee_div2t(expr).side_1), + convert_ast(to_ieee_div2t(expr).side_2), + convert_rounding_mode(to_ieee_div2t(expr).rounding_mode)); + } + break; } - else if (int_encoding) + case expr2t::ieee_fma_id: { - a = mk_sub(args[0], args[1]); + assert(is_floatbv_type(expr)); + if (int_encoding) + { + a = mk_add( + mk_mul( + convert_ast(to_ieee_fma2t(expr).value_1), + convert_ast(to_ieee_fma2t(expr).value_2)), + convert_ast(to_ieee_fma2t(expr).value_3)); + } + else + { + a = fp_api->mk_smt_fpbv_fma( + convert_ast(to_ieee_fma2t(expr).value_1), + convert_ast(to_ieee_fma2t(expr).value_2), + convert_ast(to_ieee_fma2t(expr).value_3), + convert_rounding_mode(to_ieee_fma2t(expr).rounding_mode)); + } + break; } - else + case expr2t::ieee_sqrt_id: { - a = mk_bvsub(args[0], args[1]); + assert(is_floatbv_type(expr)); + // TODO: no integer mode implementation + a = fp_api->mk_smt_fpbv_sqrt( + convert_ast(to_ieee_sqrt2t(expr).value), + convert_rounding_mode(to_ieee_sqrt2t(expr).rounding_mode)); + break; } - break; - } - case expr2t::mul_id: - { - // Fixedbvs are handled separately - if (is_fixedbv_type(expr) && !int_encoding) + case expr2t::modulus_id: { - auto mul = to_mul2t(expr); - auto fbvt = to_fixedbv_type(mul.type); + auto m = to_modulus2t(expr); - unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; - - args[0] = mk_sign_ext(convert_ast(mul.side_1), fraction_bits); - args[1] = mk_sign_ext(convert_ast(mul.side_2), fraction_bits); + if (int_encoding) + { + a = mk_mod(args[0], args[1]); + } + else if (is_fixedbv_type(m.side_1) && is_fixedbv_type(m.side_2)) + { + a = mk_bvsmod(args[0], args[1]); + } + else if (is_unsignedbv_type(m.side_1) && is_unsignedbv_type(m.side_2)) + { + a = mk_bvumod(args[0], args[1]); + } + else + { + assert(is_signedbv_type(m.side_1) || is_signedbv_type(m.side_2)); + a = mk_bvsmod(args[0], args[1]); + } + break; + } + case expr2t::index_id: + { + a = convert_array_index(expr); + break; + } + case expr2t::with_id: + { + const with2t &with = to_with2t(expr); - a = mk_bvmul(args[0], args[1]); - a = mk_extract(a, fbvt.width + fraction_bits - 1, fraction_bits); + // We reach here if we're with'ing a struct, not an array. Or a bool. + if (is_struct_type(expr) || is_pointer_type(expr)) + { + unsigned int idx = get_member_name_field(expr->type, with.update_field); + smt_astt srcval = convert_ast(with.source_value); + + #ifndef NDEBUG + const struct_union_data &data = get_type_def(with.type); + assert(idx < data.members.size() && "Out of bounds with expression"); + // Base type eq examines pointer types to closely + assert( + (base_type_eq(data.members[idx], with.update_value->type, ns) || + (is_pointer_type(data.members[idx]) && + is_pointer_type(with.update_value))) && + "Assigned tuple member has type mismatch"); + #endif + + a = srcval->update(this, convert_ast(with.update_value), idx); + } + else if (is_union_type(expr)) + { + uint64_t bits = type_byte_size_bits(expr->type).to_uint64(); + const union_type2t &tu = to_union_type(expr->type); + assert(is_constant_string2t(with.update_field)); + unsigned c = + tu.get_component_number(to_constant_string2t(with.update_field).value); + uint64_t mem_bits = type_byte_size_bits(tu.members[c]).to_uint64(); + expr2tc upd = bitcast2tc( + get_uint_type(mem_bits), typecast2tc(tu.members[c], with.update_value)); + if (mem_bits < bits) + upd = concat2tc( + get_uint_type(bits), + extract2tc( + get_uint_type(bits - mem_bits), + with.source_value, + bits - 1, + mem_bits), + upd); + a = convert_ast(upd); + } + else + { + a = convert_array_store(expr); + } + break; } - else if (int_encoding) + case expr2t::member_id: { - a = mk_mul(args[0], args[1]); + a = convert_member(expr); + break; } - else + case expr2t::same_object_id: { - a = mk_bvmul(args[0], args[1]); + const same_object2t& so = to_same_object2t(expr); + // Two projects, then comparison. + if (use_old_encoding) { + args[0] = args[0]->project(this, 0); + args[1] = args[1]->project(this, 0); + a = mk_eq(args[0], args[1]); + } else { + a = convert_slhv_opts(expr, args); + } + break; } - break; - } - case expr2t::div_id: - { - auto d = to_div2t(expr); - - // Fixedbvs are handled separately - if (is_fixedbv_type(expr) && !int_encoding) + case expr2t::pointer_offset_id: { - auto fbvt = to_fixedbv_type(d.type); + const pointer_offset2t &obj = to_pointer_offset2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type(*ptr)) + ptr = &to_typecast2t(*ptr).from; - unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; - - args[1] = mk_sign_ext(convert_ast(d.side_2), fraction_bits); - - smt_astt zero = mk_smt_bv(BigInt(0), fraction_bits); - smt_astt op0 = convert_ast(d.side_1); - - args[0] = mk_concat(op0, zero); + args[0] = convert_ast(*ptr); + a = !use_old_encoding ? args[0] : args[0]->project(this, 0); + break; + } + case expr2t::pointer_object_id: + { + const pointer_object2t &obj = to_pointer_object2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) + ptr = &to_typecast2t(*ptr).from; - // Sorts. - a = mk_bvsdiv(args[0], args[1]); - a = mk_extract(a, fbvt.width - 1, 0); + args[0] = convert_ast(*ptr); + a = !use_old_encoding ? args[0] : args[0]->project(this, 0); + break; } - else if (int_encoding) + case expr2t::pointer_capability_id: { - a = mk_div(args[0], args[1]); + assert(config.ansi_c.cheri); + const pointer_capability2t &obj = to_pointer_capability2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) + ptr = &to_typecast2t(*ptr).from; + + args[0] = convert_ast(*ptr); + a = args[0]->project(this, 2); + break; } - else if (is_unsignedbv_type(d.side_1) && is_unsignedbv_type(d.side_2)) + case expr2t::typecast_id: { - a = mk_bvudiv(args[0], args[1]); + a = convert_typecast(expr); + break; } - else + case expr2t::nearbyint_id: { - assert(is_signedbv_type(d.side_1) && is_signedbv_type(d.side_2)); - a = mk_bvsdiv(args[0], args[1]); + assert(is_floatbv_type(expr)); + a = fp_api->mk_smt_nearbyint_from_float( + convert_ast(to_nearbyint2t(expr).from), + convert_rounding_mode(to_nearbyint2t(expr).rounding_mode)); + break; } - break; - } - case expr2t::ieee_add_id: - { - if (int_encoding) + case expr2t::if_id: { - a = mk_add( - convert_ast(to_ieee_add2t(expr).side_1), - convert_ast(to_ieee_add2t(expr).side_2)); + // Only attempt to handle struct.s + const if2t &if_ref = to_if2t(expr); + args[0] = convert_ast(if_ref.cond); + args[1] = convert_ast(if_ref.true_value); + args[2] = convert_ast(if_ref.false_value); + a = args[1]->ite(this, args[0], args[2]); + break; } - else + case expr2t::isnan_id: { - assert(is_floatbv_type(expr)); - a = fp_api->mk_smt_fpbv_add( - convert_ast(to_ieee_add2t(expr).side_1), - convert_ast(to_ieee_add2t(expr).side_2), - convert_rounding_mode(to_ieee_add2t(expr).rounding_mode)); + a = convert_is_nan(expr); + break; } - break; - } - case expr2t::ieee_sub_id: - { - assert(is_floatbv_type(expr)); - if (int_encoding) + case expr2t::isinf_id: { - a = mk_sub( - convert_ast(to_ieee_sub2t(expr).side_1), - convert_ast(to_ieee_sub2t(expr).side_2)); + a = convert_is_inf(expr); + break; } - else + case expr2t::isnormal_id: { - a = fp_api->mk_smt_fpbv_sub( - convert_ast(to_ieee_sub2t(expr).side_1), - convert_ast(to_ieee_sub2t(expr).side_2), - convert_rounding_mode(to_ieee_sub2t(expr).rounding_mode)); + a = convert_is_normal(expr); + break; } - break; - } - case expr2t::ieee_mul_id: - { - assert(is_floatbv_type(expr)); - if (int_encoding) + case expr2t::isfinite_id: { - a = mk_mul( - convert_ast(to_ieee_mul2t(expr).side_1), - convert_ast(to_ieee_mul2t(expr).side_2)); + a = convert_is_finite(expr); + break; } - else + case expr2t::signbit_id: { - a = fp_api->mk_smt_fpbv_mul( - convert_ast(to_ieee_mul2t(expr).side_1), - convert_ast(to_ieee_mul2t(expr).side_2), - convert_rounding_mode(to_ieee_mul2t(expr).rounding_mode)); + a = convert_signbit(expr); + break; } - break; - } - case expr2t::ieee_div_id: - { - assert(is_floatbv_type(expr)); - if (int_encoding) + case expr2t::popcount_id: { - a = mk_div( - convert_ast(to_ieee_div2t(expr).side_1), - convert_ast(to_ieee_div2t(expr).side_2)); + a = convert_popcount(expr); + break; } - else + case expr2t::bswap_id: { - a = fp_api->mk_smt_fpbv_div( - convert_ast(to_ieee_div2t(expr).side_1), - convert_ast(to_ieee_div2t(expr).side_2), - convert_rounding_mode(to_ieee_div2t(expr).rounding_mode)); + a = convert_bswap(expr); + break; } - break; - } - case expr2t::ieee_fma_id: - { - assert(is_floatbv_type(expr)); - if (int_encoding) + case expr2t::overflow_id: { - a = mk_add( - mk_mul( - convert_ast(to_ieee_fma2t(expr).value_1), - convert_ast(to_ieee_fma2t(expr).value_2)), - convert_ast(to_ieee_fma2t(expr).value_3)); + a = overflow_arith(expr); + break; } - else + case expr2t::overflow_cast_id: { - a = fp_api->mk_smt_fpbv_fma( - convert_ast(to_ieee_fma2t(expr).value_1), - convert_ast(to_ieee_fma2t(expr).value_2), - convert_ast(to_ieee_fma2t(expr).value_3), - convert_rounding_mode(to_ieee_fma2t(expr).rounding_mode)); + a = overflow_cast(expr); + break; } - break; - } - case expr2t::ieee_sqrt_id: - { - assert(is_floatbv_type(expr)); - // TODO: no integer mode implementation - a = fp_api->mk_smt_fpbv_sqrt( - convert_ast(to_ieee_sqrt2t(expr).value), - convert_rounding_mode(to_ieee_sqrt2t(expr).rounding_mode)); - break; - } - case expr2t::modulus_id: - { - auto m = to_modulus2t(expr); - - if (int_encoding) + case expr2t::overflow_neg_id: { - a = mk_mod(args[0], args[1]); + a = overflow_neg(expr); + break; } - else if (is_fixedbv_type(m.side_1) && is_fixedbv_type(m.side_2)) + case expr2t::byte_extract_id: { - a = mk_bvsmod(args[0], args[1]); + a = convert_byte_extract(expr); + break; } - else if (is_unsignedbv_type(m.side_1) && is_unsignedbv_type(m.side_2)) + case expr2t::byte_update_id: { - a = mk_bvumod(args[0], args[1]); + a = convert_byte_update(expr); + break; } - else + case expr2t::address_of_id: { - assert(is_signedbv_type(m.side_1) || is_signedbv_type(m.side_2)); - a = mk_bvsmod(args[0], args[1]); + a = convert_addr_of(expr); + break; } - break; - } - case expr2t::index_id: - { - a = convert_array_index(expr); - break; - } - case expr2t::with_id: - { - const with2t &with = to_with2t(expr); - - // We reach here if we're with'ing a struct, not an array. Or a bool. - if (is_struct_type(expr) || is_pointer_type(expr)) - { - unsigned int idx = get_member_name_field(expr->type, with.update_field); - smt_astt srcval = convert_ast(with.source_value); - -#ifndef NDEBUG - const struct_union_data &data = get_type_def(with.type); - assert(idx < data.members.size() && "Out of bounds with expression"); - // Base type eq examines pointer types to closely - assert( - (base_type_eq(data.members[idx], with.update_value->type, ns) || - (is_pointer_type(data.members[idx]) && - is_pointer_type(with.update_value))) && - "Assigned tuple member has type mismatch"); -#endif - - a = srcval->update(this, convert_ast(with.update_value), idx); - } - else if (is_union_type(expr)) - { - uint64_t bits = type_byte_size_bits(expr->type).to_uint64(); - const union_type2t &tu = to_union_type(expr->type); - assert(is_constant_string2t(with.update_field)); - unsigned c = - tu.get_component_number(to_constant_string2t(with.update_field).value); - uint64_t mem_bits = type_byte_size_bits(tu.members[c]).to_uint64(); - expr2tc upd = bitcast2tc( - get_uint_type(mem_bits), typecast2tc(tu.members[c], with.update_value)); - if (mem_bits < bits) - upd = concat2tc( - get_uint_type(bits), - extract2tc( - get_uint_type(bits - mem_bits), - with.source_value, - bits - 1, - mem_bits), - upd); - a = convert_ast(upd); + case expr2t::equality_id: + { + /* Compare the representations directly. + * + * This also applies to pointer-typed expressions which are represented as + * (object, offset) structs, i.e., two pointers compare equal iff both + * members are the same. + * + * 'offset' is between 0 and the size of the object, both inclusively. This + * is in line with what's allowed by C99 and what current GCC assumes + * regarding the one-past the end pointer: + * + * Two pointers compare equal if and only if both are null pointers, both + * are pointers to the same object (including a pointer to an object and a + * subobject at its beginning) or function, both are pointers to one past + * the last element of the same array object, or one is a pointer to one + * past the end of one array object and the other is a pointer to the + * start of a different array object that happens to immediately follow + * the first array object in the address space. + * + * It's not strictly what Clang does, though, but de-facto, C compilers do + * perform optimizations based on provenance, i.e., "one past the end + * pointers cannot alias another object" as soon as it *cannot* be proven + * that they do. Sigh. For instance + * makes for a "fun" + * read illuminating how reasoning works from a certain compiler's + * writers' points of view. + * + * C++ has changed this one-past behaviour in [expr.eq] to "unspecified" + * + * and C might eventually follow the same path. + * + * CHERI-C semantics say that only addresses should be compared, but this + * might also change in the future, see e.g. + * . + * + * TODO: As languages begin to differ in their pointer equality semantics, + * we could move pointer comparisons to symex in order to express + * them properly according to the input language. + */ + + auto eq = to_equality2t(expr); + + if ( + is_floatbv_type(eq.side_1) && is_floatbv_type(eq.side_2) && !int_encoding) + a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); + else + a = args[0]->eq(this, args[1]); + break; } - else + case expr2t::notequal_id: { - a = convert_array_store(expr); - } - break; - } - case expr2t::member_id: - { - a = convert_member(expr); - break; - } - case expr2t::same_object_id: - { - const same_object2t& so = to_same_object2t(expr); - // Two projects, then comparison. - if (use_old_encoding) { - args[0] = args[0]->project(this, 0); - args[1] = args[1]->project(this, 0); - a = mk_eq(args[0], args[1]); - } else { - a = convert_slhv_opts(expr, args); - } - break; - } - case expr2t::pointer_offset_id: - { - const pointer_offset2t &obj = to_pointer_offset2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type(*ptr)) - ptr = &to_typecast2t(*ptr).from; + // Handle all kinds of structs by inverted equality. The only that's really + // going to turn up is pointers though. - args[0] = convert_ast(*ptr); - a = !use_old_encoding ? args[0] : args[0]->project(this, 0); - break; - } - case expr2t::pointer_object_id: - { - const pointer_object2t &obj = to_pointer_object2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) - ptr = &to_typecast2t(*ptr).from; - - args[0] = convert_ast(*ptr); - a = !use_old_encoding ? args[0] : args[0]->project(this, 0); - break; - } - case expr2t::pointer_capability_id: - { - assert(config.ansi_c.cheri); - const pointer_capability2t &obj = to_pointer_capability2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) - ptr = &to_typecast2t(*ptr).from; + auto neq = to_notequal2t(expr); - args[0] = convert_ast(*ptr); - a = args[0]->project(this, 2); - break; - } - case expr2t::typecast_id: - { - a = convert_typecast(expr); - break; - } - case expr2t::nearbyint_id: - { - assert(is_floatbv_type(expr)); - a = fp_api->mk_smt_nearbyint_from_float( - convert_ast(to_nearbyint2t(expr).from), - convert_rounding_mode(to_nearbyint2t(expr).rounding_mode)); - break; - } - case expr2t::if_id: - { - // Only attempt to handle struct.s - const if2t &if_ref = to_if2t(expr); - args[0] = convert_ast(if_ref.cond); - args[1] = convert_ast(if_ref.true_value); - args[2] = convert_ast(if_ref.false_value); - a = args[1]->ite(this, args[0], args[2]); - break; - } - case expr2t::isnan_id: - { - a = convert_is_nan(expr); - break; - } - case expr2t::isinf_id: - { - a = convert_is_inf(expr); - break; - } - case expr2t::isnormal_id: - { - a = convert_is_normal(expr); - break; - } - case expr2t::isfinite_id: - { - a = convert_is_finite(expr); - break; - } - case expr2t::signbit_id: - { - a = convert_signbit(expr); - break; - } - case expr2t::popcount_id: - { - a = convert_popcount(expr); - break; - } - case expr2t::bswap_id: - { - a = convert_bswap(expr); - break; - } - case expr2t::overflow_id: - { - a = overflow_arith(expr); - break; - } - case expr2t::overflow_cast_id: - { - a = overflow_cast(expr); - break; - } - case expr2t::overflow_neg_id: - { - a = overflow_neg(expr); - break; - } - case expr2t::byte_extract_id: - { - a = convert_byte_extract(expr); - break; - } - case expr2t::byte_update_id: - { - a = convert_byte_update(expr); - break; - } - case expr2t::address_of_id: - { - a = convert_addr_of(expr); - break; - } - case expr2t::equality_id: - { - /* Compare the representations directly. - * - * This also applies to pointer-typed expressions which are represented as - * (object, offset) structs, i.e., two pointers compare equal iff both - * members are the same. - * - * 'offset' is between 0 and the size of the object, both inclusively. This - * is in line with what's allowed by C99 and what current GCC assumes - * regarding the one-past the end pointer: - * - * Two pointers compare equal if and only if both are null pointers, both - * are pointers to the same object (including a pointer to an object and a - * subobject at its beginning) or function, both are pointers to one past - * the last element of the same array object, or one is a pointer to one - * past the end of one array object and the other is a pointer to the - * start of a different array object that happens to immediately follow - * the first array object in the address space. - * - * It's not strictly what Clang does, though, but de-facto, C compilers do - * perform optimizations based on provenance, i.e., "one past the end - * pointers cannot alias another object" as soon as it *cannot* be proven - * that they do. Sigh. For instance - * makes for a "fun" - * read illuminating how reasoning works from a certain compiler's - * writers' points of view. - * - * C++ has changed this one-past behaviour in [expr.eq] to "unspecified" - * - * and C might eventually follow the same path. - * - * CHERI-C semantics say that only addresses should be compared, but this - * might also change in the future, see e.g. - * . - * - * TODO: As languages begin to differ in their pointer equality semantics, - * we could move pointer comparisons to symex in order to express - * them properly according to the input language. - */ - - auto eq = to_equality2t(expr); - - if ( - is_floatbv_type(eq.side_1) && is_floatbv_type(eq.side_2) && !int_encoding) - a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); - else - a = args[0]->eq(this, args[1]); - break; - } - case expr2t::notequal_id: - { - // Handle all kinds of structs by inverted equality. The only that's really - // going to turn up is pointers though. - - auto neq = to_notequal2t(expr); - - if ( - is_floatbv_type(neq.side_1) && is_floatbv_type(neq.side_2) && - !int_encoding) - a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); - else - a = args[0]->eq(this, args[1]); - a = mk_not(a); - break; - } - case expr2t::shl_id: - { - const shl2t &shl = to_shl2t(expr); - if (shl.side_1->type->get_width() != shl.side_2->type->get_width()) - { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(shl.side_1->type, shl.side_2); - args[1] = convert_ast(cast); - } - - if (int_encoding) - { - // Raise 2^shift, then multiply first operand by that value. If it's - // negative, what to do? FIXME. - smt_astt powval = int_shift_op_array->select(this, shl.side_2); - args[1] = powval; - a = mk_mul(args[0], args[1]); + if ( + is_floatbv_type(neq.side_1) && is_floatbv_type(neq.side_2) && + !int_encoding) + a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); + else + a = args[0]->eq(this, args[1]); + a = mk_not(a); + break; } - else + case expr2t::shl_id: { - a = mk_bvshl(args[0], args[1]); - } - break; - } - case expr2t::ashr_id: - { - const ashr2t &ashr = to_ashr2t(expr); - if (ashr.side_1->type->get_width() != ashr.side_2->type->get_width()) - { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(ashr.side_1->type, ashr.side_2); - args[1] = convert_ast(cast); - } + const shl2t &shl = to_shl2t(expr); + if (shl.side_1->type->get_width() != shl.side_2->type->get_width()) + { + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(shl.side_1->type, shl.side_2); + args[1] = convert_ast(cast); + } - if (int_encoding) - { - // Raise 2^shift, then divide first operand by that value. If it's - // negative, I suspect the correct operation is to latch to -1, - smt_astt powval = int_shift_op_array->select(this, ashr.side_2); - args[1] = powval; - a = mk_div(args[0], args[1]); - } - else - { - a = mk_bvashr(args[0], args[1]); + if (int_encoding) + { + // Raise 2^shift, then multiply first operand by that value. If it's + // negative, what to do? FIXME. + smt_astt powval = int_shift_op_array->select(this, shl.side_2); + args[1] = powval; + a = mk_mul(args[0], args[1]); + } + else + { + a = mk_bvshl(args[0], args[1]); + } + break; } - break; - } - case expr2t::lshr_id: - { - const lshr2t &lshr = to_lshr2t(expr); - if (lshr.side_1->type->get_width() != lshr.side_2->type->get_width()) + case expr2t::ashr_id: { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(lshr.side_1->type, lshr.side_2); - args[1] = convert_ast(cast); - } + const ashr2t &ashr = to_ashr2t(expr); + if (ashr.side_1->type->get_width() != ashr.side_2->type->get_width()) + { + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(ashr.side_1->type, ashr.side_2); + args[1] = convert_ast(cast); + } - if (int_encoding) - { - // Raise 2^shift, then divide first operand by that value. If it's - // negative, I suspect the correct operation is to latch to -1, - smt_astt powval = int_shift_op_array->select(this, lshr.side_2); - args[1] = powval; - a = mk_div(args[0], args[1]); - } - else - { - a = mk_bvlshr(args[0], args[1]); - } - break; - } - case expr2t::abs_id: - { - const abs2t &abs = to_abs2t(expr); - if (is_unsignedbv_type(abs.value)) - { - // No need to do anything. - a = args[0]; - } - else if (is_floatbv_type(abs.value) && !int_encoding) - { - a = fp_api->mk_smt_fpbv_abs(args[0]); + if (int_encoding) + { + // Raise 2^shift, then divide first operand by that value. If it's + // negative, I suspect the correct operation is to latch to -1, + smt_astt powval = int_shift_op_array->select(this, ashr.side_2); + args[1] = powval; + a = mk_div(args[0], args[1]); + } + else + { + a = mk_bvashr(args[0], args[1]); + } + break; } - else + case expr2t::lshr_id: { - expr2tc lt = lessthan2tc(abs.value, gen_zero(abs.value->type)); - expr2tc neg = neg2tc(abs.value->type, abs.value); - expr2tc ite = if2tc(abs.type, lt, neg, abs.value); + const lshr2t &lshr = to_lshr2t(expr); + if (lshr.side_1->type->get_width() != lshr.side_2->type->get_width()) + { + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(lshr.side_1->type, lshr.side_2); + args[1] = convert_ast(cast); + } - a = convert_ast(ite); - } - break; - } - case expr2t::lessthan_id: - { - const lessthan2t < = to_lessthan2t(expr); - // Pointer relation: - if (is_pointer_type(lt.side_1)) - { - a = convert_ptr_cmp(lt.side_1, lt.side_2, expr); - } - else if (int_encoding) - { - a = mk_lt(args[0], args[1]); - } - else if (is_floatbv_type(lt.side_1) && is_floatbv_type(lt.side_2)) - { - a = fp_api->mk_smt_fpbv_lt(args[0], args[1]); - } - else if (is_fixedbv_type(lt.side_1) && is_fixedbv_type(lt.side_2)) - { - a = mk_bvslt(args[0], args[1]); + if (int_encoding) + { + // Raise 2^shift, then divide first operand by that value. If it's + // negative, I suspect the correct operation is to latch to -1, + smt_astt powval = int_shift_op_array->select(this, lshr.side_2); + args[1] = powval; + a = mk_div(args[0], args[1]); + } + else + { + a = mk_bvlshr(args[0], args[1]); + } + break; } - else if (is_unsignedbv_type(lt.side_1) && is_unsignedbv_type(lt.side_2)) + case expr2t::abs_id: { - a = mk_bvult(args[0], args[1]); + const abs2t &abs = to_abs2t(expr); + if (is_unsignedbv_type(abs.value)) + { + // No need to do anything. + a = args[0]; + } + else if (is_floatbv_type(abs.value) && !int_encoding) + { + a = fp_api->mk_smt_fpbv_abs(args[0]); + } + else + { + expr2tc lt = lessthan2tc(abs.value, gen_zero(abs.value->type)); + expr2tc neg = neg2tc(abs.value->type, abs.value); + expr2tc ite = if2tc(abs.type, lt, neg, abs.value); + + a = convert_ast(ite); + } + break; } - else + case expr2t::lessthan_id: { - assert(is_signedbv_type(lt.side_1) && is_signedbv_type(lt.side_2)); - a = mk_bvslt(args[0], args[1]); + const lessthan2t < = to_lessthan2t(expr); + // Pointer relation: + if (is_pointer_type(lt.side_1)) + { + a = convert_ptr_cmp(lt.side_1, lt.side_2, expr); + } + else if (int_encoding) + { + a = mk_lt(args[0], args[1]); + } + else if (is_floatbv_type(lt.side_1) && is_floatbv_type(lt.side_2)) + { + a = fp_api->mk_smt_fpbv_lt(args[0], args[1]); + } + else if (is_fixedbv_type(lt.side_1) && is_fixedbv_type(lt.side_2)) + { + a = mk_bvslt(args[0], args[1]); + } + else if (is_unsignedbv_type(lt.side_1) && is_unsignedbv_type(lt.side_2)) + { + a = mk_bvult(args[0], args[1]); + } + else + { + assert(is_signedbv_type(lt.side_1) && is_signedbv_type(lt.side_2)); + a = mk_bvslt(args[0], args[1]); + } + break; } - break; - } - case expr2t::lessthanequal_id: - { - const lessthanequal2t <e = to_lessthanequal2t(expr); - // Pointer relation: - if (is_pointer_type(lte.side_1)) + case expr2t::lessthanequal_id: { - a = convert_ptr_cmp(lte.side_1, lte.side_2, expr); + const lessthanequal2t <e = to_lessthanequal2t(expr); + // Pointer relation: + if (is_pointer_type(lte.side_1)) + { + a = convert_ptr_cmp(lte.side_1, lte.side_2, expr); + } + else if (int_encoding) + { + a = mk_le(args[0], args[1]); + } + else if (is_floatbv_type(lte.side_1) && is_floatbv_type(lte.side_2)) + { + a = fp_api->mk_smt_fpbv_lte(args[0], args[1]); + } + else if (is_fixedbv_type(lte.side_1) && is_fixedbv_type(lte.side_2)) + { + a = mk_bvsle(args[0], args[1]); + } + else if (is_unsignedbv_type(lte.side_1) && is_unsignedbv_type(lte.side_2)) + { + a = mk_bvule(args[0], args[1]); + } + else + { + assert(is_signedbv_type(lte.side_1) && is_signedbv_type(lte.side_2)); + a = mk_bvsle(args[0], args[1]); + } + break; } - else if (int_encoding) + case expr2t::greaterthan_id: { - a = mk_le(args[0], args[1]); + const greaterthan2t > = to_greaterthan2t(expr); + // Pointer relation: + if (is_pointer_type(gt.side_1)) + { + a = convert_ptr_cmp(gt.side_1, gt.side_2, expr); + } + else if (int_encoding) + { + a = mk_gt(args[0], args[1]); + } + else if (is_floatbv_type(gt.side_1) && is_floatbv_type(gt.side_2)) + { + a = fp_api->mk_smt_fpbv_gt(args[0], args[1]); + } + else if (is_fixedbv_type(gt.side_1) && is_fixedbv_type(gt.side_2)) + { + a = mk_bvsgt(args[0], args[1]); + } + else if (is_unsignedbv_type(gt.side_1) && is_unsignedbv_type(gt.side_2)) + { + a = mk_bvugt(args[0], args[1]); + } + else + { + assert(is_signedbv_type(gt.side_1) && is_signedbv_type(gt.side_2)); + a = mk_bvsgt(args[0], args[1]); + } + break; } - else if (is_floatbv_type(lte.side_1) && is_floatbv_type(lte.side_2)) + case expr2t::greaterthanequal_id: { - a = fp_api->mk_smt_fpbv_lte(args[0], args[1]); + const greaterthanequal2t >e = to_greaterthanequal2t(expr); + // Pointer relation: + if (is_pointer_type(gte.side_1)) + { + a = convert_ptr_cmp(gte.side_1, gte.side_2, expr); + } + else if (int_encoding) + { + a = mk_ge(args[0], args[1]); + } + else if (is_floatbv_type(gte.side_1) && is_floatbv_type(gte.side_2)) + { + a = fp_api->mk_smt_fpbv_gte(args[0], args[1]); + } + else if (is_fixedbv_type(gte.side_1) && is_fixedbv_type(gte.side_2)) + { + a = mk_bvsge(args[0], args[1]); + } + else if (is_unsignedbv_type(gte.side_1) && is_unsignedbv_type(gte.side_2)) + { + a = mk_bvuge(args[0], args[1]); + } + else + { + assert(is_signedbv_type(gte.side_1) && is_signedbv_type(gte.side_2)); + a = mk_bvsge(args[0], args[1]); + } + break; } - else if (is_fixedbv_type(lte.side_1) && is_fixedbv_type(lte.side_2)) + case expr2t::concat_id: { - a = mk_bvsle(args[0], args[1]); + assert( + !int_encoding && + "Concatenate encountered in integer mode; unimplemented (and funky)"); + a = mk_concat(args[0], args[1]); + break; } - else if (is_unsignedbv_type(lte.side_1) && is_unsignedbv_type(lte.side_2)) + case expr2t::implies_id: { - a = mk_bvule(args[0], args[1]); + a = mk_implies(args[0], args[1]); + break; } - else + case expr2t::bitand_id: { - assert(is_signedbv_type(lte.side_1) && is_signedbv_type(lte.side_2)); - a = mk_bvsle(args[0], args[1]); + assert(!int_encoding); + a = mk_bvand(args[0], args[1]); + break; } - break; - } - case expr2t::greaterthan_id: - { - const greaterthan2t > = to_greaterthan2t(expr); - // Pointer relation: - if (is_pointer_type(gt.side_1)) + case expr2t::bitor_id: { - a = convert_ptr_cmp(gt.side_1, gt.side_2, expr); + assert(!int_encoding); + a = mk_bvor(args[0], args[1]); + break; } - else if (int_encoding) + case expr2t::bitxor_id: { - a = mk_gt(args[0], args[1]); + assert(!int_encoding); + a = mk_bvxor(args[0], args[1]); + break; } - else if (is_floatbv_type(gt.side_1) && is_floatbv_type(gt.side_2)) + case expr2t::bitnand_id: { - a = fp_api->mk_smt_fpbv_gt(args[0], args[1]); + assert(!int_encoding); + a = mk_bvnand(args[0], args[1]); + break; } - else if (is_fixedbv_type(gt.side_1) && is_fixedbv_type(gt.side_2)) + case expr2t::bitnor_id: { - a = mk_bvsgt(args[0], args[1]); + assert(!int_encoding); + a = mk_bvnor(args[0], args[1]); + break; } - else if (is_unsignedbv_type(gt.side_1) && is_unsignedbv_type(gt.side_2)) + case expr2t::bitnxor_id: { - a = mk_bvugt(args[0], args[1]); + assert(!int_encoding); + a = mk_bvnxor(args[0], args[1]); + break; } - else + case expr2t::bitnot_id: { - assert(is_signedbv_type(gt.side_1) && is_signedbv_type(gt.side_2)); - a = mk_bvsgt(args[0], args[1]); + assert(!int_encoding); + a = mk_bvnot(args[0]); + break; } - break; - } - case expr2t::greaterthanequal_id: - { - const greaterthanequal2t >e = to_greaterthanequal2t(expr); - // Pointer relation: - if (is_pointer_type(gte.side_1)) + case expr2t::not_id: { - a = convert_ptr_cmp(gte.side_1, gte.side_2, expr); + assert(is_bool_type(expr)); + a = mk_not(args[0]); + break; } - else if (int_encoding) + case expr2t::neg_id: { - a = mk_ge(args[0], args[1]); + const neg2t &neg = to_neg2t(expr); + if (int_encoding) + { + a = mk_neg(args[0]); + } + else if (is_floatbv_type(neg.value)) + { + a = fp_api->mk_smt_fpbv_neg(args[0]); + } + else + { + a = mk_bvneg(args[0]); + } + break; } - else if (is_floatbv_type(gte.side_1) && is_floatbv_type(gte.side_2)) + case expr2t::and_id: { - a = fp_api->mk_smt_fpbv_gte(args[0], args[1]); + a = mk_and(args[0], args[1]); + break; } - else if (is_fixedbv_type(gte.side_1) && is_fixedbv_type(gte.side_2)) + case expr2t::or_id: { - a = mk_bvsge(args[0], args[1]); + a = mk_or(args[0], args[1]); + break; } - else if (is_unsignedbv_type(gte.side_1) && is_unsignedbv_type(gte.side_2)) + case expr2t::xor_id: { - a = mk_bvuge(args[0], args[1]); + a = mk_xor(args[0], args[1]); + break; } - else + case expr2t::bitcast_id: { - assert(is_signedbv_type(gte.side_1) && is_signedbv_type(gte.side_2)); - a = mk_bvsge(args[0], args[1]); + a = convert_bitcast(expr); + break; } - break; - } - case expr2t::concat_id: - { - assert( - !int_encoding && - "Concatenate encountered in integer mode; unimplemented (and funky)"); - a = mk_concat(args[0], args[1]); - break; - } - case expr2t::implies_id: - { - a = mk_implies(args[0], args[1]); - break; - } - case expr2t::bitand_id: - { - assert(!int_encoding); - a = mk_bvand(args[0], args[1]); - break; - } - case expr2t::bitor_id: - { - assert(!int_encoding); - a = mk_bvor(args[0], args[1]); - break; - } - case expr2t::bitxor_id: - { - assert(!int_encoding); - a = mk_bvxor(args[0], args[1]); - break; - } - case expr2t::bitnand_id: - { - assert(!int_encoding); - a = mk_bvnand(args[0], args[1]); - break; - } - case expr2t::bitnor_id: - { - assert(!int_encoding); - a = mk_bvnor(args[0], args[1]); - break; - } - case expr2t::bitnxor_id: - { - assert(!int_encoding); - a = mk_bvnxor(args[0], args[1]); - break; - } - case expr2t::bitnot_id: - { - assert(!int_encoding); - a = mk_bvnot(args[0]); - break; - } - case expr2t::not_id: - { - assert(is_bool_type(expr)); - a = mk_not(args[0]); - break; - } - case expr2t::neg_id: - { - const neg2t &neg = to_neg2t(expr); - if (int_encoding) + case expr2t::extract_id: { - a = mk_neg(args[0]); + const extract2t &ex = to_extract2t(expr); + a = convert_ast(ex.from); + if (ex.from->type->get_width() == ex.upper - ex.lower + 1) + return a; + a = mk_extract(a, ex.upper, ex.lower); + break; } - else if (is_floatbv_type(neg.value)) + case expr2t::code_comma_id: { - a = fp_api->mk_smt_fpbv_neg(args[0]); + /* + TODO: for some reason comma expressions survive when they are under + * RETURN statements. They should have been taken care of at the GOTO + * level. Remove this code once we do! + + the expression on the right side will become the value of the entire comma-separated expression. + + e.g. + return side_1, side_2; + equals to + side1; + return side_2; + */ + const code_comma2t &cm = to_code_comma2t(expr); + a = convert_ast(cm.side_2); + break; } - else + default: { - a = mk_bvneg(args[0]); + log_error("Couldn't convert expression in unrecognised format\n{}", *expr); + abort(); } - break; - } - case expr2t::and_id: - { - a = mk_and(args[0], args[1]); - break; - } - case expr2t::or_id: - { - a = mk_or(args[0], args[1]); - break; - } - case expr2t::xor_id: - { - a = mk_xor(args[0], args[1]); - break; - } - case expr2t::bitcast_id: - { - a = convert_bitcast(expr); - break; - } - case expr2t::extract_id: - { - const extract2t &ex = to_extract2t(expr); - a = convert_ast(ex.from); - if (ex.from->type->get_width() == ex.upper - ex.lower + 1) - return a; - a = mk_extract(a, ex.upper, ex.lower); - break; - } - case expr2t::code_comma_id: - { - /* - TODO: for some reason comma expressions survive when they are under - * RETURN statements. They should have been taken care of at the GOTO - * level. Remove this code once we do! - - the expression on the right side will become the value of the entire comma-separated expression. - - e.g. - return side_1, side_2; - equals to - side1; - return side_2; - */ - const code_comma2t &cm = to_code_comma2t(expr); - a = convert_ast(cm.side_2); - break; - } - default: - log_error("Couldn't convert expression in unrecognised format\n{}", *expr); - abort(); } struct smt_cache_entryt entry = {expr, a, ctx_level}; smt_cache.insert(entry); - log_status("==== converted reuslt: "); - a->dump(); - log_status("===="); return a; } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index a803cbdc..12434ead 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -230,11 +230,9 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { log_status("------------------------------- convert ast -----------------------------"); expr->dump(); - log_status("-------------------------------------------------------------------------"); smt_cachet::const_iterator cache_result = smt_cache.find(expr); if (cache_result != smt_cache.end()) { - log_status("found!!!!!!!!"); cache_result->ast->dump(); return (cache_result->ast); } @@ -244,34 +242,26 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) switch (expr->expr_id) { - case expr2t::pointer_object_id: - case expr2t::same_object_id: - - case expr2t::constant_intloc_id: - case expr2t::constant_intheap_id: - case expr2t::location_of_id: - case expr2t::field_of_id: - case expr2t::heap_region_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: - break; // Don't convert their operands - - default: - { - // Convert all the arguments and store them in 'args'. - unsigned int i = 0; - expr->foreach_operand( - [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); - log_status(" -------------- convert args finished ------------ "); - for (int i = 0; i < expr->get_num_sub_exprs(); i++) { - args[i]->dump(); - } - log_status(" -------------- convert args finished ------------ "); - } - } + case expr2t::pointer_object_id: + case expr2t::same_object_id: - log_status("begin convert expr"); - expr->dump(); + case expr2t::constant_intloc_id: + case expr2t::constant_intheap_id: + case expr2t::location_of_id: + case expr2t::field_of_id: + case expr2t::heap_region_id: + case expr2t::heap_update_id: + case expr2t::heap_delete_id: + break; // Don't convert their operands + + default: + { + // Convert all the arguments and store them in 'args'. + unsigned int i = 0; + expr->foreach_operand( + [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); + } + } smt_astt a; switch (expr->expr_id) @@ -410,8 +400,10 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) break; } default: + { log_error("Couldn't convert expression in unrecognised format\n{}", *expr); abort(); + } } if (is_bool_type(expr->type)) collect_heap_state(a); @@ -419,9 +411,9 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) struct smt_cache_entryt entry = {expr, a, ctx_level}; smt_cache.insert(entry); - log_status("==== converted reuslt: "); + log_status("====================== converted reuslt: "); a->dump(); - log_status("===="); + log_status("-------------------------------------------------------------------------"); return a; } @@ -663,7 +655,8 @@ z3_slhv_convt::convert_slhv_opts( smt_astt eq = mk_eq(p1, p2); return eq; } - default: { + default: + { log_status("Invalid SLHV operations!!!"); abort(); } @@ -722,7 +715,8 @@ void z3_slhv_convt::dump_smt() { } } -void z3_slhv_convt::print_smt_formulae(std::ostream& dest) { +void z3_slhv_convt::print_smt_formulae(std::ostream& dest) +{ auto smt_formula = solver.to_smt2(); std::replace(smt_formula.begin(), smt_formula.end(), '\\', '_'); Z3_ast_vector __z3_assertions = Z3_solver_get_assertions(z3_ctx, solver); From 28ff0825cd30c76d9cc07916219a4a83db5145fb Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 10 Sep 2024 17:43:03 +0800 Subject: [PATCH 077/126] encode disjointness --- src/esbmc/bmc.cpp | 3 - src/goto-symex/builtin_functions.cpp | 10 +- src/goto-symex/goto_symex.h | 7 + src/goto-symex/slice.cpp | 26 +++ src/goto-symex/symex_assign.cpp | 28 +++ src/irep2/irep2.h | 7 +- src/irep2/irep2_expr.cpp | 16 ++ src/irep2/irep2_expr.h | 170 +++++++++++------- src/irep2/templates/irep2_templates.cpp | 2 + .../templates/irep2_templates_expr_data.cpp | 1 + src/solvers/z3-slhv/z3_slhv_conv.cpp | 13 +- src/util/migrate.cpp | 13 +- 12 files changed, 219 insertions(+), 77 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index b5e6c972..d35ad2ce 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -142,7 +142,6 @@ void bmct::generate_smt_from_equation( smt_convt &smt_conv, symex_target_equationt &eq) { - log_status("generate smt from equation"); std::string logic; if (options.get_bool_option("z3-slhv")) { @@ -192,8 +191,6 @@ bmct::run_decision_procedure(smt_convt &smt_conv, symex_target_equationt &eq) return dec_result; } - - void bmct::report_success() { log_success("\nVERIFICATION SUCCESSFUL"); diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 470eccf8..7c7d96fa 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -269,7 +269,15 @@ expr2tc goto_symext::symex_mem( rhs_base_loc, get_intheap_type(), gen_ulong(to_intheap_type(rhs_region->type).total_bytes)); - + + if (dynamic_memory.size() > 0) + { + expr2tc disj = disjh2tc(rhs_heap); + for (auto const &it : dynamic_memory) + to_disjh2t(disj).do_disjh(it.obj); + assume(disj); + } + log_status("use dynamic memory to track malloc heap - {}", to_symbol2t(rhs_heap).get_symbol_name()); dynamic_memory.emplace_back( diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 5ad203dc..3720171d 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -860,6 +860,13 @@ class goto_symext */ expr2tc create_heap_region(const sideeffect2t &effect, expr2tc &flag); + /** + * @brief Encode disjointness among all heap regions + * + * @param heap + */ + expr2tc symex_disj_heaps(const expr2tc &heap); + /** * @brief In SLHV, struct/array are heap variable * diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 477c0ecc..4ff70aae 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -59,6 +59,32 @@ void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) } return; } + else if (is_disjh2t(SSA_step.cond)) + { + disjh2t &disj = to_disjh2t(SSA_step.cond); + + if (!get_symbols(disj.source_heap)) + { + // we don't really need it + SSA_step.ignore = true; + ++sliced; + log_debug( + "slice", + "slice ignoring assignment to symbol {}", + to_symbol2t(SSA_step.lhs).get_symbol_name()); + } + else + { + get_symbols(SSA_step.guard); + get_symbols(SSA_step.cond); + } + + // for (unsigned int i = 0; i < disj.other_heaps.size(); i++) + // disj.is_sliced = !get_symbols(disj.other_heaps[i]); + + // for (unsigned int i = 0; i < disj.other_heaps.size(); i++) + // disj.is_sliced = !get_symbols(disj.other_heaps[i]); + } if (!slice_assumes) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 053c4435..dd6f28b0 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -923,6 +923,11 @@ void goto_symext::symex_assign_fieldof( heap_update2tc(heap_region->type, heap_region, field, rhs); symex_assign_rec(heap_region, full_lhs, update_heap, full_rhs, guard, hidden); + + expr2tc disj = disjh2tc(heap_region); + for (auto const& it : dynamic_memory) + to_disjh2t(disj).do_disjh(it.obj); + assume(disj); } void goto_symext::replace_nondet(expr2tc &expr) @@ -1159,6 +1164,27 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla return heap_region2tc(heap_type, base_loc); } +expr2tc goto_symext::symex_disj_heaps(const expr2tc &heap) +{ + if (!is_symbol2t(heap) || !is_intheap_type(heap)) + { + log_status("Wrong heap region"); + abort(); + } + + expr2tc l0_heap = heap; + cur_state->get_original_name(l0_heap); + + expr2tc disj; + for (auto const &it : dynamic_memory) + { + expr2tc h = it.obj; + if (to_symbol2t(h).get_symbol_name() + == to_symbol2t(l0_heap).get_symbol_name()) + continue; + } +} + void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) { log_status(" ======== symex nondet ===== "); @@ -1177,6 +1203,8 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); symex_assign(code_assign2tc(lhs, new_rhs)); + + // TODO : maybe added to set to do disjh if (is_intheap_type(new_lhs->type)) { diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index 941cb1c5..bdc232c5 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -103,12 +103,13 @@ BOOST_PP_LIST_CONS(with, \ BOOST_PP_LIST_CONS(member, \ BOOST_PP_LIST_CONS(index, \ + BOOST_PP_LIST_CONS(disjh, \ BOOST_PP_LIST_CONS(points_to, \ BOOST_PP_LIST_CONS(uplus, \ BOOST_PP_LIST_CONS(locadd, \ BOOST_PP_LIST_CONS(heap_region, \ - BOOST_PP_LIST_CONS(location_of, \ - BOOST_PP_LIST_CONS(field_of, \ + BOOST_PP_LIST_CONS(location_of, \ + BOOST_PP_LIST_CONS(field_of, \ BOOST_PP_LIST_CONS(heap_update, \ BOOST_PP_LIST_CONS(heap_append, \ BOOST_PP_LIST_CONS(heap_delete, \ @@ -153,7 +154,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 252ea1d5..8d87674f 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -74,6 +74,7 @@ static const char *expr_names[] = { "with", "member", "index", + "disjh", "points_to", "uplus", "locadd", @@ -489,6 +490,21 @@ arith_2ops::arith_2ops( #endif } + +void disjh2t::do_disjh(const expr2tc &heap) +{ + if (!is_intheap_type(heap) || + !is_symbol2t(heap)) + { + log_status("Wrong object"); + heap->dump(); + abort(); + } + + other_heaps.push_back(heap); + is_sliced.push_back(false); +} + expr2tc locadd2t::get_base_location() const { if (is_locadd2t(location)) diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index a5d12c6e..1dc0e29c 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -913,6 +913,94 @@ class index_data : public datatype_ops /* ================================ SLHV ================================ */ +class heap_ops : public expr2t +{ +public: + heap_ops( + const type2tc &t, + expr2t::expr_ids id, + const expr2tc &h) + : expr2t(t, id), source_heap(h) + { + } + heap_ops(const heap_ops& ref) = default; + + expr2tc source_heap; + + // Type mangling: + typedef esbmct::field_traits + source_heap_field; + typedef esbmct::expr2t_traits traits; +}; + +class heap_1op : public heap_ops +{ +public: + heap_1op( + const type2tc &t, + heap_ops::expr_ids id, + const expr2tc &h, + const expr2tc &op) + : heap_ops(t, id, h), operand(op) + { + } + heap_1op(const heap_1op &ref) = default; + + expr2tc operand; + + // Type mangling: + typedef esbmct::field_traits + operand_field; + typedef esbmct::expr2t_traits traits; +}; + +class heap_2ops : public heap_ops +{ +public: + heap_2ops( + const type2tc &t, + heap_ops::expr_ids id, + const expr2tc &h, + const expr2tc &op1, + const expr2tc &op2) + : heap_ops(t, id, h), operand_1(op1), operand_2(op2) + { + } + heap_2ops(const heap_2ops &ref) = default; + + expr2tc operand_1; + expr2tc operand_2; + + // Type mangling: + typedef esbmct::field_traits + operand_1_field; + typedef esbmct::field_traits + operand_2_field; + typedef esbmct::expr2t_traits< + source_heap_field, operand_1_field, operand_2_field> traits; +}; + +class disjh_data : public heap_ops +{ +public: + disjh_data(const type2tc &t, datatype_ops::expr_ids id, const expr2tc &h) + : heap_ops(t, id, h) + { + } + disjh_data(const disjh_data& ref) = default; + + std::vector other_heaps; + std::vector is_sliced; + + // Type mangling: + typedef esbmct::field_traits< + std::vector, disjh_data, &disjh_data::other_heaps> + other_heaps_field; + typedef esbmct::expr2t_traits< + heap_ops::source_heap_field, + other_heaps_field> traits; +}; + class points_to_data : public expr2t { public: @@ -1001,73 +1089,6 @@ class heap_region_data : public expr2t typedef esbmct::expr2t_traits traits; }; -class heap_ops : public expr2t -{ -public: - heap_ops( - const type2tc &t, - expr2t::expr_ids id, - const expr2tc &h) - : expr2t(t, id), source_heap(h) - { - } - heap_ops(const heap_ops& ref) = default; - - expr2tc source_heap; - - // Type mangling: - typedef esbmct::field_traits - source_heap_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_1op : public heap_ops -{ -public: - heap_1op( - const type2tc &t, - heap_ops::expr_ids id, - const expr2tc &h, - const expr2tc &op) - : heap_ops(t, id, h), operand(op) - { - } - heap_1op(const heap_1op &ref) = default; - - expr2tc operand; - - // Type mangling: - typedef esbmct::field_traits - operand_field; - typedef esbmct::expr2t_traits traits; -}; - -class heap_2ops : public heap_ops -{ -public: - heap_2ops( - const type2tc &t, - heap_ops::expr_ids id, - const expr2tc &h, - const expr2tc &op1, - const expr2tc &op2) - : heap_ops(t, id, h), operand_1(op1), operand_2(op2) - { - } - heap_2ops(const heap_2ops &ref) = default; - - expr2tc operand_1; - expr2tc operand_2; - - // Type mangling: - typedef esbmct::field_traits - operand_1_field; - typedef esbmct::field_traits - operand_2_field; - typedef esbmct::expr2t_traits< - source_heap_field, operand_1_field, operand_2_field> traits; -}; - /* ================================ SLHV ================================ */ class string_ops : public expr2t @@ -1696,6 +1717,7 @@ irep_typedefs(byte_update, byte_update_data); irep_typedefs(with, with_data); irep_typedefs(member, member_data); irep_typedefs(index, index_data); +irep_typedefs(disjh, disjh_data); irep_typedefs(points_to, points_to_data); irep_typedefs(uplus, uplus_data); irep_typedefs(locadd, locadd_data); @@ -3170,6 +3192,20 @@ class index2t : public index_expr_methods /* ================================ SLHV ================================ */ +class disjh2t : public disjh_expr_methods +{ +public: + disjh2t(const expr2tc &source_heap) + : disjh_expr_methods(get_bool_type(), disjh_id, source_heap) + { + } + disjh2t(const disjh2t &ref) = default; + + void do_disjh(const expr2tc &heap); + + static std::string field_names[esbmct::num_type_fields]; +}; + class points_to2t : public points_to_expr_methods { public: diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index 7d095045..a83dbe00 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -162,6 +162,8 @@ std::string member2t::field_names[esbmct::num_type_fields] = {"source_value", "member_name", "", "", ""}; std::string index2t::field_names[esbmct::num_type_fields] = {"source_value", "index", "", "", ""}; +std::string disjh2t::field_names[esbmct::num_type_fields] = + {"source_heap", "other_heaps", "", "", ""}; std::string points_to2t::field_names[esbmct::num_type_fields] = {"location", "content", "", "", ""}; std::string uplus2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index c0d743ef..17f46c06 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -57,6 +57,7 @@ expr_typedefs1(code_cpp_throw_decl_end, code_cpp_throw_decl_data); expr_typedefs3(extract, extract_data); +expr_typedefs1(disjh, disjh_data); expr_typedefs2(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); expr_typedefs2(locadd, locadd_data); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 12434ead..661f331c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -244,7 +244,6 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { case expr2t::pointer_object_id: case expr2t::same_object_id: - case expr2t::constant_intloc_id: case expr2t::constant_intheap_id: case expr2t::location_of_id: @@ -268,6 +267,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: + case expr2t::disjh_id: case expr2t::heap_region_id: case expr2t::location_of_id: case expr2t::field_of_id: @@ -427,6 +427,17 @@ z3_slhv_convt::convert_slhv_opts( return mk_emp(); case expr2t::constant_intloc_id: return mk_nil(); + case expr2t::disjh_id: + { + const disjh2t &disj = to_disjh2t(expr); + smt_astt res = mk_disjh(args[0], args[1]); + for (unsigned int i = 2; i <= disj.other_heaps.size(); i++) + { + smt_astt dis = mk_disjh(args[0], args[i]); + res = mk_and(res, dis); + } + return res; + } case expr2t::heap_region_id: { const intheap_type2t &_type = to_intheap_type(expr->type); diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 61510cf2..2d542601 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2605,6 +2605,16 @@ exprt migrate_expr_back(const expr2tc &ref) migrate_expr_back(ref2.source_value), migrate_expr_back(ref2.index)); return index; } + case expr2t::disjh_id: + { + const disjh2t &ref2 = to_disjh2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt disj("disjh", thetype); + disj.copy_to_operands(migrate_expr_back(ref2.source_heap)); + for (expr2tc h : ref2.other_heaps) + disj.copy_to_operands(migrate_expr_back(h)); + return disj; + } case expr2t::points_to_id: { const points_to2t &ref2 = to_points_to2t(ref); @@ -2621,9 +2631,8 @@ exprt migrate_expr_back(const expr2tc &ref) const uplus2t & ref2 = to_uplus2t(ref); typet thetype = migrate_type_back(ref->type); exprt uplus("uplus", thetype); - for(expr2tc op2 : ref2.heap_terms) { + for(expr2tc op2 : ref2.heap_terms) uplus.copy_to_operands(migrate_expr_back(op2)); - } return uplus; } case expr2t::locadd_id: From 303c6e72d25687c69e9f736cedd303ea8bb5bbbf Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 10 Sep 2024 19:40:05 +0800 Subject: [PATCH 078/126] fix slice for disjh --- src/goto-symex/goto_symex_state.cpp | 6 ---- src/goto-symex/slice.cpp | 43 ++++++++++-------------- src/goto-symex/symex_assign.cpp | 1 + src/goto-symex/symex_target_equation.cpp | 2 +- src/irep2/irep2_expr.cpp | 4 +++ src/solvers/z3-slhv/z3_slhv_conv.cpp | 12 ++++--- 6 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 9ac76f27..2a20e675 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -273,12 +273,6 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } - else if (is_location_of2t(expr)) - { - location_of2t &loc_of = to_location_of2t(expr); - // Only do l1 rename - rename_address(loc_of.source_heap); - } else { // do this recursively diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 4ff70aae..23754586 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -40,50 +40,43 @@ void symex_slicet::run_on_assert(symex_target_equationt::SSA_stept &SSA_step) void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) { + bool is_special_assume = false; + bool is_sliced = false; if (SSA_step.is_assign_to_assume) { + is_special_assume = true; if (!get_symbols(SSA_step.lhs)) - { - // we don't really need it - SSA_step.ignore = true; - ++sliced; - log_debug( - "slice", - "slice ignoring assignment to symbol {}", - to_symbol2t(SSA_step.lhs).get_symbol_name()); - } + is_sliced = true; else { + get_symbols(SSA_step.guard); get_symbols(SSA_step.cond); depends.erase(to_symbol2t(SSA_step.lhs).get_symbol_name()); } - return; } else if (is_disjh2t(SSA_step.cond)) { + is_special_assume = true; disjh2t &disj = to_disjh2t(SSA_step.cond); if (!get_symbols(disj.source_heap)) + is_sliced = true; + else + { + for (unsigned int i = 0; i < disj.other_heaps.size(); i++) + get_symbols(disj.other_heaps[i]); + } + } + + if (is_special_assume) + { + if (is_sliced) { // we don't really need it SSA_step.ignore = true; ++sliced; - log_debug( - "slice", - "slice ignoring assignment to symbol {}", - to_symbol2t(SSA_step.lhs).get_symbol_name()); - } - else - { - get_symbols(SSA_step.guard); - get_symbols(SSA_step.cond); } - - // for (unsigned int i = 0; i < disj.other_heaps.size(); i++) - // disj.is_sliced = !get_symbols(disj.other_heaps[i]); - - // for (unsigned int i = 0; i < disj.other_heaps.size(); i++) - // disj.is_sliced = !get_symbols(disj.other_heaps[i]); + return; } if (!slice_assumes) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index dd6f28b0..de26ddd1 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -925,6 +925,7 @@ void goto_symext::symex_assign_fieldof( symex_assign_rec(heap_region, full_lhs, update_heap, full_rhs, guard, hidden); expr2tc disj = disjh2tc(heap_region); + cur_state->get_original_name(disj); for (auto const& it : dynamic_memory) to_disjh2t(disj).do_disjh(it.obj); assume(disj); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 818e1be7..0657f7a6 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -220,7 +220,7 @@ void symex_target_equationt::convert_internal_step( assert(0 && "Unexpected SSA step type in conversion"); } - if (step.is_assign_to_assume) + if (step.is_assign_to_assume || is_disjh2t(step.cond)) { smt_conv.assert_ast(step.cond_ast); } diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 8d87674f..16db9384 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -501,6 +501,10 @@ void disjh2t::do_disjh(const expr2tc &heap) abort(); } + if (to_symbol2t(source_heap).get_symbol_name() == + to_symbol2t(heap).get_symbol_name()) + return; + other_heaps.push_back(heap); is_sliced.push_back(false); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 661f331c..33e993aa 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -430,13 +430,15 @@ z3_slhv_convt::convert_slhv_opts( case expr2t::disjh_id: { const disjh2t &disj = to_disjh2t(expr); - smt_astt res = mk_disjh(args[0], args[1]); - for (unsigned int i = 2; i <= disj.other_heaps.size(); i++) + int n = 0; + smt_astt res; + for (unsigned int i = 0; i < disj.other_heaps.size(); i++) { - smt_astt dis = mk_disjh(args[0], args[i]); - res = mk_and(res, dis); + smt_astt disj = mk_disjh(args[0], args[i + 1]); + res = n == 0 ? disj : mk_and(res, disj); + ++n; } - return res; + return n == 0 ? mk_smt_bool(true) : res; } case expr2t::heap_region_id: { From 966c861931a73e8c2b660f26f4a86b525ff2f26c Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 11 Sep 2024 17:20:06 +0800 Subject: [PATCH 079/126] add property info --- src/esbmc/bmc.cpp | 25 +++++++++++++++++++++---- src/solvers/z3-slhv/z3_slhv_conv.cpp | 11 ++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index d35ad2ce..8c180f2c 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -780,17 +780,34 @@ smt_convt::resultt bmct::multi_property_check( std::unique_ptr runtime_solver(create_solver("", ns, options)); // Save current instance generate_smt_from_equation(*runtime_solver, local_eq); - + + fine_timet sat_start = current_time(); + smt_convt::resultt result = runtime_solver->dec_solve(); + fine_timet sat_stop = current_time(); + + log_status("---------------------------------------------"); log_status( "Solving claim '{}' with solver {}", claim.claim_msg, runtime_solver->solver_text()); + + for (auto it = local_eq.SSA_steps.begin(); + it != local_eq.SSA_steps.end(); + it++) + if (it->is_assert() && !it->ignore) + { + log_status("{}", it->source.pc->location); + log_status("{}", it->comment); + break; + } + log_status("Dec result - {}", + result == smt_convt::P_SATISFIABLE ? "sat" : + result == smt_convt::P_UNSATISFIABLE ? "unsat" : + "error"); - fine_timet sat_start = current_time(); - smt_convt::resultt result = runtime_solver->dec_solve(); - fine_timet sat_stop = current_time(); log_status( "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); + log_status("---------------------------------------------"); // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 33e993aa..035da5da 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -52,9 +52,8 @@ z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } -smt_convt::resultt z3_slhv_convt::dec_solve() { - log_status("z3-slhv debug: before slhv check"); - +smt_convt::resultt z3_slhv_convt::dec_solve() +{ const std::string &path = options.get_option("output"); if (path != "-") { @@ -68,12 +67,6 @@ smt_convt::resultt z3_slhv_convt::dec_solve() { z3::check_result result = solver.check(); - log_status("z3-slhv debug: after check"); - log_status("Dec result - {}", - result == z3::sat ? "sat" : - result == z3::unsat ? "unsat" : - "error"); - if (result == z3::sat) return P_SATISFIABLE; From d6abd683b1672314522734825af16376343694dc Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 12 Sep 2024 11:20:44 +0800 Subject: [PATCH 080/126] slice for disjointness --- src/goto-symex/slice.cpp | 24 +++++++++++++++------- src/goto-symex/slice.h | 13 ++++++++++++ src/pointer-analysis/dereference.cpp | 30 +++++++++------------------- src/solvers/z3-slhv/z3_slhv_conv.cpp | 3 ++- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 23754586..c93c521f 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -51,7 +51,6 @@ void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) { get_symbols(SSA_step.guard); get_symbols(SSA_step.cond); - depends.erase(to_symbol2t(SSA_step.lhs).get_symbol_name()); } } else if (is_disjh2t(SSA_step.cond)) @@ -61,11 +60,6 @@ void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) if (!get_symbols(disj.source_heap)) is_sliced = true; - else - { - for (unsigned int i = 0; i < disj.other_heaps.size(); i++) - get_symbols(disj.other_heaps[i]); - } } if (is_special_assume) @@ -141,7 +135,7 @@ void symex_slicet::run_on_assignment(symex_target_equationt::SSA_stept &SSA_step // Remove this symbol as we won't be seeing any references to it further // into the history. - depends.erase(to_symbol2t(SSA_step.lhs).get_symbol_name()); + // depends.erase(to_symbol2t(SSA_step.lhs).get_symbol_name()); } } @@ -248,6 +242,7 @@ bool claim_slicer::run(symex_target_equationt::SSA_stepst &steps) return true; } + // Recursively try to extract the nondet symbol of an expression expr2tc symex_slicet::get_nondet_symbol(const expr2tc &expr) { @@ -279,4 +274,19 @@ expr2tc symex_slicet::get_nondet_symbol(const expr2tc &expr) default: return expr2tc(); } +} + +void symex_slicet::run_on_disjhs(symex_target_equationt::SSA_stepst &eq) +{ + for (auto &step : eq) + { + if (step.ignore) continue; + if (!step.is_assume()) continue; + if (!is_disjh2t(step.cond)) continue; + disjh2t &disj = to_disjh2t(step.cond); + log_status("run on disjhs"); + disj.dump(); + for (unsigned int i = 0; i < disj.other_heaps.size(); i++) + disj.is_sliced[i] = !get_symbols(disj.other_heaps[i]); + } } \ No newline at end of file diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index 8adc25a8..a75ad111 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -103,6 +103,10 @@ class symex_slicet : public slicer if (step.ignore) continue; run_on_step(step); } + + // added needed heap vars for their disjointness + run_on_disjhs(eq); + fine_timet algorithm_stop = current_time(); log_status( "Slicing time: {}s (removed {} assignments)", @@ -222,6 +226,15 @@ class symex_slicet : public slicer * @param SSA_step an renumber step */ void run_on_renumber(symex_target_equationt::SSA_stept &SSA_step) override; + +private: + + /** + * @brief Add disjointness of connected heap variables + * + * @param eq + */ + void run_on_disjhs(symex_target_equationt::SSA_stepst &eq); }; #endif diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 8e1f3be5..71ebf5d8 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -2519,13 +2519,9 @@ void dereferencet::check_heap_region_access( const guardt &guard, modet mode) { - // This check is in word-level; + if(options.get_bool_option("no-bounds-check")) return; - // log_status(" ------------------ check heap region access ------------------ "); - // value->dump(); - // offset->dump(); - // type->dump(); - // guard.dump(); + // This check is in word-level; expr2tc offset_cond; if (is_intheap_type(value)) @@ -2552,22 +2548,14 @@ void dereferencet::check_heap_region_access( offset_cond = equality2tc(offset, gen_ulong(0)); } - // log_status("offset condition:"); - // offset_cond->dump(); - expr2tc bound_check = not2tc(offset_cond); - if(!options.get_bool_option("no-bounds-check")) - { - guardt tmp_guard = guard; - tmp_guard.add(bound_check); - dereference_failure( - "pointer dereference", - "Access of heap out of region", - tmp_guard - ); - } - - // log_status(" ------------------ check heap region access ------------------ "); + guardt tmp_guard = guard; + tmp_guard.add(offset_cond); + dereference_failure( + "pointer dereference", + "Access of heap out of region", + tmp_guard + ); } void dereferencet::check_alignment( diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 035da5da..31ab3683 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -195,7 +195,7 @@ void z3_slhv_convt::collect_heap_state(smt_astt &a) to_solver_smt_ast(heap_state)->a.simplify(), mk_bool_sort() ); - a = mk_and(simp, a); + a = mk_implies(simp, a); heap_state = mk_smt_bool(true); } @@ -427,6 +427,7 @@ z3_slhv_convt::convert_slhv_opts( smt_astt res; for (unsigned int i = 0; i < disj.other_heaps.size(); i++) { + if (disj.is_sliced[i]) continue; smt_astt disj = mk_disjh(args[0], args[i + 1]); res = n == 0 ? disj : mk_and(res, disj); ++n; From 7b46dc91d0f874f9ed9728c1483473a587fb4308 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 12 Sep 2024 12:29:02 +0800 Subject: [PATCH 081/126] fix heap state encoding --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 67 +++++----------------------- src/solvers/z3-slhv/z3_slhv_conv.h | 3 -- 2 files changed, 10 insertions(+), 60 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 31ab3683..03421798 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -186,39 +186,6 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { } } -void z3_slhv_convt::collect_heap_state(smt_astt &a) -{ - if (to_solver_smt_ast(heap_state)->a.is_true()) - return; - smt_astt simp = - new_ast( - to_solver_smt_ast(heap_state)->a.simplify(), - mk_bool_sort() - ); - a = mk_implies(simp, a); - heap_state = mk_smt_bool(true); -} - -smt_astt z3_slhv_convt::convert_assign(const expr2tc &expr) -{ - const equality2t &eq = to_equality2t(expr); - smt_astt side1 = convert_ast(eq.side_1); // LHS - smt_astt side2 = convert_ast(eq.side_2); // RHS - - smt_astt a = mk_eq(side1, side2); - collect_heap_state(a); - assert_ast(a); - - // Put that into the smt cache, thus preserving the value of the assigned symbols. - // IMPORTANT: the cache is now a fundamental part of how some flatteners work, - // in that one can choose to create a set of expressions and their ASTs, then - // store them in the cache, rather than have a more sophisticated conversion. - smt_cache_entryt e = {eq.side_1, a, ctx_level}; - smt_cache.insert(e); - - return side2; -} - smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { log_status("------------------------------- convert ast -----------------------------"); @@ -240,12 +207,8 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) case expr2t::constant_intloc_id: case expr2t::constant_intheap_id: case expr2t::location_of_id: - case expr2t::field_of_id: case expr2t::heap_region_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: break; // Don't convert their operands - default: { // Convert all the arguments and store them in 'args'. @@ -399,8 +362,6 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) } } - if (is_bool_type(expr->type)) collect_heap_state(a); - struct smt_cache_entryt entry = {expr, a, ctx_level}; smt_cache.insert(entry); @@ -529,8 +490,6 @@ z3_slhv_convt::convert_slhv_opts( } return h; } - case expr2t::add_id: - case expr2t::sub_id: case expr2t::locadd_id: { assert(args.size() == 2); @@ -597,12 +556,8 @@ z3_slhv_convt::convert_slhv_opts( } smt_astt v1 = mk_fresh(s1, name); - // assert_ast(mk_subh(mk_pt(loc, v1), convert_ast(heap_region))); - heap_state = - mk_and( - heap_state, - mk_subh(mk_pt(loc, v1), convert_ast(heap_region)) - ); + // current heap state + assert_ast(mk_subh(mk_pt(loc, v1), args[0])); return v1; } case expr2t::heap_update_id: @@ -621,9 +576,9 @@ z3_slhv_convt::convert_slhv_opts( unsigned int _field = to_constant_int2t(upd_field).value.to_uint64(); - smt_astt h = convert_ast(heap_region); + smt_astt h = args[0]; smt_astt source_loc = convert_ast(_type.location); - smt_astt field = convert_ast(upd_field); + smt_astt field = args[1]; smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, field); smt_astt val = convert_ast(upd_value); @@ -632,25 +587,23 @@ z3_slhv_convt::convert_slhv_opts( // current heap state smt_astt old_state = mk_uplus(h1, mk_pt(loc, v1)); - // assert_ast(mk_eq(h, old_state)); - heap_state = mk_and(heap_state, mk_eq(h, old_state)); + assert_ast(mk_eq(h, old_state)); // new heap state - smt_astt new_state = mk_uplus(h1, mk_pt(loc, val)); - return new_state; + return mk_uplus(h1, mk_pt(loc, val)); } case expr2t::heap_delete_id: { const heap_delete2t &heap_del = to_heap_delete2t(expr); - smt_astt h = convert_ast(heap_del.source_heap); - smt_astt l = convert_ast(heap_del.operand); + smt_astt h = args[0]; + smt_astt l = args[1]; smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - // assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); - heap_state = mk_and(heap_state, mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); + // current heap state + assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); return h1; } case expr2t::same_object_id: diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 583e616c..2f53f0b4 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -40,9 +40,7 @@ class z3_slhv_convt : public z3_convt { smt_sortt convert_slhv_sorts(const type2tc &type) override; - // To support encoding heap state, we override default convert smt_astt convert_ast(const expr2tc &expr) override; - smt_astt convert_assign(const expr2tc &expr); smt_astt convert_slhv_opts(const expr2tc &expr, const std::vector& args) override; @@ -52,7 +50,6 @@ class z3_slhv_convt : public z3_convt { void dump_smt() override; private: - void collect_heap_state(smt_astt &a); void print_smt_formulae(std::ostream& dest); std::vector assertions; From cd1c22054e30c8447361288ee5dcbccb45e4bae3 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 12 Sep 2024 12:33:17 +0800 Subject: [PATCH 082/126] fix bound check --- src/goto-symex/slice.cpp | 2 -- src/pointer-analysis/dereference.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index c93c521f..7fa8001f 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -284,8 +284,6 @@ void symex_slicet::run_on_disjhs(symex_target_equationt::SSA_stepst &eq) if (!step.is_assume()) continue; if (!is_disjh2t(step.cond)) continue; disjh2t &disj = to_disjh2t(step.cond); - log_status("run on disjhs"); - disj.dump(); for (unsigned int i = 0; i < disj.other_heaps.size(); i++) disj.is_sliced[i] = !get_symbols(disj.other_heaps[i]); } diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 71ebf5d8..adb8a52a 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -2550,7 +2550,7 @@ void dereferencet::check_heap_region_access( expr2tc bound_check = not2tc(offset_cond); guardt tmp_guard = guard; - tmp_guard.add(offset_cond); + tmp_guard.add(bound_check); dereference_failure( "pointer dereference", "Access of heap out of region", From 6d71238e1f3edd4f01ed22b3dccaf16c33e5d011 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 12 Sep 2024 14:07:49 +0800 Subject: [PATCH 083/126] fix l2 name of location_of --- src/goto-symex/builtin_functions.cpp | 1 + src/goto-symex/goto_symex_state.cpp | 5 +++++ src/goto-symex/symex_assign.cpp | 4 +--- src/pointer-analysis/dereference.cpp | 5 +++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 7c7d96fa..c36ac7c9 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -288,6 +288,7 @@ expr2tc goto_symext::symex_mem( ); log_status("create valueset base loc symbol and assign"); + cur_state->rename(rhs_heap); symex_assign(code_assign2tc(lhs, location_of2tc(rhs_heap))); return expr2tc(); diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 2a20e675..22fc4044 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -273,6 +273,11 @@ void goto_symex_statet::rename(expr2tc &expr) address_of2t &addrof = to_address_of2t(expr); rename_address(addrof.ptr_obj); } + else if (is_location_of2t(expr)) + { + location_of2t &locof = to_location_of2t(expr); + rename_address(locof.source_heap); + } else { // do this recursively diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index de26ddd1..2653f0e5 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -1014,12 +1014,10 @@ void goto_symext::replace_address_of(expr2tc &expr) { if (is_nil_expr(expr)) return; - expr->Foreach_operand([this](expr2tc &e) { replace_pointer_airth(e); }); + expr->Foreach_operand([this](expr2tc &e) { replace_address_of(e); }); if (is_address_of2t(expr)) - { expr = location_of2tc(to_address_of2t(expr).ptr_obj); - } } void goto_symext::replace_typecast(expr2tc &expr) diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index adb8a52a..3dc1f1bb 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -590,6 +590,11 @@ bool dereferencet::dereference_type_compare( // Test for simple equality if (object->type == dereference_type) return true; + + // intloc is pointer + if (is_intloc_type(object->type) && is_pointer_type(dereference_type) || + is_pointer_type(object->type) && is_intloc_type(dereference_type)) + return true; // Check for C++ subclasses; we can cast derived up to base safely. if (is_struct_type(object) && is_struct_type(dereference_type)) From d0cc43756d440e0e3ea086844fdd197dcc4737fc Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 13 Sep 2024 15:08:38 +0800 Subject: [PATCH 084/126] fit slhv load operation --- src/goto-symex/builtin_functions.cpp | 8 +- src/goto-symex/dynamic_allocation.cpp | 25 ++++- src/goto-symex/slice.cpp | 24 +---- src/goto-symex/symex_assign.cpp | 24 ++--- src/goto-symex/symex_target.h | 4 +- src/goto-symex/symex_target_equation.cpp | 127 +++++++++++++++++++++-- src/goto-symex/symex_target_equation.h | 14 ++- src/irep2/irep2_expr.cpp | 15 ++- src/irep2/irep2_expr.h | 2 +- src/pointer-analysis/dereference.cpp | 25 +++-- src/solvers/z3-slhv/z3_slhv_conv.cpp | 51 +++++++-- src/solvers/z3-slhv/z3_slhv_conv.h | 9 +- 12 files changed, 233 insertions(+), 95 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index c36ac7c9..1fca2b36 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -275,7 +275,13 @@ expr2tc goto_symext::symex_mem( expr2tc disj = disjh2tc(rhs_heap); for (auto const &it : dynamic_memory) to_disjh2t(disj).do_disjh(it.obj); - assume(disj); + cur_state->rename(disj); + target->assumption( + cur_state->guard.as_expr(), + disj, + cur_state->source, + first_loop + ); } log_status("use dynamic memory to track malloc heap - {}", diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 5b02f3d7..9cb9dae7 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -95,13 +95,30 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc size_sym = symbol2tc( get_int64_type(), - std::string("INVALID_SIZE_") + std::to_string(nondet_counter) + std::string("SOME_SIZE_") + std::to_string(nondet_counter) ); - expr2tc pt = points_to2tc(obj_expr, size_sym); - expr2tc heap_ct = heap_contain2tc(alloc_size_heap, pt); + expr2tc loc; + expr2tc extra_eq; + if (!is_if2t(obj_expr)) + loc = obj_expr; + else + { + loc = + symbol2tc( + get_int64_type(), + std::string("assigned_loc_") + std::to_string(nondet_counter) + ); + extra_eq = equality2tc(loc, obj_expr); + } + + expr2tc pt = points_to2tc(loc, size_sym); + expr2tc is_invalid = disjh2tc(alloc_size_heap); + to_disjh2t(is_invalid).do_disjh(pt); + if (!is_nil_expr(extra_eq)) + is_invalid = and2tc(extra_eq, is_invalid); - expr = not2tc(heap_ct); + expr = is_invalid; } } else if (is_deallocated_obj2t(expr)) diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 7fa8001f..0f96e3f8 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -40,33 +40,11 @@ void symex_slicet::run_on_assert(symex_target_equationt::SSA_stept &SSA_step) void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) { - bool is_special_assume = false; - bool is_sliced = false; - if (SSA_step.is_assign_to_assume) + if (is_disjh2t(SSA_step.cond)) { - is_special_assume = true; - if (!get_symbols(SSA_step.lhs)) - is_sliced = true; - else - { - get_symbols(SSA_step.guard); - get_symbols(SSA_step.cond); - } - } - else if (is_disjh2t(SSA_step.cond)) - { - is_special_assume = true; disjh2t &disj = to_disjh2t(SSA_step.cond); - if (!get_symbols(disj.source_heap)) - is_sliced = true; - } - - if (is_special_assume) - { - if (is_sliced) { - // we don't really need it SSA_step.ignore = true; ++sliced; } diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 2653f0e5..0f962840 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -400,22 +400,6 @@ void goto_symext::symex_assign_symbol( guardt tmp_guard(cur_state->guard); tmp_guard.append(guard); - if (has_cond_expr(rhs)) - { - // Transfer assignment to assume - expr2tc new_cond = transfer_to_assume(rhs, expr2tc(), renamed_lhs); - - target->assumption( - tmp_guard.as_expr(), - new_cond, - cur_state->source, - first_loop, - renamed_lhs, - true - ); - return; - } - // do the assignment target->assignment( tmp_guard.as_expr(), @@ -928,7 +912,13 @@ void goto_symext::symex_assign_fieldof( cur_state->get_original_name(disj); for (auto const& it : dynamic_memory) to_disjh2t(disj).do_disjh(it.obj); - assume(disj); + cur_state->rename(disj); + target->assumption( + cur_state->guard.as_expr(), + disj, + cur_state->source, + first_loop + ); } void goto_symext::replace_nondet(expr2tc &expr) diff --git a/src/goto-symex/symex_target.h b/src/goto-symex/symex_target.h index 4da2ac8f..643a85bc 100644 --- a/src/goto-symex/symex_target.h +++ b/src/goto-symex/symex_target.h @@ -59,9 +59,7 @@ class symex_targett const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number, - const expr2tc &lhs = expr2tc(), // use to assign-to_assume - const bool is_assign_to_assume = false) = 0; + unsigned loop_number) = 0; // record an assertion // cond is destroyed diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 0657f7a6..1c33ed2b 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -73,9 +73,7 @@ void symex_target_equationt::assumption( const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number, - const expr2tc &lhs, - const bool is_assign_to_assume) + unsigned loop_number) { SSA_steps.emplace_back(); SSA_stept &SSA_step = SSA_steps.back(); @@ -85,9 +83,6 @@ void symex_target_equationt::assumption( SSA_step.type = goto_trace_stept::ASSUME; SSA_step.source = source; SSA_step.loop_number = loop_number; - SSA_step.is_assign_to_assume = is_assign_to_assume; - - if (is_assign_to_assume) SSA_step.lhs = lhs; if (debug_print) debug_print_step(SSA_step); @@ -142,8 +137,21 @@ void symex_target_equationt::convert(smt_convt &smt_conv) smt_convt::ast_vec assertions; smt_astt assumpt_ast = smt_conv.convert_ast(gen_true_expr()); - for (auto &SSA_step : SSA_steps) + for (auto SSA_step : SSA_steps) + { + if (!SSA_step.ignore && has_cond_val(SSA_step.cond)) + { + log_status("========================================================"); + log_status("before reconstruct : "); + SSA_step.cond->dump(); + reconstruct_cond_expr(SSA_step.cond); + + log_status("after reconstruct : "); + SSA_step.cond->dump(); + log_status("========================================================"); + } convert_internal_step(smt_conv, assumpt_ast, assertions, SSA_step); + } if (!assertions.empty()) smt_conv.assert_ast(smt_conv.make_n_ary_or(assertions)); @@ -184,10 +192,19 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_assignment()) { - smt_astt assign = smt_conv.convert_assign(step.cond); - if (ssa_smt_trace) + if (!is_equality2t(step.cond) || + is_field_of2t(to_equality2t(step.cond).side_2)) { - assign->dump(); + smt_astt assign = smt_conv.convert_ast(step.cond); + smt_conv.assert_ast(assign); + } + else + { + smt_astt assign = smt_conv.convert_assign(step.cond); + if (ssa_smt_trace) + { + assign->dump(); + } } } else if (step.is_output()) @@ -220,7 +237,7 @@ void symex_target_equationt::convert_internal_step( assert(0 && "Unexpected SSA step type in conversion"); } - if (step.is_assign_to_assume || is_disjh2t(step.cond)) + if (is_disjh2t(step.cond)) { smt_conv.assert_ast(step.cond_ast); } @@ -426,6 +443,94 @@ void symex_target_equationt::reconstruct_symbolic_expression( } } +void symex_target_equationt::reconstruct_cond_expr(expr2tc &expr) +{ + if (is_nil_expr(expr)) return; + + expr->Foreach_operand([this](expr2tc &e){ + reconstruct_cond_expr(e); + }); + + switch (expr->expr_id) + { + case expr2t::same_object_id: + case expr2t::equality_id: + { + expr2tc side_1 = + is_equality2t(expr) ? + to_equality2t(expr).side_1 : to_same_object2t(expr).side_1; + expr2tc side_2 = + is_equality2t(expr) ? + to_equality2t(expr).side_2 : to_same_object2t(expr).side_2; + + if (!has_cond_val(side_1) && !has_cond_val(side_2)) break; + + cond_val_set s1, s2; + get_cond_val(side_1, constant_bool2tc(true), s1); + get_cond_val(side_2, constant_bool2tc(true), s2); + + expr2tc new_expr; + int n = 0; + for (const cond_val &v1 : s1) + for (const cond_val &v2 : s2) + { + expr2tc cond = and2tc(v1.first, v2.first); + simplify(cond); + expr2tc bexpr = + is_equality2t(expr) ? + equality2tc(v1.second, v2.second) : + same_object2tc(v1.second, v2.second); + simplify(bexpr); + expr2tc e = and2tc(cond, bexpr); + new_expr = (n == 0) ? e : or2tc(new_expr, e); + n++; + } + expr = new_expr; + break; + } + // add more cases if exists + default: + break; + } +} + +void symex_target_equationt::get_cond_val( + const expr2tc &expr, const expr2tc &cond, cond_val_set &s) +{ + if (is_if2t(expr)) + { + const if2t &_if = to_if2t(expr); + + expr2tc true_cond = and2tc(cond, _if.cond); + expr2tc false_cond = and2tc(cond, not2tc(_if.cond)); + + get_cond_val(_if.true_value, true_cond, s); + get_cond_val(_if.false_value, false_cond, s); + return; + } + else if (is_typecast2t(expr)) + { + get_cond_val(to_typecast2t(expr).from, cond, s); + return; + } + + s.push_back(std::make_pair(cond, expr)); +} + +bool symex_target_equationt::has_cond_val(const expr2tc &expr, bool is_in_if) +{ + if (is_nil_expr(expr)) return false; + if (is_field_of2t(expr)) return is_in_if; + + is_in_if |= is_if2t(expr); + bool has_cond = false; + expr->foreach_operand([this, &has_cond, &is_in_if](const expr2tc &e) { + has_cond |= has_cond_val(e, is_in_if); + }); + + return has_cond; +} + runtime_encoded_equationt::runtime_encoded_equationt( const namespacet &_ns, smt_convt &_conv) diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index b7673f3c..f69456d8 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -54,9 +54,7 @@ class symex_target_equationt : public symex_targett const expr2tc &guard, const expr2tc &cond, const sourcet &source, - unsigned loop_number, - const expr2tc &lhs = expr2tc(), - const bool is_assign_to_assume = false) override; + unsigned loop_number) override; // record an assertion // cond is destroyed @@ -131,7 +129,6 @@ class symex_target_equationt : public symex_targett // for ASSUME/ASSERT expr2tc cond; std::string comment; - bool is_assign_to_assume; // for OUTPUT std::string format_string; @@ -150,7 +147,7 @@ class symex_target_equationt : public symex_targett // for bidirectional search unsigned loop_number; - SSA_stept() : ignore(false), hidden(false), is_assign_to_assume(false) + SSA_stept() : ignore(false), hidden(false) { } @@ -207,6 +204,8 @@ class symex_target_equationt : public symex_targett void push_ctx() override; void pop_ctx() override; + void reconstruct_cond_expr(expr2tc &expr); + protected: const namespacet &ns; @@ -216,6 +215,11 @@ class symex_target_equationt : public symex_targett private: void debug_print_step(const SSA_stept &step) const; + + typedef std::pair cond_val; + typedef std::vector cond_val_set; + void get_cond_val(const expr2tc &expr, const expr2tc &cond, cond_val_set &s); + bool has_cond_val(const expr2tc &expr, bool is_in_if = false); }; class runtime_encoded_equationt : public symex_target_equationt diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 16db9384..788034f0 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -490,22 +490,21 @@ arith_2ops::arith_2ops( #endif } - -void disjh2t::do_disjh(const expr2tc &heap) +void disjh2t::do_disjh(const expr2tc &heap_term) { - if (!is_intheap_type(heap) || - !is_symbol2t(heap)) + if (!is_intheap_type(heap_term)) { log_status("Wrong object"); - heap->dump(); + heap_term->dump(); abort(); } - if (to_symbol2t(source_heap).get_symbol_name() == - to_symbol2t(heap).get_symbol_name()) + if (is_symbol2t(heap_term) && + to_symbol2t(source_heap).get_symbol_name() == + to_symbol2t(heap_term).get_symbol_name()) return; - other_heaps.push_back(heap); + other_heaps.push_back(heap_term); is_sliced.push_back(false); } diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index 1dc0e29c..efa48dd2 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -3201,7 +3201,7 @@ class disjh2t : public disjh_expr_methods } disjh2t(const disjh2t &ref) = default; - void do_disjh(const expr2tc &heap); + void do_disjh(const expr2tc &heap_term); static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 3dc1f1bb..46b8e4bb 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1243,32 +1243,31 @@ void dereferencet::build_deref_slhv( abort(); } - bool is_field = true; if (field >= _type.field_types.size() || access_sz != _type.total_bytes / _type.field_types.size()) { // Out of bound or unaligned - undefined behavior - expr2tc sym = symbol2tc( - type, - dereference_callback.get_nondet_id("undefined_behavior_var")); - value = sym; - is_field = false; + // expr2tc sym = symbol2tc( + // type, + // dereference_callback.get_nondet_id("undefined_behavior_var")); + // value = sym; + value = expr2tc(); } else + { value = field_of2tc(type, value, gen_ulong(field)); - - // update field type - if (is_field && _type.set_field_type(field, type)) - dereference_callback.update_heap_type(_type); + // update field type + if (_type.set_field_type(field, type)) + dereference_callback.update_heap_type(_type); + } } else { // pointer - return itself } - - log_status("return dereference --->"); - value->dump(); + log_status("return dereference ---> {}", !is_nil_expr(value)); + if (!is_nil_expr(value)) value->dump(); log_status(" ----------------- build deref slhv ----------------- "); } diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 03421798..955b3958 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -43,7 +43,7 @@ smt_convt *create_new_z3_slhv_solver( } z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) - : z3_convt(_ns, _options), heap_state(mk_smt_bool(true)) { + : z3_convt(_ns, _options), loaded_state(mk_smt_bool(true)) { // initialize the z3 based slhv converter here int_encoding = true; solver = z3::solver(z3_ctx, "SLHV"); @@ -186,6 +186,22 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { } } +smt_astt z3_slhv_convt::convert_assign(const expr2tc &expr) +{ + const equality2t &eq = to_equality2t(expr); + smt_astt side1 = convert_ast(eq.side_1); // LHS + smt_astt side2 = convert_ast(eq.side_2); // RHS + + smt_astt a = mk_eq(side1, side2); + collect_loaded_state(a); + assert_ast(a); + + smt_cache_entryt e = {eq.side_1, side2, ctx_level}; + smt_cache.insert(e); + + return a; +} + smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { log_status("------------------------------- convert ast -----------------------------"); @@ -207,6 +223,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) case expr2t::constant_intloc_id: case expr2t::constant_intheap_id: case expr2t::location_of_id: + case expr2t::field_of_id: case expr2t::heap_region_id: break; // Don't convert their operands default: @@ -264,6 +281,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) args[0] = this->project(so.side_1); args[1] = this->project(so.side_2); a = mk_eq(args[0], args[1]); + collect_loaded_state(a); break; } case expr2t::pointer_object_id: @@ -348,6 +366,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) case expr2t::and_id: { a = mk_and(args[0], args[1]); + collect_loaded_state(a); break; } case expr2t::or_id: @@ -537,27 +556,29 @@ z3_slhv_convt::convert_slhv_opts( const expr2tc &field = field_of.operand; unsigned int _field = to_constant_int2t(field).value.to_uint64(); + smt_astt h = convert_ast(heap_region); smt_astt source_loc = convert_ast(_type.location); smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, convert_ast(field)); smt_sortt s1; - std::string name; + std::string n1; if (!_type.is_aligned) { s1 = mk_intloc_sort(); - name = mk_fresh_name("tmp_loc::"); + n1 = mk_fresh_name("tmp_loc::"); } else { s1 = is_intloc_type(_type.field_types[_field]) ? mk_intloc_sort() : mk_int_sort(); - name = mk_fresh_name( + n1 = mk_fresh_name( is_intloc_type(_type.field_types[_field]) ? "tmp_loc::" : "tmp_val::"); } - smt_astt v1 = mk_fresh(s1, name); + smt_astt v1 = mk_fresh(s1, n1); // current heap state - assert_ast(mk_subh(mk_pt(loc, v1), args[0])); + smt_astt heap_state = mk_subh(mk_pt(loc, v1), h); + add_loaded_state(heap_state); return v1; } case expr2t::heap_update_id: @@ -654,7 +675,7 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) const if2t &_if = to_if2t(expr); smt_astt cond = convert_ast(_if.cond); smt_astt t = this->project(_if.true_value); - smt_astt f = this->project(_if.true_value); + smt_astt f = this->project(_if.false_value); return mk_ite(cond, t, f); } else @@ -697,4 +718,20 @@ void z3_slhv_convt::print_smt_formulae(std::ostream& dest) log_status( "Total number of safety properties: {}", Z3_ast_vector_size(z3_ctx, __z3_assertions)); +} + +void z3_slhv_convt::add_loaded_state(smt_astt a) +{ + if (to_solver_smt_ast(loaded_state)->a.is_true()) + loaded_state = a; + else + loaded_state = mk_and(loaded_state, a); +} + +void z3_slhv_convt::collect_loaded_state(smt_astt &a) +{ + if (to_solver_smt_ast(loaded_state)->a.is_true()) + return; + a = mk_and(loaded_state, a); + loaded_state = mk_smt_bool(true); } \ No newline at end of file diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 2f53f0b4..4c13a160 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -39,7 +39,9 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_smt_symbol(const std::string &name, smt_sortt s) override; smt_sortt convert_slhv_sorts(const type2tc &type) override; - + + + smt_astt convert_assign(const expr2tc &expr) override; smt_astt convert_ast(const expr2tc &expr) override; smt_astt @@ -53,7 +55,10 @@ class z3_slhv_convt : public z3_convt { void print_smt_formulae(std::ostream& dest); std::vector assertions; - smt_astt heap_state; + + smt_astt loaded_state; + void add_loaded_state(smt_astt a); + void collect_loaded_state(smt_astt &a); }; #endif \ No newline at end of file From 2258cf937e7a50c58b8296d63c369b33670cf3e7 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 18 Sep 2024 17:13:24 +0800 Subject: [PATCH 085/126] fix encoding of load operation --- src/goto-symex/builtin_functions.cpp | 2 - src/goto-symex/symex_main.cpp | 1 - src/goto-symex/symex_target_equation.cpp | 3 +- src/goto-symex/symex_valid_object.cpp | 3 -- src/pointer-analysis/dereference.cpp | 3 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 55 ++++++++---------------- src/solvers/z3-slhv/z3_slhv_conv.h | 8 +--- 7 files changed, 23 insertions(+), 52 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 1fca2b36..cf225eee 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -353,8 +353,6 @@ void goto_symext::symex_free(const expr2tc &expr) log_status("tmp before dereference FREE mode: "); tmp->dump(); dereference(tmp, dereferencet::FREE); - log_status("tmp after dereference FREE mode:"); - tmp->dump(); // Don't rely on the output of dereference in free mode; instead fetch all // the internal dereference state for pointed at objects, and creates claims // that if pointed at, their offset is zero. diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 81aeb228..9f4c73d3 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -200,7 +200,6 @@ void goto_symext::symex_step(reachability_treet &art) dereference(tmp, dereferencet::READ); replace_dynamic_allocation(tmp); - log_status("herer"); symex_goto(tmp); } break; diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 1c33ed2b..c9182936 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -192,8 +192,7 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_assignment()) { - if (!is_equality2t(step.cond) || - is_field_of2t(to_equality2t(step.cond).side_2)) + if (!is_equality2t(step.cond)) { smt_astt assign = smt_conv.convert_ast(step.cond); smt_conv.assert_ast(assign); diff --git a/src/goto-symex/symex_valid_object.cpp b/src/goto-symex/symex_valid_object.cpp index 2ad65996..5380c80c 100644 --- a/src/goto-symex/symex_valid_object.cpp +++ b/src/goto-symex/symex_valid_object.cpp @@ -29,7 +29,6 @@ void goto_symext::replace_dynamic_allocation(expr2tc &expr) if (is_valid_object2t(expr) || is_deallocated_obj2t(expr)) { - log_status("replace dynamic object : valid object or deallocated object"); expr2tc &obj_ref = (is_valid_object2t(expr)) ? to_valid_object2t(expr).value : to_deallocated_obj2t(expr).value; @@ -67,13 +66,11 @@ void goto_symext::replace_dynamic_allocation(expr2tc &expr) } else if (is_dynamic_size2t(expr)) { - log_status("replace dynamic object : dynamic size"); // default behavior default_replace_dynamic_allocation(expr); } else if (is_invalid_pointer2t(expr)) { - log_status("replace dynamic object : invalid pointer"); // default behavior default_replace_dynamic_allocation(expr); } diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 46b8e4bb..559dd34c 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -881,7 +881,6 @@ expr2tc dereferencet::build_reference_to( // to have a reference built at all. if (is_internal(mode)) { - log_status("collect objects for doing free"); dereference_callbackt::internal_item internal; internal.object = value; internal.offset = final_offset; // offset for SLHV @@ -2279,6 +2278,8 @@ void dereferencet::valid_check( } else if(is_intheap_type(symbol)) { + if (is_internal(mode)) return; + expr2tc not_valid_heap_region = not2tc(valid_object2tc(symbol)); guardt tmp_guard(guard); tmp_guard.add(not_valid_heap_region); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 955b3958..acf30d1c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -43,7 +43,7 @@ smt_convt *create_new_z3_slhv_solver( } z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) - : z3_convt(_ns, _options), loaded_state(mk_smt_bool(true)) { + : z3_convt(_ns, _options) { // initialize the z3 based slhv converter here int_encoding = true; solver = z3::solver(z3_ctx, "SLHV"); @@ -186,22 +186,6 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { } } -smt_astt z3_slhv_convt::convert_assign(const expr2tc &expr) -{ - const equality2t &eq = to_equality2t(expr); - smt_astt side1 = convert_ast(eq.side_1); // LHS - smt_astt side2 = convert_ast(eq.side_2); // RHS - - smt_astt a = mk_eq(side1, side2); - collect_loaded_state(a); - assert_ast(a); - - smt_cache_entryt e = {eq.side_1, side2, ctx_level}; - smt_cache.insert(e); - - return a; -} - smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { log_status("------------------------------- convert ast -----------------------------"); @@ -209,6 +193,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) smt_cachet::const_iterator cache_result = smt_cache.find(expr); if (cache_result != smt_cache.end()) { + log_status("has been cached : "); cache_result->ast->dump(); return (cache_result->ast); } @@ -281,7 +266,6 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) args[0] = this->project(so.side_1); args[1] = this->project(so.side_2); a = mk_eq(args[0], args[1]); - collect_loaded_state(a); break; } case expr2t::pointer_object_id: @@ -366,11 +350,21 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) case expr2t::and_id: { a = mk_and(args[0], args[1]); - collect_loaded_state(a); break; } case expr2t::or_id: { + // const or2t &_or = to_or2t(expr); + // smt_astt s1 = collect_loaded_state(_or.side_1); + // smt_astt s2 = collect_loaded_state(_or.side_2); + + // smt_astt side1 = args[0]; + // if (!to_solver_smt_ast(s1)->a.is_true()) + // side1 = mk_and(s1, side1); + // smt_astt side2 = args[1]; + // if (!to_solver_smt_ast(s2)->a.is_true()) + // side2 = mk_and(s2, side2); + a = mk_or(args[0], args[1]); break; } @@ -577,8 +571,11 @@ z3_slhv_convt::convert_slhv_opts( smt_astt v1 = mk_fresh(s1, n1); // current heap state - smt_astt heap_state = mk_subh(mk_pt(loc, v1), h); - add_loaded_state(heap_state); + smt_astt s = mk_subh(mk_pt(loc, v1), h); + // if load operation is invalid, + // dereference will lead to undedined behavior + assert_ast(mk_or(s, mk_smt_bool(false))); + return v1; } case expr2t::heap_update_id: @@ -718,20 +715,4 @@ void z3_slhv_convt::print_smt_formulae(std::ostream& dest) log_status( "Total number of safety properties: {}", Z3_ast_vector_size(z3_ctx, __z3_assertions)); -} - -void z3_slhv_convt::add_loaded_state(smt_astt a) -{ - if (to_solver_smt_ast(loaded_state)->a.is_true()) - loaded_state = a; - else - loaded_state = mk_and(loaded_state, a); -} - -void z3_slhv_convt::collect_loaded_state(smt_astt &a) -{ - if (to_solver_smt_ast(loaded_state)->a.is_true()) - return; - a = mk_and(loaded_state, a); - loaded_state = mk_smt_bool(true); } \ No newline at end of file diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 4c13a160..70a2fbb1 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -1,6 +1,8 @@ #ifndef _ESBMC_SOLVERS_Z3_SLHV_CONV_H #define _ESBMC_SOLVERS_Z3_SLHV_CONV_H +#include + #include #include @@ -40,8 +42,6 @@ class z3_slhv_convt : public z3_convt { smt_sortt convert_slhv_sorts(const type2tc &type) override; - - smt_astt convert_assign(const expr2tc &expr) override; smt_astt convert_ast(const expr2tc &expr) override; smt_astt @@ -55,10 +55,6 @@ class z3_slhv_convt : public z3_convt { void print_smt_formulae(std::ostream& dest); std::vector assertions; - - smt_astt loaded_state; - void add_loaded_state(smt_astt a); - void collect_loaded_state(smt_astt &a); }; #endif \ No newline at end of file From 265dafbb9999fd11e479dcbce421625147f6721c Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 20 Sep 2024 10:00:48 +0800 Subject: [PATCH 086/126] use heap read/write to encoding field_of and heap_update --- src/goto-symex/symex_assign.cpp | 2 + src/goto-symex/symex_target_equation.cpp | 199 +++++++++----------- src/goto-symex/symex_target_equation.h | 10 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 222 ++++++++++++----------- src/solvers/z3-slhv/z3_slhv_conv.h | 25 +-- 5 files changed, 228 insertions(+), 230 deletions(-) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 0f962840..3857a26c 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -1103,6 +1103,8 @@ type2tc goto_symext::create_heap_region_type( ); } } + else + _heap_type.field_types.push_back(empty_type2tc()); return heap_type; } diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index c9182936..15c26b46 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -137,21 +137,8 @@ void symex_target_equationt::convert(smt_convt &smt_conv) smt_convt::ast_vec assertions; smt_astt assumpt_ast = smt_conv.convert_ast(gen_true_expr()); - for (auto SSA_step : SSA_steps) - { - if (!SSA_step.ignore && has_cond_val(SSA_step.cond)) - { - log_status("========================================================"); - log_status("before reconstruct : "); - SSA_step.cond->dump(); - reconstruct_cond_expr(SSA_step.cond); - - log_status("after reconstruct : "); - SSA_step.cond->dump(); - log_status("========================================================"); - } + for (auto &SSA_step : SSA_steps) convert_internal_step(smt_conv, assumpt_ast, assertions, SSA_step); - } if (!assertions.empty()) smt_conv.assert_ast(smt_conv.make_n_ary_or(assertions)); @@ -192,18 +179,10 @@ void symex_target_equationt::convert_internal_step( } else if (step.is_assignment()) { - if (!is_equality2t(step.cond)) + smt_astt assign = smt_conv.convert_assign(step.cond); + if (ssa_smt_trace) { - smt_astt assign = smt_conv.convert_ast(step.cond); - smt_conv.assert_ast(assign); - } - else - { - smt_astt assign = smt_conv.convert_assign(step.cond); - if (ssa_smt_trace) - { - assign->dump(); - } + assign->dump(); } } else if (step.is_output()) @@ -442,93 +421,93 @@ void symex_target_equationt::reconstruct_symbolic_expression( } } -void symex_target_equationt::reconstruct_cond_expr(expr2tc &expr) -{ - if (is_nil_expr(expr)) return; - - expr->Foreach_operand([this](expr2tc &e){ - reconstruct_cond_expr(e); - }); - - switch (expr->expr_id) - { - case expr2t::same_object_id: - case expr2t::equality_id: - { - expr2tc side_1 = - is_equality2t(expr) ? - to_equality2t(expr).side_1 : to_same_object2t(expr).side_1; - expr2tc side_2 = - is_equality2t(expr) ? - to_equality2t(expr).side_2 : to_same_object2t(expr).side_2; - - if (!has_cond_val(side_1) && !has_cond_val(side_2)) break; - - cond_val_set s1, s2; - get_cond_val(side_1, constant_bool2tc(true), s1); - get_cond_val(side_2, constant_bool2tc(true), s2); - - expr2tc new_expr; - int n = 0; - for (const cond_val &v1 : s1) - for (const cond_val &v2 : s2) - { - expr2tc cond = and2tc(v1.first, v2.first); - simplify(cond); - expr2tc bexpr = - is_equality2t(expr) ? - equality2tc(v1.second, v2.second) : - same_object2tc(v1.second, v2.second); - simplify(bexpr); - expr2tc e = and2tc(cond, bexpr); - new_expr = (n == 0) ? e : or2tc(new_expr, e); - n++; - } - expr = new_expr; - break; - } - // add more cases if exists - default: - break; - } -} - -void symex_target_equationt::get_cond_val( - const expr2tc &expr, const expr2tc &cond, cond_val_set &s) -{ - if (is_if2t(expr)) - { - const if2t &_if = to_if2t(expr); - - expr2tc true_cond = and2tc(cond, _if.cond); - expr2tc false_cond = and2tc(cond, not2tc(_if.cond)); - - get_cond_val(_if.true_value, true_cond, s); - get_cond_val(_if.false_value, false_cond, s); - return; - } - else if (is_typecast2t(expr)) - { - get_cond_val(to_typecast2t(expr).from, cond, s); - return; - } - - s.push_back(std::make_pair(cond, expr)); -} - -bool symex_target_equationt::has_cond_val(const expr2tc &expr, bool is_in_if) -{ - if (is_nil_expr(expr)) return false; - if (is_field_of2t(expr)) return is_in_if; +// void symex_target_equationt::reconstruct_cond_expr(expr2tc &expr) +// { +// if (is_nil_expr(expr)) return; + +// expr->Foreach_operand([this](expr2tc &e){ +// reconstruct_cond_expr(e); +// }); + +// switch (expr->expr_id) +// { +// case expr2t::same_object_id: +// case expr2t::equality_id: +// { +// expr2tc side_1 = +// is_equality2t(expr) ? +// to_equality2t(expr).side_1 : to_same_object2t(expr).side_1; +// expr2tc side_2 = +// is_equality2t(expr) ? +// to_equality2t(expr).side_2 : to_same_object2t(expr).side_2; + +// if (!has_cond_val(side_1) && !has_cond_val(side_2)) break; + +// cond_val_set s1, s2; +// get_cond_val(side_1, constant_bool2tc(true), s1); +// get_cond_val(side_2, constant_bool2tc(true), s2); + +// expr2tc new_expr; +// int n = 0; +// for (const cond_val &v1 : s1) +// for (const cond_val &v2 : s2) +// { +// expr2tc cond = and2tc(v1.first, v2.first); +// simplify(cond); +// expr2tc bexpr = +// is_equality2t(expr) ? +// equality2tc(v1.second, v2.second) : +// same_object2tc(v1.second, v2.second); +// simplify(bexpr); +// expr2tc e = and2tc(cond, bexpr); +// new_expr = (n == 0) ? e : or2tc(new_expr, e); +// n++; +// } +// expr = new_expr; +// break; +// } +// // add more cases if exists +// default: +// break; +// } +// } + +// void symex_target_equationt::get_cond_val( +// const expr2tc &expr, const expr2tc &cond, cond_val_set &s) +// { +// if (is_if2t(expr)) +// { +// const if2t &_if = to_if2t(expr); + +// expr2tc true_cond = and2tc(cond, _if.cond); +// expr2tc false_cond = and2tc(cond, not2tc(_if.cond)); + +// get_cond_val(_if.true_value, true_cond, s); +// get_cond_val(_if.false_value, false_cond, s); +// return; +// } +// else if (is_typecast2t(expr)) +// { +// get_cond_val(to_typecast2t(expr).from, cond, s); +// return; +// } + +// s.push_back(std::make_pair(cond, expr)); +// } + +// bool symex_target_equationt::has_cond_val(const expr2tc &expr, bool is_in_if) +// { +// if (is_nil_expr(expr)) return false; +// if (is_field_of2t(expr)) return is_in_if; - is_in_if |= is_if2t(expr); - bool has_cond = false; - expr->foreach_operand([this, &has_cond, &is_in_if](const expr2tc &e) { - has_cond |= has_cond_val(e, is_in_if); - }); +// is_in_if |= is_if2t(expr); +// bool has_cond = false; +// expr->foreach_operand([this, &has_cond, &is_in_if](const expr2tc &e) { +// has_cond |= has_cond_val(e, is_in_if); +// }); - return has_cond; -} +// return has_cond; +// } runtime_encoded_equationt::runtime_encoded_equationt( const namespacet &_ns, diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index f69456d8..5efb9e8b 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -204,7 +204,7 @@ class symex_target_equationt : public symex_targett void push_ctx() override; void pop_ctx() override; - void reconstruct_cond_expr(expr2tc &expr); + // void reconstruct_cond_expr(expr2tc &expr); protected: const namespacet &ns; @@ -216,10 +216,10 @@ class symex_target_equationt : public symex_targett private: void debug_print_step(const SSA_stept &step) const; - typedef std::pair cond_val; - typedef std::vector cond_val_set; - void get_cond_val(const expr2tc &expr, const expr2tc &cond, cond_val_set &s); - bool has_cond_val(const expr2tc &expr, bool is_in_if = false); + // typedef std::pair cond_val; + // typedef std::vector cond_val_set; + // void get_cond_val(const expr2tc &expr, const expr2tc &cond, cond_val_set &s); + // bool has_cond_val(const expr2tc &expr, bool is_in_if = false); }; class runtime_encoded_equationt : public symex_target_equationt diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index acf30d1c..81344eb1 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -43,11 +43,12 @@ smt_convt *create_new_z3_slhv_solver( } z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) - : z3_convt(_ns, _options) { - // initialize the z3 based slhv converter here - int_encoding = true; - solver = z3::solver(z3_ctx, "SLHV"); - log_status("z3_slhv_convt created"); + : z3_convt(_ns, _options) +{ + // initialize the z3 based slhv converter here + int_encoding = true; + solver = z3::solver(z3_ctx, "SLHV"); + log_status("z3_slhv_convt created"); } z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } @@ -76,91 +77,146 @@ smt_convt::resultt z3_slhv_convt::dec_solve() return smt_convt::P_ERROR; } -const std::string z3_slhv_convt::solver_text() { - return "Z3-slhv"; +const std::string z3_slhv_convt::solver_text() { return "Z3-slhv"; } + +smt_sortt z3_slhv_convt::mk_intheap_sort() +{ + return new solver_smt_sort(SMT_SORT_INTHEAP, z3_ctx.intheap_sort()); +} + +smt_sortt z3_slhv_convt::mk_intloc_sort() +{ + return new solver_smt_sort(SMT_SORT_INTLOC, z3_ctx.intloc_sort()); +} + +smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) +{ + return mk_intloc_sort(); } -smt_astt z3_slhv_convt::mk_emp() { +smt_astt z3_slhv_convt::mk_emp() +{ return new_ast(z3_ctx.emp_const(), this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_nil() { +smt_astt z3_slhv_convt::mk_nil() +{ return new_ast(z3_ctx.nil_const(), this->mk_intloc_sort()); } -smt_astt z3_slhv_convt::mk_pt(smt_astt a, smt_astt b) { - assert(a->sort == mk_intloc_sort()); +smt_astt z3_slhv_convt::mk_pt(smt_astt l, smt_astt v) +{ + assert(l->sort->id == SMT_SORT_INTLOC); return new_ast( z3::points_to( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(l)->a, + to_solver_smt_ast(v)->a ), this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_uplus(smt_astt a, smt_astt b) { - assert(a->sort == mk_intheap_sort()); - assert(b->sort == mk_intheap_sort()); +smt_astt z3_slhv_convt::mk_uplus(smt_astt ht1, smt_astt ht2) +{ + assert(ht1->sort->id == SMT_SORT_INTHEAP); + assert(ht2->sort->id == SMT_SORT_INTHEAP); return new_ast( z3::uplus( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(ht1)->a, + to_solver_smt_ast(ht2)->a ), this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_uplus(std::vector pts) { - z3::expr_vector pt_vec(z3_ctx); - for (auto pt : pts) { - pt_vec.push_back(to_solver_smt_ast(pt)->a); +smt_astt z3_slhv_convt::mk_uplus(std::vector hts) +{ + z3::expr_vector ht_vec(z3_ctx); + for (auto ht : hts) { + ht_vec.push_back(to_solver_smt_ast(ht)->a); } - return new_ast(z3::uplus(pt_vec), this->mk_intheap_sort()); + return new_ast(z3::uplus(ht_vec), this->mk_intheap_sort()); } -smt_astt z3_slhv_convt::mk_subh(smt_astt a, smt_astt b) { - assert(a->sort == mk_intheap_sort()); - assert(b->sort == mk_intheap_sort()); +smt_astt z3_slhv_convt::mk_subh(smt_astt ht1, smt_astt ht2) +{ + assert(ht1->sort->id == SMT_SORT_INTHEAP); + assert(ht2->sort->id == SMT_SORT_INTHEAP); return new_ast( z3::subh( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(ht1)->a, + to_solver_smt_ast(ht2)->a ), this->boolean_sort); } -smt_astt z3_slhv_convt::mk_disjh(smt_astt a, smt_astt b) { - assert(a->sort == mk_intheap_sort()); - assert(b->sort == mk_intheap_sort()); +smt_astt z3_slhv_convt::mk_disjh(smt_astt ht1, smt_astt ht2) +{ + assert(ht1->sort->id == SMT_SORT_INTHEAP); + assert(ht2->sort->id == SMT_SORT_INTHEAP); return new_ast( z3::disjh( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(ht1)->a, + to_solver_smt_ast(ht2)->a ), this->boolean_sort); } -smt_astt z3_slhv_convt::mk_locadd(smt_astt a, smt_astt b) { - assert(a->sort == mk_intloc_sort() || b->sort == mk_intloc_sort()); +smt_astt z3_slhv_convt::mk_locadd(smt_astt l, smt_astt o) +{ + assert(l->sort->id == SMT_SORT_INTLOC); return new_ast( z3::locadd( - to_solver_smt_ast(a)->a, - to_solver_smt_ast(b)->a + to_solver_smt_ast(l)->a, + to_solver_smt_ast(o)->a ), this->mk_intloc_sort() ); } -BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed){ - log_error("SLHV does not support bv"); - abort(); +smt_astt z3_slhv_convt::mk_heap_read(smt_astt h, smt_astt l, smt_sortt s) +{ + z3::expr (*heap_read)(z3::expr, z3::expr); + if (s->id == SMT_SORT_INTLOC) + heap_read = z3::heap_read_loc; + else + heap_read = z3::heap_read_data; + return new_ast( + (*heap_read)( + to_solver_smt_ast(h)->a, + to_solver_smt_ast(l)->a + ), + s + ); } -smt_sortt z3_slhv_convt::mk_intheap_sort() { - return new solver_smt_sort(SMT_SORT_INTHEAP, z3_ctx.intheap_sort()); +smt_astt z3_slhv_convt::mk_heap_write(smt_astt h, smt_astt l, smt_astt c) +{ + z3::expr (*heap_write)(z3::expr, z3::expr, z3::expr); + if (c->sort->id == SMT_SORT_INTLOC) + heap_write = z3::heap_write_loc; + else + heap_write = z3::heap_write_data; + return new_ast( + (*heap_write)( + to_solver_smt_ast(h)->a, + to_solver_smt_ast(l)->a, + to_solver_smt_ast(c)->a + ), + this->mk_intheap_sort() + ); } -smt_sortt z3_slhv_convt::mk_intloc_sort() { - return new solver_smt_sort(SMT_SORT_INTLOC, z3_ctx.intloc_sort()); +smt_astt z3_slhv_convt::mk_heap_delete(smt_astt h, smt_astt l) +{ + return new_ast( + z3::heap_delete( + to_solver_smt_ast(h)->a, + to_solver_smt_ast(l)->a + ), + this->mk_intheap_sort() + ); } -smt_sortt z3_slhv_convt::mk_struct_sort(const type2tc &type) { - return mk_intloc_sort(); +BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed) +{ + log_error("SLHV does not support bv"); + abort(); } -smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s) { +smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s) +{ z3::expr e(z3_ctx); switch (s->id) { case SMT_SORT_INTHEAP: @@ -175,7 +231,8 @@ smt_astt z3_slhv_convt::mk_smt_symbol(const std::string &name, smt_sortt s) { return new_ast(e, s); } -smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) { +smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) +{ switch (type->type_id) { case type2t::intheap_id: return mk_intheap_sort(); case type2t::intloc_id: return mk_intloc_sort(); @@ -354,17 +411,6 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) } case expr2t::or_id: { - // const or2t &_or = to_or2t(expr); - // smt_astt s1 = collect_loaded_state(_or.side_1); - // smt_astt s2 = collect_loaded_state(_or.side_2); - - // smt_astt side1 = args[0]; - // if (!to_solver_smt_ast(s1)->a.is_true()) - // side1 = mk_and(s1, side1); - // smt_astt side2 = args[1]; - // if (!to_solver_smt_ast(s2)->a.is_true()) - // side2 = mk_and(s2, side2); - a = mk_or(args[0], args[1]); break; } @@ -552,31 +598,16 @@ z3_slhv_convt::convert_slhv_opts( smt_astt h = convert_ast(heap_region); smt_astt source_loc = convert_ast(_type.location); - smt_astt loc = _field == 0 ? + smt_astt l = _field == 0 ? source_loc : mk_locadd(source_loc, convert_ast(field)); - smt_sortt s1; - std::string n1; - if (!_type.is_aligned) - { - s1 = mk_intloc_sort(); - n1 = mk_fresh_name("tmp_loc::"); - } + smt_sortt s; + if (is_intloc_type(_type.field_types[_field])) + s = mk_intloc_sort(); else - { - s1 = is_intloc_type(_type.field_types[_field]) ? mk_intloc_sort() : mk_int_sort(); - n1 = mk_fresh_name( - is_intloc_type(_type.field_types[_field]) ? "tmp_loc::" : "tmp_val::"); - } - smt_astt v1 = mk_fresh(s1, n1); + s = mk_int_sort(); - // current heap state - smt_astt s = mk_subh(mk_pt(loc, v1), h); - // if load operation is invalid, - // dereference will lead to undedined behavior - assert_ast(mk_or(s, mk_smt_bool(false))); - - return v1; + return mk_heap_read(h, l, s); } case expr2t::heap_update_id: { @@ -595,34 +626,16 @@ z3_slhv_convt::convert_slhv_opts( unsigned int _field = to_constant_int2t(upd_field).value.to_uint64(); smt_astt h = args[0]; - smt_astt source_loc = convert_ast(_type.location); smt_astt field = args[1]; - smt_astt loc = _field == 0 ? source_loc : mk_locadd(source_loc, field); - smt_astt val = convert_ast(upd_value); - - smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); - smt_astt v1 = mk_fresh(val->sort, mk_fresh_name("tmp_val::")); - - // current heap state - smt_astt old_state = mk_uplus(h1, mk_pt(loc, v1)); - assert_ast(mk_eq(h, old_state)); + smt_astt source_loc = convert_ast(_type.location); + smt_astt l = _field == 0 ? source_loc : mk_locadd(source_loc, field); + smt_astt v = convert_ast(upd_value); - // new heap state - return mk_uplus(h1, mk_pt(loc, val)); + return mk_heap_write(h, l, v); } case expr2t::heap_delete_id: { - const heap_delete2t &heap_del = to_heap_delete2t(expr); - - smt_astt h = args[0]; - smt_astt l = args[1]; - - smt_astt h1 = mk_fresh(mk_intheap_sort(), mk_fresh_name("tmp_heap::")); - smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name("tmp_val::")); - - // current heap state - assert_ast(mk_eq(h, mk_uplus(h1, mk_pt(l, v1)))); - return h1; + return mk_heap_delete(args[0], args[1]); } case expr2t::same_object_id: { @@ -683,7 +696,8 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) } } -void z3_slhv_convt::dump_smt() { +void z3_slhv_convt::dump_smt() +{ const std::string &path = options.get_option("output"); if(path == "-") { print_smt_formulae(std::cout); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 70a2fbb1..7b245b30 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -19,24 +19,27 @@ class z3_slhv_convt : public z3_convt { smt_convt::resultt dec_solve() override; const std::string solver_text() override; + // sort making + smt_sortt mk_intheap_sort(); + smt_sortt mk_intloc_sort(); + smt_sortt mk_struct_sort(const type2tc &type) override; + // constant and operators smt_astt mk_emp(); smt_astt mk_nil(); - smt_astt mk_pt(smt_astt a, smt_astt b); - smt_astt mk_uplus(smt_astt a, smt_astt b); - smt_astt mk_uplus(std::vector pts); - smt_astt mk_subh(smt_astt a, smt_astt b); - smt_astt mk_disjh(smt_astt a, smt_astt b); - smt_astt mk_locadd(smt_astt a, smt_astt b); + smt_astt mk_pt(smt_astt l, smt_astt v); + smt_astt mk_uplus(smt_astt ht1, smt_astt ht2); + smt_astt mk_uplus(std::vector hts); + smt_astt mk_subh(smt_astt ht1, smt_astt ht2); + smt_astt mk_disjh(smt_astt ht1, smt_astt ); + smt_astt mk_locadd(smt_astt l, smt_astt o); + smt_astt mk_heap_read(smt_astt h, smt_astt l, smt_sortt s); + smt_astt mk_heap_write(smt_astt h, smt_astt l, smt_astt c); + smt_astt mk_heap_delete(smt_astt h, smt_astt l); // value obtaining from solver, not supported here BigInt get_bv(smt_astt a, bool is_signed) override; - // sort making - smt_sortt mk_intheap_sort(); - smt_sortt mk_intloc_sort(); - smt_sortt mk_struct_sort(const type2tc &type) override; - // SLHV variable smt_astt mk_smt_symbol(const std::string &name, smt_sortt s) override; From 974d6a5b9e3c19eb3903b03286d65eecd4ca0140 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 20 Sep 2024 10:30:28 +0800 Subject: [PATCH 087/126] remove redundant functions --- src/goto-symex/symex_target_equation.cpp | 88 ------------------------ src/goto-symex/symex_target_equation.h | 5 -- 2 files changed, 93 deletions(-) diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 15c26b46..4b8ea718 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -421,94 +421,6 @@ void symex_target_equationt::reconstruct_symbolic_expression( } } -// void symex_target_equationt::reconstruct_cond_expr(expr2tc &expr) -// { -// if (is_nil_expr(expr)) return; - -// expr->Foreach_operand([this](expr2tc &e){ -// reconstruct_cond_expr(e); -// }); - -// switch (expr->expr_id) -// { -// case expr2t::same_object_id: -// case expr2t::equality_id: -// { -// expr2tc side_1 = -// is_equality2t(expr) ? -// to_equality2t(expr).side_1 : to_same_object2t(expr).side_1; -// expr2tc side_2 = -// is_equality2t(expr) ? -// to_equality2t(expr).side_2 : to_same_object2t(expr).side_2; - -// if (!has_cond_val(side_1) && !has_cond_val(side_2)) break; - -// cond_val_set s1, s2; -// get_cond_val(side_1, constant_bool2tc(true), s1); -// get_cond_val(side_2, constant_bool2tc(true), s2); - -// expr2tc new_expr; -// int n = 0; -// for (const cond_val &v1 : s1) -// for (const cond_val &v2 : s2) -// { -// expr2tc cond = and2tc(v1.first, v2.first); -// simplify(cond); -// expr2tc bexpr = -// is_equality2t(expr) ? -// equality2tc(v1.second, v2.second) : -// same_object2tc(v1.second, v2.second); -// simplify(bexpr); -// expr2tc e = and2tc(cond, bexpr); -// new_expr = (n == 0) ? e : or2tc(new_expr, e); -// n++; -// } -// expr = new_expr; -// break; -// } -// // add more cases if exists -// default: -// break; -// } -// } - -// void symex_target_equationt::get_cond_val( -// const expr2tc &expr, const expr2tc &cond, cond_val_set &s) -// { -// if (is_if2t(expr)) -// { -// const if2t &_if = to_if2t(expr); - -// expr2tc true_cond = and2tc(cond, _if.cond); -// expr2tc false_cond = and2tc(cond, not2tc(_if.cond)); - -// get_cond_val(_if.true_value, true_cond, s); -// get_cond_val(_if.false_value, false_cond, s); -// return; -// } -// else if (is_typecast2t(expr)) -// { -// get_cond_val(to_typecast2t(expr).from, cond, s); -// return; -// } - -// s.push_back(std::make_pair(cond, expr)); -// } - -// bool symex_target_equationt::has_cond_val(const expr2tc &expr, bool is_in_if) -// { -// if (is_nil_expr(expr)) return false; -// if (is_field_of2t(expr)) return is_in_if; - -// is_in_if |= is_if2t(expr); -// bool has_cond = false; -// expr->foreach_operand([this, &has_cond, &is_in_if](const expr2tc &e) { -// has_cond |= has_cond_val(e, is_in_if); -// }); - -// return has_cond; -// } - runtime_encoded_equationt::runtime_encoded_equationt( const namespacet &_ns, smt_convt &_conv) diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index 5efb9e8b..cf770582 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -215,11 +215,6 @@ class symex_target_equationt : public symex_targett private: void debug_print_step(const SSA_stept &step) const; - - // typedef std::pair cond_val; - // typedef std::vector cond_val_set; - // void get_cond_val(const expr2tc &expr, const expr2tc &cond, cond_val_set &s); - // bool has_cond_val(const expr2tc &expr, bool is_in_if = false); }; class runtime_encoded_equationt : public symex_target_equationt From 6314fcf2adfbba960f2b2156f85d324308211e18 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 20 Sep 2024 12:58:15 +0800 Subject: [PATCH 088/126] pretty result for multi-property-check --- src/esbmc/bmc.cpp | 33 +++++++++---- src/goto-symex/symex_main.cpp | 62 ++++++++++++------------ src/goto-symex/symex_target_equation.cpp | 26 +++++----- src/solvers/smt/smt_conv.cpp | 2 - src/solvers/solve.cpp | 2 - src/solvers/z3-slhv/z3_slhv_conv.cpp | 17 +++---- 6 files changed, 74 insertions(+), 68 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 8c180f2c..287329b7 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -156,7 +156,6 @@ void bmct::generate_smt_from_equation( logic = "integer/real arithmetic"; log_status("Encoding remaining VCC(s) using {}", logic); - log_status("Equations: "); fine_timet encode_start = current_time(); eq.convert(smt_conv); fine_timet encode_stop = current_time(); @@ -785,29 +784,45 @@ smt_convt::resultt bmct::multi_property_check( smt_convt::resultt result = runtime_solver->dec_solve(); fine_timet sat_stop = current_time(); - log_status("---------------------------------------------"); log_status( "Solving claim '{}' with solver {}", claim.claim_msg, runtime_solver->solver_text()); + log_status( + "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); + locationt location; + std::string property; for (auto it = local_eq.SSA_steps.begin(); it != local_eq.SSA_steps.end(); it++) if (it->is_assert() && !it->ignore) { - log_status("{}", it->source.pc->location); - log_status("{}", it->comment); + location = it->source.pc->location; + property = it->comment; break; } - log_status("Dec result - {}", + + std::string short_property; + if (property.find("invalid free") != std::string::npos || + property.find("Invalid pointer freed") != std::string::npos) + short_property = "INVALID_FREE"; + else if (property.find("forgotten memory") != std::string::npos) + short_property = "MEMORY_LEAK"; + else + short_property = "INVALID_DEREF"; + + log_status( + "--------------------------------- Result -----------------------------------"); + log_status("Location: {}", location); + log_status("Property({}): {}", short_property, property); + log_status( + "Result: {}, Time: {}s", result == smt_convt::P_SATISFIABLE ? "sat" : result == smt_convt::P_UNSATISFIABLE ? "unsat" : - "error"); - + "error", time2string(sat_stop - sat_start)); log_status( - "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); - log_status("---------------------------------------------"); + "--------------------------------- Result -----------------------------------\n"); // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 9f4c73d3..b868c88e 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1201,7 +1201,8 @@ void goto_symext::add_memory_leak_checks() }; } bool use_old_encoding = !options.get_bool_option("z3-slhv"); - if(use_old_encoding) { + if(use_old_encoding) + { for (auto const &it : dynamic_memory) { // Don't check memory leak if the object is automatically deallocated @@ -1212,39 +1213,39 @@ void goto_symext::add_memory_leak_checks() continue; } - // Assert that the allocated object was freed. - expr2tc deallocd = deallocated_obj2tc(it.obj); + // Assert that the allocated object was freed. + expr2tc deallocd = deallocated_obj2tc(it.obj); - // For each dynamic object we generate a condition checking - // whether it has been deallocated. - expr2tc eq = equality2tc(deallocd, gen_true_expr()); + // For each dynamic object we generate a condition checking + // whether it has been deallocated. + expr2tc eq = equality2tc(deallocd, gen_true_expr()); - expr2tc when = it.alloc_guard.as_expr(); + expr2tc when = it.alloc_guard.as_expr(); - if (no_reachable_memleak) - { - expr2tc obj = get_base_object(it.obj); - expr2tc adr = obj; - if (!is_if2t(obj)) - adr = address_of2tc(obj->type, obj); - expr2tc targeted = maybe_global_target(adr); - when = and2tc(when, not2tc(targeted)); - } + if (no_reachable_memleak) + { + expr2tc obj = get_base_object(it.obj); + expr2tc adr = obj; + if (!is_if2t(obj)) + adr = address_of2tc(obj->type, obj); + expr2tc targeted = maybe_global_target(adr); + when = and2tc(when, not2tc(targeted)); + } - // Additionally, we need to make sure that we check the above condition - // only for dynamic objects that were created from successful - // memory allocations. This is because we always create a dynamic object for - // each dynamic allocation, and the allocation success status - // is described by a separate "allocation_guard". - // (see "symex_mem" method in "goto-symex/builtin_functions. cpp"). - expr2tc cond = implies2tc(when, eq); - - replace_dynamic_allocation(cond); - cur_state->rename(cond); - claim( - cond, - "dereference failure: forgotten memory: " + get_pretty_name(it.name)); - } + // Additionally, we need to make sure that we check the above condition + // only for dynamic objects that were created from successful + // memory allocations. This is because we always create a dynamic object for + // each dynamic allocation, and the allocation success status + // is described by a separate "allocation_guard". + // (see "symex_mem" method in "goto-symex/builtin_functions. cpp"). + expr2tc cond = implies2tc(when, eq); + + replace_dynamic_allocation(cond); + cur_state->rename(cond); + claim( + cond, + "dereference failure: forgotten memory: " + get_pretty_name(it.name)); + } } else { log_status(" ----------- [memleak encoding]----------- "); for (auto const &it : dynamic_memory){ @@ -1257,7 +1258,6 @@ void goto_symext::add_memory_leak_checks() cond, "dereference failure, forgotten memory: " + get_pretty_name(it.name) ); - } } } diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 4b8ea718..5c11e1c5 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -161,8 +161,8 @@ void symex_target_equationt::convert_internal_step( return; } - log_status(" ============================== step ======================== "); - step.dump(); + // log_status(" ============================== step ======================== "); + // step.dump(); // guard_ast is used for generating witness // step.guard_ast = smt_conv.convert_ast(step.guard); @@ -172,18 +172,18 @@ void symex_target_equationt::convert_internal_step( // step.cond_ast = false_val; expr2tc tmp(step.cond); step.cond_ast = smt_conv.convert_ast(tmp); - if (ssa_smt_trace) - { - step.cond_ast->dump(); - } + // if (ssa_smt_trace) + // { + // step.cond_ast->dump(); + // } } else if (step.is_assignment()) { smt_astt assign = smt_conv.convert_assign(step.cond); - if (ssa_smt_trace) - { - assign->dump(); - } + // if (ssa_smt_trace) + // { + // assign->dump(); + // } } else if (step.is_output()) { @@ -223,15 +223,15 @@ void symex_target_equationt::convert_internal_step( { step.cond_ast = smt_conv.imply_ast(assumpt_ast, step.cond_ast); assertions.push_back(smt_conv.invert_ast(step.cond_ast)); - smt_conv.invert_ast(step.cond_ast)->dump(); + // smt_conv.invert_ast(step.cond_ast)->dump(); } else if (step.is_assume()) { assumpt_ast = smt_conv.mk_and(assumpt_ast, step.cond_ast); - step.cond_ast->dump(); + // step.cond_ast->dump(); } - log_status(" ============================== step ======================== "); + // log_status(" ============================== step ======================== "); } void symex_target_equationt::output(std::ostream &out) const diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index c643795c..ce4a503b 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -1428,8 +1428,6 @@ static std::string fixed_point(const std::string &v, unsigned width) smt_astt smt_convt::convert_terminal(const expr2tc &expr) { - log_status("convert terminal: "); - expr.get()->dump(); switch (expr->expr_id) { case expr2t::constant_int_id: diff --git a/src/solvers/solve.cpp b/src/solvers/solve.cpp index 50978646..c85950e9 100644 --- a/src/solvers/solve.cpp +++ b/src/solvers/solve.cpp @@ -86,7 +86,6 @@ static std::string pick_default_solver() static solver_creator & pick_solver(std::string &solver_name, const optionst &options) { - log_status("pick solver"); if (solver_name == "") { // Pick one based on options. @@ -124,7 +123,6 @@ smt_convt *create_solver( const namespacet &ns, const optionst &options) { - log_status("create solver"); tuple_iface *tuple_api = nullptr; array_iface *array_api = nullptr; fp_convt *fp_api = nullptr; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 81344eb1..81385586 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -38,7 +38,6 @@ smt_convt *create_new_z3_slhv_solver( *tuple_api = static_cast(conv); *array_api = static_cast(conv); *fp_api = static_cast(conv); - log_status("z3_slhv solver created"); return conv; } @@ -48,7 +47,6 @@ z3_slhv_convt::z3_slhv_convt(const namespacet &_ns, const optionst& _options) // initialize the z3 based slhv converter here int_encoding = true; solver = z3::solver(z3_ctx, "SLHV"); - log_status("z3_slhv_convt created"); } z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } @@ -245,15 +243,12 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { - log_status("------------------------------- convert ast -----------------------------"); - expr->dump(); + // log_status("------------------------------- convert ast -----------------------------"); + // expr->dump(); smt_cachet::const_iterator cache_result = smt_cache.find(expr); - if (cache_result != smt_cache.end()) { - log_status("has been cached : "); - cache_result->ast->dump(); + if (cache_result != smt_cache.end()) return (cache_result->ast); - } std::vector args; args.reserve(expr->get_num_sub_exprs()); @@ -424,9 +419,9 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) struct smt_cache_entryt entry = {expr, a, ctx_level}; smt_cache.insert(entry); - log_status("====================== converted reuslt: "); - a->dump(); - log_status("-------------------------------------------------------------------------"); + // log_status("====================== converted reuslt: "); + // a->dump(); + // log_status("-------------------------------------------------------------------------"); return a; } From 69eef5409f5439e9d3729bf91acd09f15aac70dc Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 20 Sep 2024 15:18:51 +0800 Subject: [PATCH 089/126] fix encoding load --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 80 +++++++++++----------------- src/solvers/z3-slhv/z3_slhv_conv.h | 3 -- 2 files changed, 30 insertions(+), 53 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 81385586..703dcec7 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -163,50 +163,6 @@ smt_astt z3_slhv_convt::mk_locadd(smt_astt l, smt_astt o) ); } -smt_astt z3_slhv_convt::mk_heap_read(smt_astt h, smt_astt l, smt_sortt s) -{ - z3::expr (*heap_read)(z3::expr, z3::expr); - if (s->id == SMT_SORT_INTLOC) - heap_read = z3::heap_read_loc; - else - heap_read = z3::heap_read_data; - return new_ast( - (*heap_read)( - to_solver_smt_ast(h)->a, - to_solver_smt_ast(l)->a - ), - s - ); -} - -smt_astt z3_slhv_convt::mk_heap_write(smt_astt h, smt_astt l, smt_astt c) -{ - z3::expr (*heap_write)(z3::expr, z3::expr, z3::expr); - if (c->sort->id == SMT_SORT_INTLOC) - heap_write = z3::heap_write_loc; - else - heap_write = z3::heap_write_data; - return new_ast( - (*heap_write)( - to_solver_smt_ast(h)->a, - to_solver_smt_ast(l)->a, - to_solver_smt_ast(c)->a - ), - this->mk_intheap_sort() - ); -} - -smt_astt z3_slhv_convt::mk_heap_delete(smt_astt h, smt_astt l) -{ - return new_ast( - z3::heap_delete( - to_solver_smt_ast(h)->a, - to_solver_smt_ast(l)->a - ), - this->mk_intheap_sort() - ); -} - BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed) { log_error("SLHV does not support bv"); @@ -596,13 +552,20 @@ z3_slhv_convt::convert_slhv_opts( smt_astt l = _field == 0 ? source_loc : mk_locadd(source_loc, convert_ast(field)); - smt_sortt s; + smt_sortt s1; if (is_intloc_type(_type.field_types[_field])) - s = mk_intloc_sort(); + s1 = mk_intloc_sort(); else - s = mk_int_sort(); + s1 = mk_int_sort(); + smt_astt v1 = mk_fresh(s1, mk_fresh_name(std::string("_loaded_val_"))); + + smt_astt pt = mk_pt(l, v1); + smt_astt load_success = mk_subh(pt, h); + smt_astt load_fail = mk_eq(h, mk_emp()); + smt_astt load_res = mk_or(load_success, load_fail); + assert_ast(load_res); - return mk_heap_read(h, l, s); + return v1; } case expr2t::heap_update_id: { @@ -626,11 +589,28 @@ z3_slhv_convt::convert_slhv_opts( smt_astt l = _field == 0 ? source_loc : mk_locadd(source_loc, field); smt_astt v = convert_ast(upd_value); - return mk_heap_write(h, l, v); + smt_astt h1 = mk_fresh(h->sort, mk_fresh_name(std::string("_tmp_heap_"))); + smt_astt v1 = mk_fresh(v->sort, mk_fresh_name(std::string("_tmp_val_"))); + + smt_astt heap_state = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); + assert_ast(heap_state); + + return mk_uplus(h1, mk_pt(l, v)); } case expr2t::heap_delete_id: { - return mk_heap_delete(args[0], args[1]); + const heap_delete2t &heap_del = to_heap_delete2t(expr); + + smt_astt h = args[0]; + smt_astt l = args[1]; + + smt_astt h1 = mk_fresh(h->sort, mk_fresh_name(std::string("_tmp_heap_"))); + smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name(std::string("_tmp_val_"))); + + smt_astt heap_state = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); + assert_ast(heap_state); + + return h1; } case expr2t::same_object_id: { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 7b245b30..85928dc2 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -33,9 +33,6 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_subh(smt_astt ht1, smt_astt ht2); smt_astt mk_disjh(smt_astt ht1, smt_astt ); smt_astt mk_locadd(smt_astt l, smt_astt o); - smt_astt mk_heap_read(smt_astt h, smt_astt l, smt_sortt s); - smt_astt mk_heap_write(smt_astt h, smt_astt l, smt_astt c); - smt_astt mk_heap_delete(smt_astt h, smt_astt l); // value obtaining from solver, not supported here BigInt get_bv(smt_astt a, bool is_signed) override; From 27c799a091e44d4d51fbdde54cd290114683325c Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 20 Sep 2024 15:49:33 +0800 Subject: [PATCH 090/126] fix property info --- src/esbmc/bmc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 287329b7..3773fc88 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -805,7 +805,9 @@ smt_convt::resultt bmct::multi_property_check( std::string short_property; if (property.find("invalid free") != std::string::npos || - property.find("Invalid pointer freed") != std::string::npos) + property.find("Invalid pointer freed") != std::string::npos || + property.find("Operand of free must have zero pointer offset") != + std::string::npos) short_property = "INVALID_FREE"; else if (property.find("forgotten memory") != std::string::npos) short_property = "MEMORY_LEAK"; From ee509190a549f3b415e1f08a84508ac097116316 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 22 Sep 2024 13:22:03 +0800 Subject: [PATCH 091/126] update expriment script --- scripts/x.py | 194 ++++++++++++++++++++++++++++++++++++++-------- src/esbmc/bmc.cpp | 25 +++--- 2 files changed, 175 insertions(+), 44 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index c90b51af..0fccf974 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -1,40 +1,170 @@ #!/usr/bin/env python3 -if __name__ == '__main__': - import os - import sys +import os +import sys +import csv + +esbmc_slhv_root = "./esbmc" +esbmc_slhv_build = os.path.join(esbmc_slhv_root, "build") +esbmc_slhv = os.path.join(esbmc_slhv_build, "src", "esbmc", "esbmc") + +output_root = "./output" +log_root = os.path.join(output_root, "Logs") +vcc_root = os.path.join(output_root, "VCCs") +t_log = os.path.join(output_root, "t.log") +vcc_log = os.path.join(output_root, "vcc.log") + +csv_file = os.path.join(output_root, "results.csv") + +def compile(): + os.system(f"cd {esbmc_slhv_build } && cmake --build .") + +def help(): + os.system(f"{esbmc_slhv} -h") + +def collect_one_assert(info): + assert(len(info) == 4) + res = {} + + # Location + res["Line"] = "None" + res["Column"] = "None" + if len(info[0].split(' ')) >= 7: + location = info[0].split(' ') + res["Line"] = location[4] + res["Column"] = location[6] + + # Property + property = info[2].split(" ") + res["Property"] = property[1] + + # Result & Time + rt = info[3].split(' ') + res["Result"] = rt[1] + res["Time"] = rt[3] + + return res + +def analysis_result(log): + assert(os.path.exists(log)) + + flag = "--- Result ---" + + assert_results = [] + is_collecting = False + with open(log) as log_file: + info_buf = [] + for line in log_file: + if line.find(flag) != -1: + if not is_collecting: + is_collecting = True + continue + else: + is_collecting = False + assert_results.append(collect_one_assert(info_buf)) + info_buf.clear() + if not is_collecting: continue + info_buf.append(line.strip()) + + return assert_results + +def run_on(cprog, extra_args): + assert(os.path.exists(cprog)) + + cprog_name = os.path.basename(cprog) + print(f"Verifying program: {cprog_name}") - esbmc_slhv_root = "./esbmc/" - esbmc_slhv_build = esbmc_slhv_root + "build/" - esbmc_slhv = esbmc_slhv_build + "src/esbmc/esbmc" + args = [ + esbmc_slhv, + cprog, + "--no-library", + "--ir", + "--force-malloc-success", + "--memory-leak-check", + "--result-only", + "--show-vcc", + "--output", + vcc_log, + "--multi-property", + "--z3-slhv" + ] + + redirect_arg = [">", t_log, "2>&1"] + if "--std-out" not in extra_args: + args += redirect_arg + + cmd = " ".join(args) + print(f"Command: {cmd}") + os.system(cmd) + + result = analysis_result(t_log) + for d in result: + res = [k + ": " + v for k, v in list(d.items())] + print("{:<10} {:<12} {:<25} {:<15} {:<10}".format(*res)) + + return result + +def collect_results(cprog): + cprog_name = cprog.split('.')[0] + + log_file = cprog_name + "_log.log" + vcc_file = cprog_name + "_vcc.log" + + log_path = os.path.join(log_root, log_file) + vcc_path = os.path.join(vcc_root, vcc_file) + + os.system(f"cp {t_log} {log_path}") + os.system(f"cp {vcc_log} {vcc_path}") + + print(f"Result for {cprog}: {log_path} {vcc_path}") + + +def generate_csv(results): + print(f"Write to {csv_file}") + with open(csv_file, "w") as f: + header = ["File", "Line", "Column", "Property", "Result", "Time"] + w = csv.DictWriter(f, header) + w.writeheader() + for cprog, assert_results in results.items(): + is_head = True + for assert_result in assert_results: + new_row = {'File': cprog if is_head else ''} + is_head = False + new_row.update(assert_result) + w.writerow(new_row) + + +def run_expriment_on(benchmark_root): + assert(os.path.exists(benchmark_root)) + + cprogs = [] + for file in os.listdir(f"{benchmark_root}"): + if file.endswith(".c"): + cprogs.append(file) + + cprogs = sorted(cprogs) + + results = {} + for cprog in cprogs: + cprog_path = os.path.join(benchmark_root, cprog) + results[cprog] = run_on(cprog_path, []) + collect_results(cprog) + + generate_csv(results) + +if __name__ == '__main__': + if not os.path.exists(output_root): + os.mkdir(output_root) + os.mkdir(log_root) + os.mkdir(vcc_root) if sys.argv[1] == "--compile": - os.system(f"cd {esbmc_slhv_build } && cmake --build .") + compile() elif sys.argv[1] == "--run": - cprog = sys.argv[2] - assert(os.path.exists(cprog)) - - output_file = "vcc.log" - - args = [ - cprog, - "--no-library", - "--ir", - "--force-malloc-success", - "--memory-leak-check", - "--ssa-smt-trace", - "--result-only", - "--show-vcc", - "--output", - output_file - ] - - if "--bv" not in sys.argv : args.append("--z3-slhv") - if "--multi" in sys.argv : args.append("--multi-property") - if "--no-slice" in sys.argv : args.append("--no-slice") - - os.system(esbmc_slhv + " " + " ".join(args)) + run_on(sys.argv[2], sys.argv[3:-1]) + elif sys.argv[1] == "--expriment": + run_expriment_on(sys.argv[2]) elif sys.argv[1] == "--help": - os.system(f"{esbmc_slhv} -h") + help() else: - assert(False) + assert(False) \ No newline at end of file diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 3773fc88..4bfc5749 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -792,34 +792,35 @@ smt_convt::resultt bmct::multi_property_check( "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); locationt location; - std::string property; + std::string comment; for (auto it = local_eq.SSA_steps.begin(); it != local_eq.SSA_steps.end(); it++) if (it->is_assert() && !it->ignore) { location = it->source.pc->location; - property = it->comment; + comment = it->comment; break; } - std::string short_property; - if (property.find("invalid free") != std::string::npos || - property.find("Invalid pointer freed") != std::string::npos || - property.find("Operand of free must have zero pointer offset") != + std::string property; + if (comment.find("invalid free") != std::string::npos || + comment.find("Invalid pointer freed") != std::string::npos || + comment.find("Operand of free must have zero pointer offset") != std::string::npos) - short_property = "INVALID_FREE"; - else if (property.find("forgotten memory") != std::string::npos) - short_property = "MEMORY_LEAK"; + property = "INVALID_FREE"; + else if (comment.find("forgotten memory") != std::string::npos) + property = "MEMORY_LEAK"; else - short_property = "INVALID_DEREF"; + property = "INVALID_DEREF"; log_status( "--------------------------------- Result -----------------------------------"); log_status("Location: {}", location); - log_status("Property({}): {}", short_property, property); + log_status("Comment: {}", comment); + log_status("Property: {}", property); log_status( - "Result: {}, Time: {}s", + "Result: {} Time: {}s", result == smt_convt::P_SATISFIABLE ? "sat" : result == smt_convt::P_UNSATISFIABLE ? "unsat" : "error", time2string(sat_stop - sat_start)); From efdcf362303765bda6e0811bca59131f5fb882c6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 24 Sep 2024 16:52:45 +0800 Subject: [PATCH 092/126] fix encoding --- src/pointer-analysis/dereference.cpp | 10 +++------- src/solvers/z3-slhv/z3_slhv_conv.cpp | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 559dd34c..94e55953 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -1232,7 +1232,7 @@ void dereferencet::build_deref_slhv( { expr2tc &heap_region = value; - unsigned int field = to_constant_int2t(offset).value.to_uint64(); + int field = to_constant_int2t(offset).value.to_uint64(); intheap_type2t &_type = to_intheap_type(heap_region->type); unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); @@ -1242,14 +1242,10 @@ void dereferencet::build_deref_slhv( abort(); } - if (field >= _type.field_types.size() || + if (field >= _type.field_types.size() || field < 0 || access_sz != _type.total_bytes / _type.field_types.size()) { - // Out of bound or unaligned - undefined behavior - // expr2tc sym = symbol2tc( - // type, - // dereference_callback.get_nondet_id("undefined_behavior_var")); - // value = sym; + // Out of bound or unaligned value = expr2tc(); } else diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 703dcec7..584b053c 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -561,7 +561,7 @@ z3_slhv_convt::convert_slhv_opts( smt_astt pt = mk_pt(l, v1); smt_astt load_success = mk_subh(pt, h); - smt_astt load_fail = mk_eq(h, mk_emp()); + smt_astt load_fail = mk_disjh(pt, h); // v1 is free smt_astt load_res = mk_or(load_success, load_fail); assert_ast(load_res); From 2441e08ce75e890fa5a545dc6856c6e2d4168541 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Wed, 25 Sep 2024 23:31:11 +0800 Subject: [PATCH 093/126] fix: assign locaiton when assigning heap variable --- src/esbmc/bmc.cpp | 7 ++- src/goto-symex/goto_symex.h | 17 +----- src/goto-symex/goto_symex_state.cpp | 12 +++- src/goto-symex/slice.cpp | 3 + src/goto-symex/symex_assign.cpp | 88 ++++++++++++++++------------- 5 files changed, 68 insertions(+), 59 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 4bfc5749..9705bc90 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -818,12 +818,13 @@ smt_convt::resultt bmct::multi_property_check( "--------------------------------- Result -----------------------------------"); log_status("Location: {}", location); log_status("Comment: {}", comment); - log_status("Property: {}", property); log_status( - "Result: {} Time: {}s", + "Property: {} Result: {} Time: {}s", + property, result == smt_convt::P_SATISFIABLE ? "sat" : result == smt_convt::P_UNSATISFIABLE ? "unsat" : - "error", time2string(sat_stop - sat_start)); + "error", + time2string(sat_stop - sat_start)); log_status( "--------------------------------- Result -----------------------------------\n"); diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 3720171d..e8b24164 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -876,24 +876,11 @@ class goto_symext void symex_nondet(const expr2tc &lhs, const expr2tc &effect); /** - * @brief Check whether an expr has field_of, heap_update or heap_delete + * @brief Create a rhs location of object * * @param expr - * @return true - * @return false */ - bool has_cond_expr(const expr2tc &expr); - - /** - * @brief Transfer v = (ite cond v1 v2) to (ite cond (= v v1) (= v v2) - * where has_cond_expr(v1) || has_cond_expr(v2) holds. - * - * @param expr - * @param cond - * @param lhs - * @return expr2tc - */ - expr2tc transfer_to_assume(const expr2tc &expr, const expr2tc &cond, const expr2tc &lhs); + void create_rhs_location(expr2tc &expr); /** * Fetch reference to global dynamic object counter. diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 22fc4044..321e8f95 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -247,6 +247,13 @@ void goto_symex_statet::rename_type(expr2tc &expr) }); } + if (is_intheap_type(type)) + { + intheap_type2t &ty = to_intheap_type(type); + if (!is_nil_expr(ty.location)) + rename(ty.location); + } + /* All subexpressions' types should also be renamed, this is in line with * how goto_convert_functionst::rename_types() is defined */ expr->Foreach_operand([this](expr2tc &expr) { rename_type(expr); }); @@ -255,9 +262,7 @@ void goto_symex_statet::rename_type(expr2tc &expr) void goto_symex_statet::rename(expr2tc &expr) { // rename all the symbols with their last known value - if (is_nil_expr(expr) || - is_heap_region2t(expr)) - return; + if (is_nil_expr(expr)) return; rename_type(expr); @@ -277,6 +282,7 @@ void goto_symex_statet::rename(expr2tc &expr) { location_of2t &locof = to_location_of2t(expr); rename_address(locof.source_heap); + rename_type(locof.source_heap); } else { diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 0f96e3f8..6922ffc5 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -13,6 +13,9 @@ bool symex_slicet::get_symbols(const expr2tc &expr) bool res = false; if (is_heap_region2t(expr)) return false; + if (is_intheap_type(expr) && + !is_nil_expr(to_intheap_type(expr->type).location)) + get_symbols(to_intheap_type(expr->type).location); // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 3857a26c..92f4ca3e 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -377,6 +377,8 @@ void goto_symext::symex_assign_symbol( if (!guard.is_true()) rhs = if2tc(rhs->type, guard.as_expr(), rhs, lhs); + expr2tc org_rhs = rhs; + cur_state->rename(rhs); do_simplify(rhs); @@ -411,6 +413,31 @@ void goto_symext::symex_assign_symbol( cur_state->gen_stack_trace(), hidden, first_loop); + + if (is_intheap_type(lhs) && + is_intheap_type(org_rhs) && + !is_heap_region2t(org_rhs) && + !is_constant_intheap2t(org_rhs) && + !is_heap_update2t(org_rhs)) + { + // assign loc for each region + const intheap_type2t &lhs_ty = to_intheap_type(lhs->type); + if (lhs_ty.is_region) + { + if (is_nil_expr(lhs_ty.location)) + { + // TODO: fix it + log_error("No location"); + abort(); + } + expr2tc lhs_loc = lhs_ty.location; + expr2tc rhs_loc = org_rhs; + create_rhs_location(rhs_loc); + + log_status("Begin assign location"); + symex_assign(code_assign2tc(lhs_loc, rhs_loc)); + } + } } void goto_symext::symex_assign_structure( @@ -1040,7 +1067,6 @@ void goto_symext::replace_tuple(expr2tc &expr) if (is_symbol2t(expr) && is_struct_type(expr->type)) { - log_status("found struct?"); unsigned int bytes = type_byte_size(expr->type, &ns).to_uint64(); // use l1 name and suffix "loc" to create base loc @@ -1070,7 +1096,6 @@ expr2tc goto_symext::create_heap_region_loc(const expr2tc &expr) new_context.add(loc_sym); expr2tc base_loc = symbol2tc(get_intloc_type(), loc_sym.id); - cur_state->rename(base_loc); return base_loc; } @@ -1210,47 +1235,34 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) log_status(" ======== symex nondet ===== "); } -bool goto_symext::has_cond_expr(const expr2tc &expr) +void goto_symext::create_rhs_location(expr2tc &expr) { - if (is_nil_expr(expr)) return false; - if (is_field_of2t(expr) || is_heap_update2t(expr) || - is_heap_delete2t(expr)) - return true; + if (is_nil_expr(expr)) return; - bool has_cond = false; - expr->foreach_operand([this, &has_cond](const expr2tc &e) { - has_cond |= has_cond_expr(e); - }); + if (is_symbol2t(expr) && + !is_nil_expr(to_intheap_type(expr->type).location)) + { + const intheap_type2t &ty = to_intheap_type(expr->type); + expr = ty.location; + return; + } - return has_cond; -} - -expr2tc goto_symext::transfer_to_assume( - const expr2tc &expr, const expr2tc &cond, const expr2tc &lhs) -{ if (is_if2t(expr)) { - const if2t &_if = to_if2t(expr); - - expr2tc true_cond, false_cond; - if (!is_nil_expr(cond)) - { - true_cond = and2tc(cond, _if.cond); - false_cond = and2tc(cond, not2tc(_if.cond)); - } - else - { - true_cond = _if.cond; - false_cond = not2tc(_if.cond); - } + expr->type = get_intloc_type(); + create_rhs_location(to_if2t(expr).true_value); + create_rhs_location(to_if2t(expr).false_value); + return; + } - return or2tc( - transfer_to_assume(_if.true_value, true_cond, lhs), - transfer_to_assume(_if.false_value, false_cond, lhs) - ); + if (is_constant_intheap2t(expr)) + { + expr = gen_nil(); + // TODO + return; } - - // find the terminal valuew - expr2tc eq = equality2tc(lhs, expr); - return is_nil_expr(cond) ? eq : and2tc(cond, eq); + + log_error("Something wrong"); + expr->dump(); + abort(); } \ No newline at end of file From 04c11b7f1c6a721a3bd47e0797123f2e903f1861 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 26 Sep 2024 00:18:19 +0800 Subject: [PATCH 094/126] do some optimization --- src/goto-symex/goto_symex.h | 10 ++++++++++ src/goto-symex/symex_assign.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index e8b24164..e3f41cd0 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -875,6 +875,16 @@ class goto_symext */ void symex_nondet(const expr2tc &lhs, const expr2tc &effect); + /** + * @brief + * + * @param lhs_loc + * @param rhs + * @return true + * @return false + */ + bool has_different_loc(const std::string &lhs_loc, const expr2tc &expr); + /** * @brief Create a rhs location of object * diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 92f4ca3e..6a3035aa 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -422,6 +422,7 @@ void goto_symext::symex_assign_symbol( { // assign loc for each region const intheap_type2t &lhs_ty = to_intheap_type(lhs->type); + if (lhs_ty.is_region) { if (is_nil_expr(lhs_ty.location)) @@ -430,11 +431,15 @@ void goto_symext::symex_assign_symbol( log_error("No location"); abort(); } + expr2tc lhs_loc = lhs_ty.location; expr2tc rhs_loc = org_rhs; + + const std::string lhs_loc_name = to_symbol2t(lhs_loc).get_symbol_name(); + if (!has_different_loc(lhs_loc_name, rhs_loc)) return; + create_rhs_location(rhs_loc); - log_status("Begin assign location"); symex_assign(code_assign2tc(lhs_loc, rhs_loc)); } } @@ -1235,11 +1240,31 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) log_status(" ======== symex nondet ===== "); } + +bool goto_symext::has_different_loc( + const std::string &lhs_loc, const expr2tc &expr) +{ + if (!is_intheap_type(expr)) return false; + if (is_nil_expr(to_intheap_type(expr->type).location)) return false; + + bool res = false; + const expr2tc &loc = to_intheap_type(expr->type).location; + if (lhs_loc != to_symbol2t(loc).get_symbol_name()) + res = true; + + if (is_if2t(expr)) + res |= + has_different_loc(lhs_loc, to_if2t(expr).true_value) | + has_different_loc(lhs_loc, to_if2t(expr).false_value); + + return res; +} + void goto_symext::create_rhs_location(expr2tc &expr) { if (is_nil_expr(expr)) return; - if (is_symbol2t(expr) && + if ((is_symbol2t(expr) || is_heap_update2t(expr)) && !is_nil_expr(to_intheap_type(expr->type).location)) { const intheap_type2t &ty = to_intheap_type(expr->type); From c3307a22139599101c9d24a121ea61a6ae9b0791 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 26 Sep 2024 08:02:01 +0800 Subject: [PATCH 095/126] fix: dot not assign loc --- src/goto-symex/goto_symex.h | 17 ------- src/goto-symex/symex_assign.cpp | 83 --------------------------------- 2 files changed, 100 deletions(-) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index e3f41cd0..d1099b64 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -875,23 +875,6 @@ class goto_symext */ void symex_nondet(const expr2tc &lhs, const expr2tc &effect); - /** - * @brief - * - * @param lhs_loc - * @param rhs - * @return true - * @return false - */ - bool has_different_loc(const std::string &lhs_loc, const expr2tc &expr); - - /** - * @brief Create a rhs location of object - * - * @param expr - */ - void create_rhs_location(expr2tc &expr); - /** * Fetch reference to global dynamic object counter. * @return Reference to global dynamic object counter. diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 6a3035aa..20fe04a3 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -413,36 +413,6 @@ void goto_symext::symex_assign_symbol( cur_state->gen_stack_trace(), hidden, first_loop); - - if (is_intheap_type(lhs) && - is_intheap_type(org_rhs) && - !is_heap_region2t(org_rhs) && - !is_constant_intheap2t(org_rhs) && - !is_heap_update2t(org_rhs)) - { - // assign loc for each region - const intheap_type2t &lhs_ty = to_intheap_type(lhs->type); - - if (lhs_ty.is_region) - { - if (is_nil_expr(lhs_ty.location)) - { - // TODO: fix it - log_error("No location"); - abort(); - } - - expr2tc lhs_loc = lhs_ty.location; - expr2tc rhs_loc = org_rhs; - - const std::string lhs_loc_name = to_symbol2t(lhs_loc).get_symbol_name(); - if (!has_different_loc(lhs_loc_name, rhs_loc)) return; - - create_rhs_location(rhs_loc); - - symex_assign(code_assign2tc(lhs_loc, rhs_loc)); - } - } } void goto_symext::symex_assign_structure( @@ -1101,7 +1071,6 @@ expr2tc goto_symext::create_heap_region_loc(const expr2tc &expr) new_context.add(loc_sym); expr2tc base_loc = symbol2tc(get_intloc_type(), loc_sym.id); - return base_loc; } @@ -1238,56 +1207,4 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) } log_status(" ======== symex nondet ===== "); -} - - -bool goto_symext::has_different_loc( - const std::string &lhs_loc, const expr2tc &expr) -{ - if (!is_intheap_type(expr)) return false; - if (is_nil_expr(to_intheap_type(expr->type).location)) return false; - - bool res = false; - const expr2tc &loc = to_intheap_type(expr->type).location; - if (lhs_loc != to_symbol2t(loc).get_symbol_name()) - res = true; - - if (is_if2t(expr)) - res |= - has_different_loc(lhs_loc, to_if2t(expr).true_value) | - has_different_loc(lhs_loc, to_if2t(expr).false_value); - - return res; -} - -void goto_symext::create_rhs_location(expr2tc &expr) -{ - if (is_nil_expr(expr)) return; - - if ((is_symbol2t(expr) || is_heap_update2t(expr)) && - !is_nil_expr(to_intheap_type(expr->type).location)) - { - const intheap_type2t &ty = to_intheap_type(expr->type); - expr = ty.location; - return; - } - - if (is_if2t(expr)) - { - expr->type = get_intloc_type(); - create_rhs_location(to_if2t(expr).true_value); - create_rhs_location(to_if2t(expr).false_value); - return; - } - - if (is_constant_intheap2t(expr)) - { - expr = gen_nil(); - // TODO - return; - } - - log_error("Something wrong"); - expr->dump(); - abort(); } \ No newline at end of file From 58f0f67029821eb93f2f6272be1276e31e5245c5 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 26 Sep 2024 14:35:14 +0800 Subject: [PATCH 096/126] handle alloc struct, automatically free --- benchmark/case_5.c | 24 ++- benchmark/case_6.c | 28 ++- src/goto-symex/builtin_functions.cpp | 187 +++++++++++++++++-- src/goto-symex/dynamic_allocation.cpp | 46 ++++- src/goto-symex/goto_symex.h | 2 +- src/goto-symex/goto_symex_state.cpp | 5 +- src/goto-symex/goto_symex_state.h | 3 + src/goto-symex/slice.cpp | 3 - src/goto-symex/symex_assign.cpp | 178 +----------------- src/goto-symex/symex_function.cpp | 44 ++++- src/irep2/irep2_type.h | 16 +- src/irep2/templates/irep2_templates.cpp | 2 +- src/irep2/templates/irep2_templates_type.cpp | 2 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 8 +- src/util/c_types.cpp | 2 +- 15 files changed, 336 insertions(+), 214 deletions(-) diff --git a/benchmark/case_5.c b/benchmark/case_5.c index db95e9ab..a5be5ac2 100644 --- a/benchmark/case_5.c +++ b/benchmark/case_5.c @@ -1,9 +1,21 @@ +extern void abort(void); +#include +void reach_error() { assert(0); } + #include +typedef struct { + void *lo; + void *hi; +} TData; + +TData* create_node() +{ + TData data; + return &data; +} -int main(){ - for(int i = 0; i < 5; i ++){ - int *j = (int*)malloc(sizeof(int)); - free(j); - } -} \ No newline at end of file +int main() { + free(create_node()); + return 0; +} diff --git a/benchmark/case_6.c b/benchmark/case_6.c index 91b205b3..0249ef5f 100644 --- a/benchmark/case_6.c +++ b/benchmark/case_6.c @@ -1,10 +1,24 @@ +extern void abort(void); +#include +void reach_error() { assert(0); } + #include +typedef struct { + void *lo; + void *hi; +} TData; + +TData* create_node() +{ + TData data; + return &data; +} -int main(){ - int a = 10; - int* j = malloc(4); - if(a > 10){ - free(j); - } -} \ No newline at end of file +int main() { + TData *p1 = create_node(); + TData *p2 = create_node(); + free(p1); + free(p2); + return 0; +} diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index cf225eee..e34aecfc 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -270,19 +270,7 @@ expr2tc goto_symext::symex_mem( get_intheap_type(), gen_ulong(to_intheap_type(rhs_region->type).total_bytes)); - if (dynamic_memory.size() > 0) - { - expr2tc disj = disjh2tc(rhs_heap); - for (auto const &it : dynamic_memory) - to_disjh2t(disj).do_disjh(it.obj); - cur_state->rename(disj); - target->assumption( - cur_state->guard.as_expr(), - disj, - cur_state->source, - first_loop - ); - } + symex_disj_heaps(rhs_heap); log_status("use dynamic memory to track malloc heap - {}", to_symbol2t(rhs_heap).get_symbol_name()); @@ -1812,3 +1800,176 @@ bool goto_symext::run_builtin( return false; } + +// Builtin SLHV function +expr2tc goto_symext::create_heap_region_loc(const expr2tc &expr) +{ + if (!is_symbol2t(expr)) + { + log_error("Wrong symbol"); + abort(); + } + expr2tc l1_sym = expr; + cur_state->top().level1.get_ident_name(l1_sym); + + symbolt loc_sym; + loc_sym.name = + id2string(to_symbol2t(l1_sym).get_symbol_name()) + std::string("_loc"); + loc_sym.id = std::string("symex_location::") + id2string(loc_sym.name); + loc_sym.lvalue = true; + loc_sym.type = typet(typet::t_intloc); + loc_sym.mode = "C"; + new_context.add(loc_sym); + + expr2tc base_loc = symbol2tc(get_intloc_type(), loc_sym.id); + return base_loc; +} + +type2tc goto_symext::create_heap_region_type( + const type2tc &type, + unsigned int bytes, + const expr2tc &loc) +{ + type2tc heap_type = get_intheap_type(); + intheap_type2t &_heap_type = to_intheap_type(heap_type); + _heap_type.location = loc; + _heap_type.total_bytes = bytes; + _heap_type.is_region = true; + + if (is_struct_type(type)) + { + _heap_type.is_aligned = true; + _heap_type.total_bytes = bytes; + const struct_type2t &_type = to_struct_type(type); + _heap_type.field_types.clear(); + const std::vector &inner_types = _type.get_structure_members(); + const std::vector &inner_field_names = _type.get_structure_member_names(); + for (unsigned int i = 0; i < inner_field_names.size(); i++) + { + const std::string &field_name = inner_field_names[i].as_string(); + if (field_name.find("anon_pad") != std::string::npos) continue; + _heap_type.field_types.push_back( + is_pointer_type(inner_types[i]) ? get_intloc_type() : get_int64_type() + ); + } + } + else + _heap_type.field_types.push_back(empty_type2tc()); + + return heap_type; +} + +expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &flag) +{ + // log_status(" ======= create a heap region ========== "); + + type2tc type; + if (effect.kind == sideeffect2t::nondet) + { + // alloc a heap region in stack + type = effect.type; + } + else + { + // malloc a heap region + type = effect.alloctype; + if (is_nil_type(type)) type = char_type2(); + } + + expr2tc base_loc = create_heap_region_loc(flag); + + unsigned int bytes; + if (is_struct_type(type)) + { + bytes = type_byte_size(type, &ns).to_uint64(); + } + else + { + expr2tc op = effect.operand; + cur_state->rename(op); + do_simplify(op); + if (!is_constant_int2t(op)) + { + log_error("Do not support dynamic size"); + abort(); + } + bytes = to_constant_int2t(op).value.to_uint64(); + } + + log_status("malloc size : {}", bytes); + + type2tc heap_type = create_heap_region_type(type, bytes, base_loc); + if (effect.kind == sideeffect2t::nondet) + to_intheap_type(heap_type).is_alloced = true; + flag->type = heap_type; + + // log_status(" ======= create a heap region ========== "); + return heap_region2tc(heap_type, base_loc); +} + +void goto_symext::symex_disj_heaps(const expr2tc &heap) +{ + if (!is_symbol2t(heap) || !is_intheap_type(heap)) + { + log_status("Wrong heap region"); + abort(); + } + + expr2tc l0_heap = heap; + cur_state->get_original_name(l0_heap); + expr2tc disj = disjh2tc(l0_heap); + + for (auto const &it : cur_state->top().local_heap_regions) + to_disjh2t(disj).do_disjh(it); + + for (auto const &it : dynamic_memory) + to_disjh2t(disj).do_disjh(it.obj); + + if (to_disjh2t(disj).other_heaps.size() == 0) + return; + + cur_state->rename(disj); + target->assumption( + cur_state->guard.as_expr(), + disj, + cur_state->source, + first_loop + ); +} + +void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) +{ + // log_status(" ======== symex nondet ===== "); + // lhs->dump(); + // effect->dump(); + + expr2tc new_lhs = lhs; + expr2tc new_rhs = effect; + + const sideeffect2t &_effect = to_sideeffect2t(effect); + + if (_effect.kind == sideeffect2t::nondet && + !is_struct_type(_effect.type)) + replace_nondet(new_rhs); + else + new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); + + symex_assign(code_assign2tc(new_lhs, new_rhs)); + + if (is_intheap_type(new_lhs->type)) + { + const intheap_type2t &_type = to_intheap_type(new_lhs->type); + + track_new_pointer( + _type.location, + get_intheap_type(), + gen_ulong(_type.total_bytes)); + + symex_disj_heaps(new_lhs); + + cur_state->get_original_name(new_lhs); + cur_state->top().local_heap_regions.push_back(new_lhs); + } + + // log_status(" ======== symex nondet ===== "); +} \ No newline at end of file diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 9cb9dae7..603cd085 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -30,7 +30,6 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc index_expr = index2tc(get_bool_type(), alloc_arr_2, obj_expr); expr = index_expr; } else { - // Checking that the object is valid by heap_alloc_size const valid_object2t &obj = to_valid_object2t(expr); const expr2tc &heap_region = obj.value; if (!is_intheap_type(heap_region->type) || @@ -39,8 +38,51 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) log_error("Wrong object"); abort(); } + const intheap_type2t &type = to_intheap_type(heap_region->type); - expr = not2tc(equality2tc(heap_region, gen_emp())); + if (type.is_alloced) + { + expr2tc loc = type.location; + cur_state->get_original_name(loc); + + bool is_in_frame = false; + goto_symex_statet::framet &frame = cur_state->top(); + for (auto const &it : frame.local_heap_regions) + { + expr2tc alloced_loc = to_intheap_type(it->type).location; + cur_state->get_original_name(alloced_loc); + + if (to_symbol2t(loc).get_symbol_name() != + to_symbol2t(alloced_loc).get_symbol_name()) + continue; + + is_in_frame = true; + } + + if (is_in_frame) + expr = not2tc(equality2tc(heap_region, gen_emp())); + else + { + // use alloc_size_heap + expr2tc alloc_size_heap; + migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); + + unsigned int &nondet_counter = get_nondet_counter(); + nondet_counter++; + expr2tc size_sym = + symbol2tc( + get_int64_type(), + std::string("SOME_SIZE_") + std::to_string(nondet_counter) + ); + + expr2tc pt = points_to2tc(loc, size_sym); + expr2tc disj = disjh2tc(alloc_size_heap); + to_disjh2t(disj).do_disjh(pt); + expr = not2tc(disj); + } + } + else + expr = not2tc(equality2tc(heap_region, gen_emp())); } } else if (is_invalid_pointer2t(expr)) diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index d1099b64..8d54f968 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -865,7 +865,7 @@ class goto_symext * * @param heap */ - expr2tc symex_disj_heaps(const expr2tc &heap); + void symex_disj_heaps(const expr2tc &heap); /** * @brief In SLHV, struct/array are heap variable diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 321e8f95..1e428bba 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -281,7 +281,10 @@ void goto_symex_statet::rename(expr2tc &expr) else if (is_location_of2t(expr)) { location_of2t &locof = to_location_of2t(expr); - rename_address(locof.source_heap); + if (is_pointer_type(locof.source_heap)) + rename_address(locof.source_heap); + else + rename(locof.source_heap); rename_type(locof.source_heap); } else diff --git a/src/goto-symex/goto_symex_state.h b/src/goto-symex/goto_symex_state.h index 5f794654..eafae42a 100644 --- a/src/goto-symex/goto_symex_state.h +++ b/src/goto-symex/goto_symex_state.h @@ -201,6 +201,9 @@ class goto_symex_statet /** Set of local variable l1 names. */ variable_name_sett local_variables; + /** Set of local heap region for struct/... */ + std::vector local_heap_regions; + /** Record the first va_args index used in this function call, if any, * otherwise UINT_MAX */ diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 6922ffc5..0f96e3f8 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -13,9 +13,6 @@ bool symex_slicet::get_symbols(const expr2tc &expr) bool res = false; if (is_heap_region2t(expr)) return false; - if (is_intheap_type(expr) && - !is_nil_expr(to_intheap_type(expr->type).location)) - get_symbols(to_intheap_type(expr->type).location); // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 20fe04a3..c5246094 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -382,6 +382,9 @@ void goto_symext::symex_assign_symbol( cur_state->rename(rhs); do_simplify(rhs); + log_status("after rename rhs"); + rhs->dump(); + if (!is_nil_expr(full_rhs)) { cur_state->rename(full_rhs); @@ -902,7 +905,9 @@ void goto_symext::symex_assign_fieldof( assert(is_scalar_type(rhs)); const field_of2t& field_of = to_field_of2t(lhs); - const expr2tc &heap_region = field_of.source_heap; + expr2tc heap_region = field_of.source_heap; + // make sure it is l1 name + cur_state->level2.get_original_name(heap_region); const expr2tc &field = field_of.operand; expr2tc update_heap = @@ -910,17 +915,7 @@ void goto_symext::symex_assign_fieldof( symex_assign_rec(heap_region, full_lhs, update_heap, full_rhs, guard, hidden); - expr2tc disj = disjh2tc(heap_region); - cur_state->get_original_name(disj); - for (auto const& it : dynamic_memory) - to_disjh2t(disj).do_disjh(it.obj); - cur_state->rename(disj); - target->assumption( - cur_state->guard.as_expr(), - disj, - cur_state->source, - first_loop - ); + symex_disj_heaps(heap_region); } void goto_symext::replace_nondet(expr2tc &expr) @@ -1048,163 +1043,6 @@ void goto_symext::replace_tuple(expr2tc &expr) expr2tc base_loc = create_heap_region_loc(expr); expr->type = create_heap_region_type(expr->type, bytes, base_loc); + to_intheap_type(expr->type).is_alloced = true; } -} - -expr2tc goto_symext::create_heap_region_loc(const expr2tc &expr) -{ - if (!is_symbol2t(expr)) - { - log_error("Wrong symbol"); - abort(); - } - expr2tc l1_sym = expr; - cur_state->level2.get_original_name(l1_sym); - - symbolt loc_sym; - loc_sym.name = - id2string(to_symbol2t(l1_sym).get_symbol_name()) + std::string("_loc"); - loc_sym.id = std::string("symex_location::") + id2string(loc_sym.name); - loc_sym.lvalue = true; - loc_sym.type = typet(typet::t_intloc); - loc_sym.mode = "C"; - new_context.add(loc_sym); - - expr2tc base_loc = symbol2tc(get_intloc_type(), loc_sym.id); - return base_loc; -} - -type2tc goto_symext::create_heap_region_type( - const type2tc &type, - unsigned int bytes, - const expr2tc &loc) -{ - type2tc heap_type = get_intheap_type(); - intheap_type2t &_heap_type = to_intheap_type(heap_type); - _heap_type.location = loc; - _heap_type.total_bytes = bytes; - _heap_type.is_region = true; - - if (is_struct_type(type)) - { - _heap_type.is_aligned = true; - _heap_type.total_bytes = bytes; - const struct_type2t &_type = to_struct_type(type); - _heap_type.field_types.clear(); - const std::vector &inner_types = _type.get_structure_members(); - const std::vector &inner_field_names = _type.get_structure_member_names(); - for (unsigned int i = 0; i < inner_field_names.size(); i++) - { - const std::string &field_name = inner_field_names[i].as_string(); - if (field_name.find("anon_pad") != std::string::npos) continue; - _heap_type.field_types.push_back( - is_pointer_type(inner_types[i]) ? get_intloc_type() : get_int64_type() - ); - } - } - else - _heap_type.field_types.push_back(empty_type2tc()); - - return heap_type; -} - -expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &flag) -{ - log_status(" ======= create a heap region ========== "); - - type2tc type; - if (effect.kind == sideeffect2t::nondet) - { - // alloc a heap region in stack - type = effect.type; - } - else - { - // malloc a heap region - type = effect.alloctype; - if (is_nil_type(type)) type = char_type2(); - } - - expr2tc base_loc = create_heap_region_loc(flag); - - unsigned int bytes; - if (is_struct_type(type)) - { - bytes = type_byte_size(type, &ns).to_uint64(); - } - else - { - expr2tc op = effect.operand; - cur_state->rename(op); - do_simplify(op); - if (!is_constant_int2t(op)) - { - log_error("Do not support dynamic size"); - abort(); - } - bytes = to_constant_int2t(op).value.to_uint64(); - } - - log_status("malloc size : {}", bytes); - - type2tc heap_type = create_heap_region_type(type, bytes, base_loc); - flag->type = heap_type; - - log_status(" ======= create a heap region ========== "); - return heap_region2tc(heap_type, base_loc); -} - -expr2tc goto_symext::symex_disj_heaps(const expr2tc &heap) -{ - if (!is_symbol2t(heap) || !is_intheap_type(heap)) - { - log_status("Wrong heap region"); - abort(); - } - - expr2tc l0_heap = heap; - cur_state->get_original_name(l0_heap); - - expr2tc disj; - for (auto const &it : dynamic_memory) - { - expr2tc h = it.obj; - if (to_symbol2t(h).get_symbol_name() - == to_symbol2t(l0_heap).get_symbol_name()) - continue; - } -} - -void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) -{ - log_status(" ======== symex nondet ===== "); - lhs->dump(); - effect->dump(); - - expr2tc new_lhs = lhs; - expr2tc new_rhs = effect; - - const sideeffect2t &_effect = to_sideeffect2t(effect); - - if (_effect.kind == sideeffect2t::nondet && - !is_struct_type(_effect.type)) - replace_nondet(new_rhs); - else - new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); - - symex_assign(code_assign2tc(lhs, new_rhs)); - - // TODO : maybe added to set to do disjh - - if (is_intheap_type(new_lhs->type)) - { - const intheap_type2t &_type = to_intheap_type(new_lhs->type); - - track_new_pointer( - _type.location, - get_intheap_type(), - gen_ulong(_type.total_bytes)); - } - - log_status(" ======== symex nondet ===== "); } \ No newline at end of file diff --git a/src/goto-symex/symex_function.cpp b/src/goto-symex/symex_function.cpp index becf39c7..7d810e91 100644 --- a/src/goto-symex/symex_function.cpp +++ b/src/goto-symex/symex_function.cpp @@ -57,6 +57,8 @@ unsigned goto_symext::argument_assignments( // iterates over the operands std::vector::const_iterator it1 = arguments.begin(); + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + // iterates over the types of the arguments for (unsigned int name_idx = 0; name_idx < function_type.arguments.size(); ++name_idx) @@ -113,7 +115,38 @@ unsigned goto_symext::argument_assignments( // Assign value to function argument // TODO: Should we hide it (true means hidden)? - symex_assign(code_assign2tc(lhs, rhs), true); + if (use_old_encoding) + symex_assign(code_assign2tc(lhs, rhs), true); + else + { + // If an argument is intheap type in SLHV, we create the + // heap_region for them and assign all field from rhs + if (is_struct_type(lhs)) + { + const struct_type2t &_type = to_struct_type(lhs->type); + expr2tc sideeffect = + sideeffect2tc( + lhs->type, + expr2tc(), + expr2tc(), + std::vector(), + type2tc(), + sideeffect2t::nondet + ); + // Create a heap region for lhs + symex_assign(code_assign2tc(lhs, sideeffect)); + + for (unsigned int i = 0; i < _type.members.size(); i++) + { + type2tc field_type = _type.members[i]; + expr2tc lhs_field_i = field_of2tc(field_type, lhs, gen_ulong(i)); + expr2tc rhs_field_i = field_of2tc(field_type, rhs, gen_ulong(i)); + symex_assign(code_assign2tc(lhs_field_i, rhs_field_i)); + } + } + else + symex_assign(code_assign2tc(lhs, rhs), true); + } } it1++; @@ -505,6 +538,15 @@ void goto_symext::pop_frame() if (!cur_state->guard.is_false()) cur_state->guard = frame.entry_guard; + + // free local heap regions + for (auto const &it : frame.local_heap_regions) + { + expr2tc l1_reg = it; + frame.level1.get_ident_name(l1_reg); + expr2tc l1_loc = location_of2tc(l1_reg); + symex_free(code_free2tc(l1_loc)); + } // clear locals from L2 renaming for (auto const &it : frame.local_variables) diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index 9332b103..c0a57fba 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -211,10 +211,11 @@ class intheap_data : public type2t const expr2tc &loc, unsigned int tb, bool ir, - bool ia) + bool ia, + bool ic) : type2t(id), location(loc), total_bytes(tb), - is_region(ir), is_aligned(ia) + is_region(ir), is_aligned(ia), is_alloced(ic) { } intheap_data(const intheap_data &ref) = default; @@ -224,6 +225,7 @@ class intheap_data : public type2t unsigned int total_bytes; bool is_region; bool is_aligned; + bool is_alloced; // Type mangling: typedef esbmct::field_traits @@ -236,12 +238,15 @@ class intheap_data : public type2t is_region_field; typedef esbmct::field_traits is_aligned_field; + typedef esbmct::field_traits + is_alloced_field; typedef esbmct::type2t_traits< location_field, field_types_field, total_bytes_field, is_region_field, - is_aligned_field> traits; + is_aligned_field, + is_alloced_field> traits; }; class pointer_data : public type2t @@ -402,11 +407,12 @@ class intheap_type2t : public intheap_type_methods const expr2tc &location, unsigned int total_bytes, bool is_region, - bool is_aligned) + bool is_aligned, + bool is_alloced) : intheap_type_methods( intheap_id, location, total_bytes, - is_region, is_aligned) + is_region, is_aligned, is_alloced) { if (is_region && this->field_types.empty()) this->field_types.push_back(empty_type2tc()); diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index a83dbe00..e87554e2 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -12,7 +12,7 @@ std::string empty_type2t::field_names[esbmct::num_type_fields] = std::string intloc_type2t::field_names[esbmct::num_type_fields] = {"", "", "", "", ""}; std::string intheap_type2t::field_names[esbmct::num_type_fields] = - {"location", "field_types", "total_bytes", "is_region", "is_aligned", ""}; + {"location", "field_types", "total_bytes", "is_region", "is_aligned", "is_alloced"}; std::string symbol_type2t::field_names[esbmct::num_type_fields] = {"symbol_name", "", "", "", ""}; std::string struct_type2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_type.cpp b/src/irep2/templates/irep2_templates_type.cpp index 6e6efbc3..ac385498 100644 --- a/src/irep2/templates/irep2_templates_type.cpp +++ b/src/irep2/templates/irep2_templates_type.cpp @@ -2,7 +2,7 @@ type_typedefs_empty(bool_type, type2t); type_typedefs_empty(empty_type, type2t); -type_typedefs4(intheap_type, intheap_data); +type_typedefs5(intheap_type, intheap_data); type_typedefs_empty(intloc_type, type2t); type_typedefs1(symbol_type, symbol_type_data); type_typedefs5(struct_type, struct_union_data); diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 584b053c..1614a9cc 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -534,7 +534,11 @@ z3_slhv_convt::convert_slhv_opts( const field_of2t &field_of = to_field_of2t(expr); if (is_constant_intheap2t(field_of.source_heap)) - return mk_fresh(convert_sort(field_of.type), mk_fresh_name("invalid_fieldof_")); + return + mk_fresh( + convert_sort(field_of.type), + mk_fresh_name("invalid_fieldof_") + ); if (!is_constant_int2t(field_of.operand)) { @@ -561,7 +565,7 @@ z3_slhv_convt::convert_slhv_opts( smt_astt pt = mk_pt(l, v1); smt_astt load_success = mk_subh(pt, h); - smt_astt load_fail = mk_disjh(pt, h); // v1 is free + smt_astt load_fail = mk_eq(h, mk_emp()); smt_astt load_res = mk_or(load_success, load_fail); assert_ast(load_res); diff --git a/src/util/c_types.cpp b/src/util/c_types.cpp index f10dd765..c33e748c 100644 --- a/src/util/c_types.cpp +++ b/src/util/c_types.cpp @@ -396,7 +396,7 @@ type2tc get_empty_type() type2tc get_intheap_type(unsigned int sz) { - return intheap_type2tc(expr2tc(), sz, false, false); + return intheap_type2tc(expr2tc(), sz, false, false, false); } type2tc get_intloc_type() { From 16707ce7322787f0f964039ffc30722731a86a82 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 26 Sep 2024 14:38:31 +0800 Subject: [PATCH 097/126] esbmc-slhv svcomp scripts --- .../esbmc-slhv-svcomp/esbmc-slhv-wrapper.py | 130 ++++++++++++++++++ scripts/esbmc-slhv-svcomp/esbmc-slhv.py | 56 ++++++++ scripts/esbmc-slhv-svcomp/esbmc-slhv.xml | 41 ++++++ 3 files changed, 227 insertions(+) create mode 100755 scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py create mode 100644 scripts/esbmc-slhv-svcomp/esbmc-slhv.py create mode 100644 scripts/esbmc-slhv-svcomp/esbmc-slhv.xml diff --git a/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py b/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py new file mode 100755 index 00000000..ef547cf4 --- /dev/null +++ b/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + +import argparse +from enum import Enum +import shlex +import subprocess +import sys + +esbmc_slhv = "./esbmc_slhv " +default_args = "--no-library --ir --force-malloc-success --result-only --multi-property --z3-slhv" + +class Property(Enum): + memory = 1 + memcleanup = 2 + +class Result(Enum): + success = 1 + fail_deref = 2 + fail_free = 3 + fail_memtrack = 4 + fail_memcleanup = 5 + unknown = 6 + +def analysis_result(out, prop): + + log = out.decode() + + invalid_deref = "Property: INVALID_DEREF Result: sat" + invalid_free = "Property: INVALID_FREE Result: sat" + memory_leak = "Property: MEMORY_LEAK Result: sat" + + if "VERIFICATION FAILED": + if prop == Property.memory: + if invalid_deref in log: + return Result.fail_deref + if invalid_free in log: + return Result.fail_free + if memory_leak in log: + return Result.fail_memtrack + + if prop == Property.memcleanup: + if memory_leak in log: + return Result.fail_memcleanup + + if "VERIFICATION SUCCESSFUL" in log: + return Result.success + + return Result.unknown + +def do_exec(cmd_line): + the_args = shlex.split(cmd_line) + p = subprocess.Popen(the_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = p.communicate() + return stdout + stderr + +def run(cmd_line): + print("Verifying with ESBMC_SLHV") + print("Command: " + cmd_line) + out = do_exec(cmd_line) + print(out.decode()) + return out + +def mk_cmd(benchmark, prop): + cmd = esbmc_slhv + benchmark + " " + default_args + if prop == Property.memory: + cmd += " --memory-leak-check" + elif prop == Property.memcleanup: + cmd += "--no-pointer-check --no-bounds-check --memory-leak-check" + return cmd + +def verify(benchmark, property): + cmd = mk_cmd(benchmark, property) + out = run(cmd) + return analysis_result(out, property) + +def get_result_string(the_result): + if the_result == Result.fail_memcleanup: + return "FALSE_MEMCLEANUP" + + if the_result == Result.fail_memtrack: + return "FALSE_MEMTRACK" + + if the_result == Result.fail_free: + return "FALSE_FREE" + + if the_result == Result.fail_deref: + return "FALSE_DEREF" + + if the_result == Result.success: + return "TRUE_PROP" + + if the_result == Result.unknown: + return "UNKNOWN" + + exit(0) + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument("benchmark", nargs='?', help="Path to the benchmark") + parser.add_argument("-v", "--version", help="Print version", action='store_true') + parser.add_argument("-p", "--propertyfile", help="Path to the property file") + + args = parser.parse_args() + property_file = args.propertyfile + benchmark = args.benchmark + + # if property_file is None: + # print("Please, specify a property file") + # exit(1) + + if benchmark is None: + print("Please, specify a benchmark to verify") + exit(1) + + # Parse property files + # f = open(property_file, 'r') + # property_file_content = f.read() + + property = Property.memory + # if "CHECK( init(main()), LTL(G valid-free) )" in property_file_content: + # property = Property.memory + # elif "CHECK( init(main()), LTL(G valid-memcleanup) )" in property_file_content: + # property = Property.memcleanup + # else: + # print("Unsupported Property") + # exit(1) + + result = verify(benchmark, property) + print(get_result_string(result)) \ No newline at end of file diff --git a/scripts/esbmc-slhv-svcomp/esbmc-slhv.py b/scripts/esbmc-slhv-svcomp/esbmc-slhv.py new file mode 100644 index 00000000..65c7169a --- /dev/null +++ b/scripts/esbmc-slhv-svcomp/esbmc-slhv.py @@ -0,0 +1,56 @@ +# This file is part of BenchExec, a framework for reliable benchmarking: +# https://github.com/sosy-lab/benchexec + +import os +from benchexec.tools.sv_benchmarks_util import get_data_model_from_task, ILP32, LP64 +import benchexec.tools.template +import benchexec.result as result + + +class Tool(benchexec.tools.template.BaseTool2): + """ + This class serves as tool adaptor for ESBMC-SLHV + """ + + def executable(self, tool_locator): + return tool_locator.find_executable("esbmc-slhv-wrapper.py") + + def working_directory(self, executable): + executableDir = os.path.dirname(executable) + return executableDir + + def version(self, executable): + return self._version_from_tool(executable, "-v") + + def name(self): + return "ESBMC-SLHV" + + def project_url(self): + return "todo" + + def cmdline(self, executable, options, task, rlimits): + data_model_param = get_data_model_from_task(task, {ILP32: "32", LP64: "64"}) + return ( + [executable] + + ["-p", task.property_file] + + options + + [task.single_input_file] + ) + + def determine_result(self, run): + status = result.RESULT_ERROR + + if run.output.any_line_contains("FALSE_DEREF"): + status = result.RESULT_FALSE_DEREF + elif run.output.any_line_contains("FALSE_FREE"): + status = result.RESULT_FALSE_FREE + elif run.output.any_line_contains("FALSE_MEMTRACK"): + status = result.RESULT_FALSE_MEMTRACK + elif run.output.any_line_contains("FALSE_MEMCLEANUP"): + status = result.RESULT_FALSE_MEMCLEANUP + elif run.output.any_line_contains("TRUE_PROP"): + status = result.RESULT_TRUE_PROP + elif run.output.any_line_contains("UNKNOWN"): + status = result.RESULT_UNKNOWN + + return status diff --git a/scripts/esbmc-slhv-svcomp/esbmc-slhv.xml b/scripts/esbmc-slhv-svcomp/esbmc-slhv.xml new file mode 100644 index 00000000..f9dff305 --- /dev/null +++ b/scripts/esbmc-slhv-svcomp/esbmc-slhv.xml @@ -0,0 +1,41 @@ + + + + + **/*.graphml + + + + ../sv-benchmarks/c/MemSafety-Arrays.set + ../sv-benchmarks/c/properties/valid-memsafety.prp + + + ../sv-benchmarks/c/MemSafety-Heap.set + ../sv-benchmarks/c/properties/valid-memsafety.prp + + + ../sv-benchmarks/c/MemSafety-LinkedLists.set + ../sv-benchmarks/c/properties/valid-memsafety.prp + + + ../sv-benchmarks/c/MemSafety-Other.set + ../sv-benchmarks/c/properties/valid-memsafety.prp + + + ../sv-benchmarks/c/MemSafety-Juliet.set + ../sv-benchmarks/c/properties/valid-memsafety.prp + + + + + + ../sv-benchmarks/c/MemSafety-MemCleanup.set + ../sv-benchmarks/c/properties/valid-memcleanup.prp + + + ../sv-benchmarks/c/SoftwareSystems-uthash-MemCleanup.set + ../sv-benchmarks/c/properties/valid-memcleanup.prp + + + + From 20dfa4c8a6b1937b50020d8c11666950c5c0ab7d Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 26 Sep 2024 14:52:48 +0800 Subject: [PATCH 098/126] update script --- scripts/esbmc-slhv-svcomp/pack.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 scripts/esbmc-slhv-svcomp/pack.sh diff --git a/scripts/esbmc-slhv-svcomp/pack.sh b/scripts/esbmc-slhv-svcomp/pack.sh new file mode 100755 index 00000000..412505ae --- /dev/null +++ b/scripts/esbmc-slhv-svcomp/pack.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# make it right +ESBMC_SLHV_ROOT="../.." +EXEC_PATH="./exec" + +WRAPPER_PATH="./esbmc-slhv-wrapper.py" + +mkdir ${EXEC_PATH} + +cp ${ESBMC_SLHV_ROOT}/build/src/esbmc/esbmc ${EXEC_PATH}/esbmc_slhv +cp ${WRAPPER_PATH} ${EXEC_PATH}/ + +zip -r esbmc-slhv.zip ${EXEC_PATH} + +rm -r ${EXEC_PATH} \ No newline at end of file From 24644f11f4813ab37a083c193127cfa96289a114 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 28 Sep 2024 11:58:46 +0800 Subject: [PATCH 099/126] use verbosity to turn on(off) debug info --- .gitignore | 3 +- scripts/x.py | 28 +- src/esbmc/esbmc_parseoptions.cpp | 6 +- src/goto-symex/builtin_functions.cpp | 43 +- src/goto-symex/dynamic_allocation.cpp | 3 - src/goto-symex/execution_state.cpp | 4 - src/goto-symex/goto_symex_state.cpp | 8 - src/goto-symex/reachability_tree.cpp | 1 - src/goto-symex/symex_assign.cpp | 74 +- src/goto-symex/symex_function.cpp | 15 +- src/goto-symex/symex_goto.cpp | 3 - src/goto-symex/symex_main.cpp | 45 +- src/goto-symex/symex_other.cpp | 4 - src/goto-symex/symex_target_equation.cpp | 6 +- src/irep2/irep2_expr.cpp | 2 +- src/pointer-analysis/dereference.cpp | 61 +- src/pointer-analysis/value_set.cpp | 27 +- src/solvers/smt/smt_conv.cpp | 1673 +++++++++++----------- src/solvers/z3-slhv/z3_slhv_conv.cpp | 11 +- src/solvers/z3/z3_conv.cpp | 7 +- 20 files changed, 961 insertions(+), 1063 deletions(-) diff --git a/.gitignore b/.gitignore index f9876a9a..1620cb4d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ __pycache__ .DS_Store tags .cache -release \ No newline at end of file +release +*.zip \ No newline at end of file diff --git a/scripts/x.py b/scripts/x.py index 0fccf974..364c5c2e 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -23,7 +23,7 @@ def help(): os.system(f"{esbmc_slhv} -h") def collect_one_assert(info): - assert(len(info) == 4) + assert(len(info) == 3) res = {} # Location @@ -34,14 +34,11 @@ def collect_one_assert(info): res["Line"] = location[4] res["Column"] = location[6] - # Property - property = info[2].split(" ") - res["Property"] = property[1] - - # Result & Time - rt = info[3].split(' ') - res["Result"] = rt[1] - res["Time"] = rt[3] + # Property & Result & Time + prt = info[2].split(" ") + res["Property"] = prt[1] + res["Result"] = prt[3] + res["Time"] = prt[5] return res @@ -86,22 +83,25 @@ def run_on(cprog, extra_args): "--output", vcc_log, "--multi-property", - "--z3-slhv" + "--z3-slhv", ] - redirect_arg = [">", t_log, "2>&1"] + if "--debug" in extra_args: + args.append("--verbosity SLHV:8") + + redirect_arg = [">", t_log] if "--std-out" not in extra_args: args += redirect_arg cmd = " ".join(args) print(f"Command: {cmd}") os.system(cmd) - + result = analysis_result(t_log) for d in result: res = [k + ": " + v for k, v in list(d.items())] print("{:<10} {:<12} {:<25} {:<15} {:<10}".format(*res)) - + return result def collect_results(cprog): @@ -161,7 +161,7 @@ def run_expriment_on(benchmark_root): if sys.argv[1] == "--compile": compile() elif sys.argv[1] == "--run": - run_on(sys.argv[2], sys.argv[3:-1]) + run_on(sys.argv[2], sys.argv[3:]) elif sys.argv[1] == "--expriment": run_expriment_on(sys.argv[2]) elif sys.argv[1] == "--help": diff --git a/src/esbmc/esbmc_parseoptions.cpp b/src/esbmc/esbmc_parseoptions.cpp index e6fd6df2..dfbe600d 100644 --- a/src/esbmc/esbmc_parseoptions.cpp +++ b/src/esbmc/esbmc_parseoptions.cpp @@ -502,8 +502,8 @@ int esbmc_parseoptionst::doit() // Create and preprocess a GOTO program if (get_goto_program(options, goto_functions)) return 6; - log_status("preprocessed goto program: "); - goto_functions.dump(); + if (messaget::state.modules.count("SLHV") > 0) + goto_functions.dump(); // Output claims about this program // (Fedor: should be moved to the output method perhaps) if (cmdline.isset("show-claims")) @@ -527,8 +527,6 @@ int esbmc_parseoptionst::doit() cmdline.isset("termination") || cmdline.isset("incremental-bmc") || cmdline.isset("falsification") || cmdline.isset("k-induction")) return do_bmc_strategy(options, goto_functions); - - log_status("before starting BMC"); // If no strategy is chosen, just rely on the simplifier // and the flags set through CMD diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index e34aecfc..f7341b81 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -110,10 +110,6 @@ expr2tc goto_symext::symex_mem( const expr2tc &lhs, const sideeffect2t &code) { - log_status(" ------------------- symex_mem --------------------------- "); - lhs->dump(); - code.dump(); - if (is_nil_expr(lhs)) return expr2tc(); // ignore @@ -231,7 +227,6 @@ expr2tc goto_symext::symex_mem( cur_state->rename(rhs); expr2tc rhs_copy(rhs); - log_status("symex assign in symex_mem: lhs = &allocated_array[index0]"); symex_assign(code_assign2tc(lhs, rhs), true); expr2tc ptr_obj = pointer_object2tc(pointer_type2(), ptr_rhs); @@ -242,8 +237,6 @@ expr2tc goto_symext::symex_mem( return to_address_of2t(rhs_addrof).ptr_obj; } else { - log_status("create heap symbol for allocation"); - // create a intheap symbol for heap region symbolt symbol; symbol.name = "dynamic_heap_"+ i2string(dynamic_counter); @@ -259,12 +252,9 @@ expr2tc goto_symext::symex_mem( expr2tc rhs_base_loc = to_heap_region2t(rhs_region).source_location; guardt rhs_guard = cur_state->guard; - log_status("symex assign in symex_mem: allocated_heap = heaplet"); symex_assign(code_assign2tc(rhs_heap, rhs_region)); - // only used for invalid pointer - // link pointer variable and heap variable - log_status("track new pointer - {}", to_symbol2t(rhs_base_loc).get_symbol_name()); + // only used for invalid pointer, link pointer variable and heap variable track_new_pointer( rhs_base_loc, get_intheap_type(), @@ -272,8 +262,6 @@ expr2tc goto_symext::symex_mem( symex_disj_heaps(rhs_heap); - log_status("use dynamic memory to track malloc heap - {}", - to_symbol2t(rhs_heap).get_symbol_name()); dynamic_memory.emplace_back( rhs_heap, rhs_guard, @@ -281,7 +269,6 @@ expr2tc goto_symext::symex_mem( to_symbol2t(rhs_heap).get_symbol_name() ); - log_status("create valueset base loc symbol and assign"); cur_state->rename(rhs_heap); symex_assign(code_assign2tc(lhs, location_of2tc(rhs_heap))); @@ -332,14 +319,15 @@ void goto_symext::track_new_pointer( void goto_symext::symex_free(const expr2tc &expr) { - log_status("xxxxxxx symex free"); + log_debug("SLHV", "xxxxxxx symex free"); const auto &code = static_cast(*expr); // Trigger 'free'-mode dereference of this pointer. Should generate various // dereference failure callbacks. expr2tc tmp = code.operand; - log_status("tmp before dereference FREE mode: "); - tmp->dump(); + log_debug("SLHV", "tmp before dereference FREE mode: "); + if (messaget::state.modules.count("SLHV") > 0) + tmp->dump(); dereference(tmp, dereferencet::FREE); // Don't rely on the output of dereference in free mode; instead fetch all // the internal dereference state for pointed at objects, and creates claims @@ -349,8 +337,6 @@ void goto_symext::symex_free(const expr2tc &expr) // Create temporary, dummy, dereference tmp = dereference2tc(get_uint8_type(), tmp); - log_status("tmp before dereference INTERNAL mode: "); - tmp->dump(); dereference(tmp, dereferencet::INTERNAL); // Only add assertions to check pointer offset if pointer check is enabled @@ -419,7 +405,7 @@ void goto_symext::symex_free(const expr2tc &expr) { if (!is_intheap_type(item.object)) { - log_status("Wrong object to be freed"); + log_error("Wrong object to be freed"); item.object->dump(); abort(); } @@ -438,7 +424,7 @@ void goto_symext::symex_free(const expr2tc &expr) guardt g; g.add(when); symex_assign(code_assign2tc(alloc_size_heap, new_heap), false, g); } - log_status("xxxxxxx symex free done"); + log_debug("SLHV", "xxxxxxx symex free done"); } void goto_symext::symex_printf(const expr2tc &lhs, expr2tc &rhs) @@ -1861,8 +1847,6 @@ type2tc goto_symext::create_heap_region_type( expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &flag) { - // log_status(" ======= create a heap region ========== "); - type2tc type; if (effect.kind == sideeffect2t::nondet) { @@ -1896,14 +1880,11 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla bytes = to_constant_int2t(op).value.to_uint64(); } - log_status("malloc size : {}", bytes); - type2tc heap_type = create_heap_region_type(type, bytes, base_loc); if (effect.kind == sideeffect2t::nondet) to_intheap_type(heap_type).is_alloced = true; flag->type = heap_type; - // log_status(" ======= create a heap region ========== "); return heap_region2tc(heap_type, base_loc); } @@ -1911,7 +1892,7 @@ void goto_symext::symex_disj_heaps(const expr2tc &heap) { if (!is_symbol2t(heap) || !is_intheap_type(heap)) { - log_status("Wrong heap region"); + log_error("Wrong heap region"); abort(); } @@ -1938,11 +1919,7 @@ void goto_symext::symex_disj_heaps(const expr2tc &heap) } void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) -{ - // log_status(" ======== symex nondet ===== "); - // lhs->dump(); - // effect->dump(); - +{ expr2tc new_lhs = lhs; expr2tc new_rhs = effect; @@ -1970,6 +1947,4 @@ void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) cur_state->get_original_name(new_lhs); cur_state->top().local_heap_regions.push_back(new_lhs); } - - // log_status(" ======== symex nondet ===== "); } \ No newline at end of file diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 603cd085..379479c3 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -126,9 +126,6 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { - log_status("replace invalid pointer"); - obj_expr->dump(); - expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); diff --git a/src/goto-symex/execution_state.cpp b/src/goto-symex/execution_state.cpp index 1ad125b9..4c8284ee 100644 --- a/src/goto-symex/execution_state.cpp +++ b/src/goto-symex/execution_state.cpp @@ -248,7 +248,6 @@ void execution_statet::symex_step(reachability_treet &art) switch (instruction.type) { case END_FUNCTION: - log_status("type: END_FUNCTION"); if (instruction.function == "__ESBMC_main") { end_thread(); @@ -275,17 +274,14 @@ void execution_statet::symex_step(reachability_treet &art) } break; case ATOMIC_BEGIN: - log_status("type: ATOMIC_BEGIN"); state.source.pc++; increment_active_atomic_number(); break; case ATOMIC_END: - log_status("type: ATOMIC_END"); decrement_active_atomic_number(); state.source.pc++; break; case RETURN: - log_status("type: RETURN"); if ( !state.guard.is_false() || !is_cur_state_guard_false(state.guard.as_expr())) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 1e428bba..2d696bdc 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -496,22 +496,14 @@ std::vector goto_symex_statet::gen_stack_trace() const void goto_symex_statet::dump() const { - log_status(" [XXXXXX state dump XXXXXX"); - log_status(" ------ thread num: "); std::cout << this->source.thread_nr << std::endl; - log_status(" ------ source pc: "); (*this->source.pc).dump(); - log_status(" ------ current state guard: "); // this->guard.dump(); this->guard.as_expr().get()->dump(); - log_status(" ------ level2: "); this->level2.dump(); - log_status(" ------ value set: "); this->value_set.dump(); - log_status(" ------ call stack"); for(auto item : call_stack) { std::string call_num = item.function_identifier.as_string(); std::cout << call_num << std::endl; } - log_status(" XXXXXXXXXXXXXXXXXXXXXXXX]"); } diff --git a/src/goto-symex/reachability_tree.cpp b/src/goto-symex/reachability_tree.cpp index ae36b4d4..4e3fb60b 100644 --- a/src/goto-symex/reachability_tree.cpp +++ b/src/goto-symex/reachability_tree.cpp @@ -563,7 +563,6 @@ goto_symext::symex_resultt reachability_treet::get_next_formula() (*cur_state_it)->add_memory_leak_checks(); has_complete_formula = false; - log_status("cur state symex result returned"); return get_cur_state().get_symex_result(); } diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index c5246094..53e33d31 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -136,8 +136,9 @@ void goto_symext::symex_assign( const bool hidden, const guardt &guard) { - log_status("xxxxxxxxxxxx symex assign: "); - code_assign->dump(); + log_debug("SLHV", "xxxxxxxxxxxxxxxxxxxxxx symex assign xxxxxxxxxxxxxxxxxxxxxx"); + if (messaget::state.modules.count("SLHV") > 0) + code_assign->dump(); const code_assign2t &code = to_code_assign2t(code_assign); expr2tc assign_target = code.target; @@ -213,19 +214,22 @@ void goto_symext::symex_assign( replace_nondet(rhs); intrinsic_races_check_dereference(lhs); - log_status("dereference lhs write"); + log_debug("SLHV", "dereference lhs write"); dereference(lhs, dereferencet::WRITE); - log_status("dereference rhs read"); + log_debug("SLHV", "dereference rhs read"); dereference(rhs, dereferencet::READ); - log_status("replace lhs"); + log_debug("SLHV", "replace lhs"); replace_dynamic_allocation(lhs); - log_status("replace rhs"); + log_debug("SLHV", "replace rhs"); replace_dynamic_allocation(rhs); - log_status("replace done"); + log_debug("SLHV", "replace done"); - log_status("after deref and replace -------------"); - lhs->dump(); - rhs->dump(); + log_debug("SLHV", "after deref and replace : lhs = rhs"); + if (messaget::state.modules.count("SLHV") > 0) + { + lhs->dump(); + rhs->dump(); + } // printf expression that has lhs if (is_code_printf2t(rhs)) @@ -236,16 +240,20 @@ void goto_symext::symex_assign( if (is_sideeffect2t(rhs)) { // check what symex_mem represent - - log_status("is side effect rhs::::::::::::::::: "); const sideeffect2t &effect = to_sideeffect2t(rhs); - effect.dump(); + + if (options.get_bool_option("z3-slhv") && + effect.kind != sideeffect2t::malloc) + { + log_error("Dot not support this type of sedeffect"); + abort(); + } + switch (effect.kind) { case sideeffect2t::cpp_new: case sideeffect2t::cpp_new_arr: - log_error("does not support va_arg cpp new"); - // symex_cpp_new(lhs, effect); + symex_cpp_new(lhs, effect); break; case sideeffect2t::realloc: symex_realloc(lhs, effect); @@ -257,13 +265,11 @@ void goto_symext::symex_assign( symex_alloca(lhs, effect); break; case sideeffect2t::va_arg: - log_error("does not support va_arg sideeffect"); - // symex_va_arg(lhs, effect); + symex_va_arg(lhs, effect); break; case sideeffect2t::printf2: // do nothing here break; - // No nondet side effect? default: assert(0 && "unexpected side effect"); } @@ -285,7 +291,8 @@ void goto_symext::symex_assign( guardt g(guard); // NOT the state guard! symex_assign_rec(lhs, original_lhs, rhs, expr2tc(), g, hidden_ssa); - log_status("xxxxxxxxxxxx symex assign: done for this step"); + + log_debug("SLHV", "xxxxxxxxxxxxxxxxxxxxxx symex assign xxxxxxxxxxxxxxxxxxxxxx"); } void goto_symext::symex_assign_rec( @@ -298,65 +305,53 @@ void goto_symext::symex_assign_rec( { if (is_symbol2t(lhs)) { - log_status("symex_assign_symbol"); + log_debug("SLHV", " xxxxxxxxx symex assign symbol xxxxxxxxx "); symex_assign_symbol(lhs, full_lhs, rhs, full_rhs, guard, hidden); - log_status("symex_assign_symbol done!!!"); - } + log_debug("SLHV", " xxxxxxxxx symex assign symbol xxxxxxxxx "); + } else if (is_index2t(lhs)) { - log_status("symex_assign_array"); symex_assign_array(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_member2t(lhs)) { - log_status("symex_assign_member"); symex_assign_member(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_if2t(lhs)) { - log_status("symex_assign_if"); symex_assign_if(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_typecast2t(lhs) || is_bitcast2t(lhs)) { - log_status("symex_assign_typecast"); symex_assign_typecast(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_constant_string2t(lhs) || is_null_object2t(lhs)) { - log_status("is_constant_string2t(lhs) || is_null_object2t(lhs)"); // ignore } else if (is_byte_extract2t(lhs)) { - log_status("symex_assign_byte_extract"); symex_assign_byte_extract(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_concat2t(lhs)) { - log_status("symex_assign_concat"); symex_assign_concat(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_constant_struct2t(lhs)) { - log_status("symex_assign_structure"); symex_assign_structure(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_extract2t(lhs)) { - log_status("symex_assign_extract"); symex_assign_extract(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_bitand2t(lhs)) { - log_status("symex_assign_bitfield"); symex_assign_bitfield(lhs, full_lhs, rhs, full_rhs, guard, hidden); } else if (is_field_of2t(lhs)) { - log_status("symex_assign_fieldof"); symex_assign_fieldof(lhs, full_lhs, rhs, full_rhs, guard, hidden); - log_status("symex_assign_fieldof done!!!"); } else { @@ -382,8 +377,8 @@ void goto_symext::symex_assign_symbol( cur_state->rename(rhs); do_simplify(rhs); - log_status("after rename rhs"); - rhs->dump(); + log_debug("SLHV", "after rename rhs"); + if(messaget::state.modules.count("SLHV") > 0) rhs->dump(); if (!is_nil_expr(full_rhs)) { @@ -1017,15 +1012,10 @@ void goto_symext::replace_typecast(expr2tc &expr) { const typecast2t &typecast = to_typecast2t(expr); - // Oly replace bool typecast + // Only replace bool typecast if ((is_pointer_type(typecast.from) || is_intloc_type(typecast.from)) && is_bool_type(typecast.type)) - { - log_status("replace typecast to bool"); - expr->dump(); - expr = notequal2tc(typecast.from, gen_nil()); - } } } diff --git a/src/goto-symex/symex_function.cpp b/src/goto-symex/symex_function.cpp index 7d810e91..3242cbab 100644 --- a/src/goto-symex/symex_function.cpp +++ b/src/goto-symex/symex_function.cpp @@ -202,6 +202,18 @@ void goto_symext::symex_function_call(const expr2tc &code) { const code_function_call2t &call = to_code_function_call2t(code); + if (options.get_bool_option("z3-slhv")) + { + const symbol2t &func = to_symbol2t(call.function); + if (has_prefix(func.get_symbol_name(), "c:@F@atexit") || + has_prefix(func.get_symbol_name(), "c:@F@memcpy") || + has_prefix(func.get_symbol_name(), "c:@F@memset")) + { + log_error("Do not support"); + abort(); + } + } + if (is_symbol2t(call.function)) symex_function_call_code(code); else @@ -527,7 +539,6 @@ bool goto_symext::run_next_function_ptr_target(bool first) void goto_symext::pop_frame() { - log_status(" pop frame"); assert(!cur_state->call_stack.empty()); statet::framet &frame = cur_state->top(); @@ -554,8 +565,6 @@ void goto_symext::pop_frame() type2tc ptr = pointer_type2tc(pointer_type2()); expr2tc l1_sym = symbol2tc(ptr, it.base_name); frame.level1.get_ident_name(l1_sym); - log_status(" clear local L1 variable:"); - l1_sym.get()->dump(); // Call free on alloca'd objects if ( it.base_name.as_string().find("return_value$_alloca") != diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp index 30ac5b1e..9686dde8 100644 --- a/src/goto-symex/symex_goto.cpp +++ b/src/goto-symex/symex_goto.cpp @@ -20,9 +20,6 @@ void goto_symext::symex_goto(const expr2tc &old_guard) cur_state->rename(new_guard); do_simplify(new_guard); - log_status("new guard"); - new_guard->dump(); - bool new_guard_false = (is_false(new_guard) || cur_state->guard.is_false()); bool new_guard_true = is_true(new_guard); diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index b868c88e..7f7c621c 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -142,11 +142,16 @@ goto_symext::symex_resultt goto_symext::get_symex_result() void goto_symext::symex_step(reachability_treet &art) { - log_status(" ======= goto_symext symex_step"); + log_debug( + "SLHV", + ">>>>>>>>>>>>>>>>>>>>>>>>>>>> SYMEX_STEP >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); assert(!cur_state->call_stack.empty()); const goto_programt::instructiont &instruction = *cur_state->source.pc; - instruction.dump(); + + if (messaget::state.modules.count("SLHV") > 0) + instruction.dump(); + // depth exceeded? { if (depth_limit != 0 && cur_state->num_instructions > depth_limit) @@ -163,20 +168,15 @@ void goto_symext::symex_step(reachability_treet &art) { case SKIP: case LOCATION: - log_status(" ======= goto symex: LOCATION"); // really ignore cur_state->source.pc++; break; case END_FUNCTION: - log_status(" ======= goto symex: END_FUNCTION"); - - this->cur_state->level2.print(std::cout); + log_debug("SLHV", " >>>>>>>> goto symex: END_FUNCTION"); symex_end_of_function(); - this->cur_state->level2.print(std::cout); - // Potentially skip to run another function ptr target; if not, // continue if (!run_next_function_ptr_target(false)) @@ -185,7 +185,7 @@ void goto_symext::symex_step(reachability_treet &art) break; case GOTO: { - log_status(" ======= goto symex: GOTO"); + log_debug("SLHV", " >>>>>>>> goto symex: GOTO"); expr2tc tmp(instruction.guard); if (options.get_bool_option("z3-slhv")) { @@ -195,7 +195,7 @@ void goto_symext::symex_step(reachability_treet &art) } replace_nondet(tmp); - tmp->dump(); + if (messaget::state.modules.count("SLHV") > 0) tmp->dump(); dereference(tmp, dereferencet::READ); replace_dynamic_allocation(tmp); @@ -205,19 +205,19 @@ void goto_symext::symex_step(reachability_treet &art) break; case ASSUME: - log_status(" ======= goto symex: ASSUME"); + log_debug("SLHV", " >>>>>>>> goto symex: ASSUME"); symex_assume(); cur_state->source.pc++; break; case ASSERT: - log_status(" ======= goto symex: ASSERT"); + log_debug("SLHV", " >>>>>>>> goto symex: ASSERT"); symex_assert(); cur_state->source.pc++; break; case RETURN: - log_status(" ======= goto symex: RETURN"); + log_debug("SLHV", " >>>>>>>> goto symex: RETURN"); if (!cur_state->guard.is_false()) { expr2tc thecode = instruction.code, assign; @@ -238,7 +238,7 @@ void goto_symext::symex_step(reachability_treet &art) break; case ASSIGN: - log_status(" ======= goto symex: ASSIGN"); + log_debug("SLHV", " >>>>>>>> goto symex: ASSIGN"); if (!cur_state->guard.is_false()) { code_assign2t deref_code = to_code_assign2t(instruction.code); // copy @@ -272,7 +272,7 @@ void goto_symext::symex_step(reachability_treet &art) case FUNCTION_CALL: { - log_status(" ======= goto symex: FUNCTION_CALL"); + log_debug("SLHV", " >>>>>>>> goto symex: FUNCTION_CALL"); expr2tc deref_code = instruction.code; replace_nondet(deref_code); @@ -338,34 +338,29 @@ void goto_symext::symex_step(reachability_treet &art) break; case DECL: - log_status(" ======= goto symex: DECL"); if (!cur_state->guard.is_false()) symex_decl(instruction.code); cur_state->source.pc++; break; case DEAD: - log_status(" ======= goto symex: DEAD"); if (!cur_state->guard.is_false()) symex_dead(instruction.code); cur_state->source.pc++; break; case OTHER: - log_status(" ======= goto symex: OTHER"); - log_status("guard - {}", !cur_state->guard.is_false()); + log_debug("SLHV", " >>>>>>>> goto symex: OTHER"); if (!cur_state->guard.is_false()) symex_other(instruction.code); cur_state->source.pc++; break; case CATCH: - log_status(" ======= goto symex: CATCH"); symex_catch(); break; case THROW: - log_status(" ======= goto symex: THROW"); if (!cur_state->guard.is_false()) { if (symex_throw()) @@ -378,13 +373,11 @@ void goto_symext::symex_step(reachability_treet &art) break; case THROW_DECL: - log_status(" ======= goto symex: THROW DECL"); symex_throw_decl(); cur_state->source.pc++; break; case THROW_DECL_END: - log_status(" ======= goto symex: THROW DECL END"); // When we reach THROW_DECL_END, we must clear any throw_decl if (stack_catch.size()) { @@ -404,7 +397,9 @@ void goto_symext::symex_step(reachability_treet &art) fmt::underlying(instruction.type)); abort(); } - log_status("finish this step"); + log_debug( + "SLHV", + "<<<<<<<<<<<<<<<<<<<<<<<<<<<< SYMEX_STEP <<<<<<<<<<<<<<<<<<<<<<<<<<<<"); } void goto_symext::symex_assume() @@ -1247,9 +1242,7 @@ void goto_symext::add_memory_leak_checks() "dereference failure: forgotten memory: " + get_pretty_name(it.name)); } } else { - log_status(" ----------- [memleak encoding]----------- "); for (auto const &it : dynamic_memory){ - log_status("allocated object {}: ", it.name); expr2tc deallocated = equality2tc(it.obj, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index 981b5801..62ebe8b9 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -14,8 +14,6 @@ void goto_symext::symex_other(const expr2tc code) replace_typecast(code2); } - code2->dump(); - if (is_code_expression2t(code2)) { // Represents an expression that gets evaluated, but does not have any @@ -55,9 +53,7 @@ void goto_symext::symex_other(const expr2tc code) void goto_symext::symex_decl(const expr2tc code) { - log_status("symex decl"); assert(is_code_decl2t(code)); - code->dump(); expr2tc code2 = code; if (options.get_bool_option("z3-slhv")) replace_null(code2); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 5c11e1c5..e922306b 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -161,8 +161,8 @@ void symex_target_equationt::convert_internal_step( return; } - // log_status(" ============================== step ======================== "); - // step.dump(); + log_debug("SLHV", " ============================== step ======================== "); + if (messaget::state.modules.count("SLHV") > 0) step.dump(); // guard_ast is used for generating witness // step.guard_ast = smt_conv.convert_ast(step.guard); @@ -231,7 +231,7 @@ void symex_target_equationt::convert_internal_step( // step.cond_ast->dump(); } - // log_status(" ============================== step ======================== "); + log_debug("SLHV", " ============================== step ======================== "); } void symex_target_equationt::output(std::ostream &out) const diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index 788034f0..fea8e4df 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -494,7 +494,7 @@ void disjh2t::do_disjh(const expr2tc &heap_term) { if (!is_intheap_type(heap_term)) { - log_status("Wrong object"); + log_error("Wrong object"); heap_term->dump(); abort(); } diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 94e55953..e3ff60f5 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -462,12 +462,15 @@ expr2tc dereferencet::dereference( modet mode, const expr2tc &lexical_offset) { - log_status("--------------- dereferencing pointer ---------"); - orig_src->dump(); - if (!is_nil_expr(lexical_offset)) + log_debug("SLHV", "------------ dereferencing pointer ------------"); + if (messaget::state.modules.count("SLHV") > 0) { - log_status("with lexical offset : "); - lexical_offset->dump(); + orig_src->dump(); + if (!is_nil_expr(lexical_offset)) + { + log_debug("SLHV", "with lexical offset : "); + lexical_offset->dump(); + } } internal_items.clear(); @@ -485,10 +488,11 @@ expr2tc dereferencet::dereference( // collect objects dest may point to value_setst::valuest points_to_set; - log_status("---- value set for "); - src->dump(); + log_debug("SLHV", "------- value set for : "); + if (messaget::state.modules.count("SLHV") > 0) + src->dump(); dereference_callback.get_value_set(src, points_to_set); - log_status("get value set done --------------------"); + log_debug("SLHV", "get value set done ---------------"); /* If the value-set contains unknown or invalid, we cannot be sure it contains * all possible values and we have to add a fallback symbol in case all guards @@ -641,11 +645,15 @@ expr2tc dereferencet::build_reference_to( const expr2tc &lexical_offset, expr2tc &pointer_guard) { - log_status(" =================== build reference to =================== "); - deref_expr->dump(); - log_status("|------------ points to -------------> "); - what->dump(); - log_status("--------------------"); + log_debug("SLHV", " =================== build reference to"); + if (messaget::state.modules.count("SLHV") > 0) + { + log_debug("SLHV", "|------------------------------------|"); + deref_expr->dump(); + log_debug("SLHV", "|------------ points to ------------->"); + what->dump(); + log_debug("SLHV", "|------------------------------------|"); + } expr2tc value; pointer_guard = gen_false_expr(); @@ -702,8 +710,6 @@ expr2tc dereferencet::build_reference_to( type2tc ptr_type = pointer_type2tc(object->type); expr2tc obj_ptr = address_of2tc(ptr_type, object); pointer_guard = same_object2tc(deref_expr, obj_ptr); - log_status("generated pointer guard:"); - pointer_guard->dump(); guardt tmp_guard(guard); tmp_guard.add(pointer_guard); @@ -802,7 +808,8 @@ expr2tc dereferencet::build_reference_to( } else { value = object; - if (!is_nil_expr(lexical_offset)) + if (messaget::state.modules.count("SLHV") > 0 && + !is_nil_expr(lexical_offset)) lexical_offset->dump(); guardt tmp_guard(guard); @@ -1027,9 +1034,6 @@ void dereferencet::build_reference_rec( modet mode, unsigned long alignment) { - log_status("build reference rec: "); - log_status("to type: "); - type->dump(); int flags = 0; if (is_constant_int2t(offset)) flags |= flag_is_const_offs; @@ -1210,11 +1214,9 @@ void dereferencet::build_deref_slhv( modet mode, unsigned long alignment) { - log_status(" ----------------- build deref slhv ----------------- "); - value->dump(); - // guard.dump(); - // offset->dump(); - // type->dump(); + log_debug("SLHV", " ----------------- build deref slhv -----------------"); + if (messaget::state.modules.count("SLHV") > 0) + value->dump(); if (!is_scalar_type(type)) { @@ -1261,10 +1263,11 @@ void dereferencet::build_deref_slhv( // pointer - return itself } - log_status("return dereference ---> {}", !is_nil_expr(value)); - if (!is_nil_expr(value)) value->dump(); - - log_status(" ----------------- build deref slhv ----------------- "); + log_debug("SLHV", "return dereference ---> {}", !is_nil_expr(value)); + if (messaget::state.modules.count("SLHV") > 0 && + !is_nil_expr(value)) + value->dump(); + log_debug("SLHV", " ----------------- build deref slhv ----------------- "); } void dereferencet::construct_from_array( @@ -2480,7 +2483,6 @@ void dereferencet::check_data_obj_access( const guardt &guard, modet mode) { - log_status("check data obj access"); assert(!is_array_type(value)); assert(offset->type == bitsize_type2()); @@ -2510,7 +2512,6 @@ void dereferencet::check_data_obj_access( * check that the access being made is aligned. */ if (is_scalar_type(type) && !mode.unaligned) check_alignment(access_sz, std::move(offset), guard); - log_status("check data obj access over"); } void dereferencet::check_heap_region_access( diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 92d56bca..29d53b28 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -214,7 +214,6 @@ void value_sett::get_value_set_rec( { if (is_unknown2t(expr) || is_invalid2t(expr)) { - log_status("is unknown expr or invalid expr"); // Unknown / invalid exprs mean we just point at something unknown (and // potentially invalid). insert(dest, unknown2tc(original_type), BigInt(0)); @@ -299,7 +298,6 @@ void value_sett::get_value_set_rec( // of things it refers to, rather than the value set (of things it points // to). const address_of2t &addrof = to_address_of2t(expr); - log_status("get address of reference set"); get_reference_set(addrof.ptr_obj, dest); return; } @@ -359,7 +357,6 @@ void value_sett::get_value_set_rec( if (is_typecast2t(expr)) { - log_status("get typecast value set"); // Push straight through typecasts. const typecast2t &cast = to_typecast2t(expr); get_value_set_rec(cast.from, dest, suffix, original_type); @@ -517,7 +514,6 @@ void value_sett::get_value_set_rec( if (is_symbol2t(expr)) { - log_status("get value for symbol"); // This is a symbol, and if it's a pointer then this expression might // evalutate to what it points at. So, return this symbols value set. const symbol2t &sym = to_symbol2t(expr); @@ -538,7 +534,7 @@ void value_sett::get_value_set_rec( // Look up this symbol, with the given suffix to distinguish any arrays or // members we've picked out of it at a higher level. valuest::const_iterator v_it = values.find(sym.get_symbol_name() + suffix); - log_status("ssssss symbol lookup name: {}", sym.get_symbol_name() + suffix); + log_debug("SLHV", "-------------> symbol lookup name: {}", sym.get_symbol_name() + suffix); if (sym.rlevel == symbol2t::renaming_level::level1_global) assert(sym.level1_num == 0); @@ -555,17 +551,20 @@ void value_sett::get_value_set_rec( if (v_it != values.end()) { make_union(dest, v_it->second.object_map); - log_status("points to somthing"); - int i = 0; - for (auto obj : dest) + log_debug("SLHV", "points to somthing"); + if (messaget::state.modules.count("SLHV") > 0) { - log_status("item - {} : ", i++); - object_numbering[obj.first]->dump(); + int i = 0; + for (auto obj : dest) + { + log_debug("SLHV", "item - {} : ", i++); + object_numbering[obj.first]->dump(); + } } return; } else - log_status("nothing"); + log_debug("SLHV", "nothing"); } // SLHV: @@ -575,7 +574,7 @@ void value_sett::get_value_set_rec( is_heap_region2t(expr) || is_constant_intheap2t(expr) || is_heap_append2t(expr) || is_heap_delete2t(expr)) { - log_status("do not support get_value_set_rec"); + log_error("Do not support get_value_set_rec"); expr->dump(); abort(); } @@ -904,7 +903,6 @@ void value_sett::get_reference_set_rec(const expr2tc &expr, object_mapt &dest) if (is_symbol2t(expr)) { const symbolt *sym = ns.lookup(to_symbol2t(expr).thename); - log_status("get reference set rec is_symbol: {}", to_symbol2t(expr).thename); assert(sym); const irept &a = sym->type.find("alignment"); if (a.is_not_nil()) @@ -933,7 +931,6 @@ void value_sett::get_reference_set_rec(const expr2tc &expr, object_mapt &dest) if (is_index2t(expr)) { - log_status("get reference set is_index"); // This index may be dereferencing a pointer. So, get the reference set of // the source value, and store a reference to all those things. const index2t &index = to_index2t(expr); @@ -969,8 +966,6 @@ void value_sett::get_reference_set_rec(const expr2tc &expr, object_mapt &dest) for (const auto &a_it : array_references) { expr2tc object = object_numbering[a_it.first]; - log_status("print object"); - object->dump(); if (is_unknown2t(object)) { diff --git a/src/solvers/smt/smt_conv.cpp b/src/solvers/smt/smt_conv.cpp index ce4a503b..5f0b4fbd 100644 --- a/src/solvers/smt/smt_conv.cpp +++ b/src/solvers/smt/smt_conv.cpp @@ -239,9 +239,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) { smt_cachet::const_iterator cache_result = smt_cache.find(expr); if (cache_result != smt_cache.end()) - return cache_result->ast; - - bool use_old_encoding = !options.get_bool_option("z3-slhv"); + return (cache_result->ast); /* Vectors! * @@ -253,7 +251,7 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) * for some reason we would like to run ESBMC without simplifications * then we need to apply it here. */ - if (use_old_encoding && is_vector_type(expr)) + if (is_vector_type(expr)) { if (is_neg2t(expr)) { @@ -289,997 +287,958 @@ smt_astt smt_convt::convert_ast(const expr2tc &expr) switch (expr->expr_id) { - case expr2t::with_id: - case expr2t::constant_array_id: - case expr2t::constant_vector_id: - case expr2t::constant_array_of_id: - case expr2t::constant_intloc_id: - case expr2t::constant_intheap_id: - case expr2t::index_id: - case expr2t::address_of_id: - case expr2t::ieee_add_id: - case expr2t::ieee_sub_id: - case expr2t::ieee_mul_id: - case expr2t::ieee_div_id: - case expr2t::ieee_fma_id: - case expr2t::ieee_sqrt_id: - case expr2t::pointer_offset_id: - case expr2t::pointer_object_id: - case expr2t::pointer_capability_id: - - case expr2t::location_of_id: - case expr2t::field_of_id: - case expr2t::heap_region_id: - case expr2t::heap_update_id: - case expr2t::heap_delete_id: - break; // Don't convert their operands - - default: - { - if (is_same_object2t(expr) && !use_old_encoding) break; - - // Convert all the arguments and store them in 'args'. - unsigned int i = 0; - expr->foreach_operand( - [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); - } - } - - smt_astt a; + case expr2t::with_id: + case expr2t::constant_array_id: + case expr2t::constant_vector_id: + case expr2t::constant_array_of_id: + case expr2t::index_id: + case expr2t::address_of_id: + case expr2t::ieee_add_id: + case expr2t::ieee_sub_id: + case expr2t::ieee_mul_id: + case expr2t::ieee_div_id: + case expr2t::ieee_fma_id: + case expr2t::ieee_sqrt_id: + case expr2t::pointer_offset_id: + case expr2t::pointer_object_id: + case expr2t::pointer_capability_id: + break; // Don't convert their operands + + default: + { + // Convert all the arguments and store them in 'args'. + unsigned int i = 0; + expr->foreach_operand( + [this, &args, &i](const expr2tc &e) { args[i++] = convert_ast(e); }); + } + } + smt_astt a; switch (expr->expr_id) { - case expr2t::constant_intheap_id: - case expr2t::constant_intloc_id: - case expr2t::heap_region_id: - case expr2t::location_of_id: - case expr2t::field_of_id: - case expr2t::points_to_id: - case expr2t::uplus_id: - case expr2t::locadd_id: - case expr2t::heap_update_id: - case expr2t::heap_contain_id: - case expr2t::heap_append_id: - case expr2t::heap_delete_id: - { - a = convert_slhv_opts(expr, args); - break; + case expr2t::constant_int_id: + case expr2t::constant_fixedbv_id: + case expr2t::constant_floatbv_id: + case expr2t::constant_bool_id: + case expr2t::symbol_id: + { + a = convert_terminal(expr); + break; + } + case expr2t::constant_string_id: + { + const constant_string2t &str = to_constant_string2t(expr); + expr2tc newarr = str.to_array(); + a = convert_ast(newarr); + break; + } + case expr2t::constant_struct_id: + { + a = tuple_api->tuple_create(expr); + break; + } + case expr2t::constant_union_id: + { + // Get size + const constant_union2t &cu = to_constant_union2t(expr); + const std::vector &dt_memb = cu.datatype_members; + expr2tc src_expr = + dt_memb.empty() ? gen_zero(get_uint_type(0)) : dt_memb[0]; +#ifndef NDEBUG + if (!cu.init_field.empty()) + { + const union_type2t &ut = to_union_type(expr->type); + unsigned c = ut.get_component_number(cu.init_field); + /* Can only initialize unions by expressions of same type as init_field */ + assert(src_expr->type->type_id == ut.members[c]->type_id); } - - case expr2t::constant_int_id: - case expr2t::constant_fixedbv_id: - case expr2t::constant_floatbv_id: - case expr2t::constant_bool_id: - case expr2t::symbol_id: +#endif + a = convert_ast(typecast2tc( + get_uint_type(type_byte_size_bits(expr->type).to_uint64()), + bitcast2tc( + get_uint_type(type_byte_size_bits(src_expr->type).to_uint64()), + src_expr))); + break; + } + case expr2t::constant_vector_id: + { + a = array_create(expr); + break; + } + case expr2t::constant_array_id: + case expr2t::constant_array_of_id: + { + const array_type2t &arr = to_array_type(expr->type); + if (!array_api->can_init_infinite_arrays && arr.size_is_infinite) { - a = convert_terminal(expr); + smt_sortt sort = convert_sort(expr->type); + + // Don't honour inifinite sized array initializers. Modelling only. + // If we have an array of tuples and no tuple support, use tuple_fresh. + // Otherwise, mk_fresh. + if (is_tuple_ast_type(arr.subtype)) + a = tuple_api->tuple_fresh(sort); + else + a = mk_fresh( + sort, + "inf_array", + convert_sort(get_flattened_array_subtype(expr->type))); break; } - case expr2t::constant_string_id: + + expr2tc flat_expr = expr; + if ( + is_array_type(get_array_subtype(expr->type)) && is_constant_array2t(expr)) + flat_expr = flatten_array_body(expr); + + if (is_struct_type(arr.subtype) || is_pointer_type(arr.subtype)) { - const constant_string2t &str = to_constant_string2t(expr); - expr2tc newarr = str.to_array(); - a = convert_ast(newarr); - break; + // Domain sort may be mesed with: + smt_sortt domain = mk_int_bv_sort( + int_encoding ? config.ansi_c.int_width + : calculate_array_domain_width(arr)); + + a = tuple_array_create_despatch(flat_expr, domain); } - case expr2t::constant_struct_id: + else + a = array_create(flat_expr); + break; + } + case expr2t::add_id: + { + const add2t &add = to_add2t(expr); + if ( + is_pointer_type(expr->type) || is_pointer_type(add.side_1) || + is_pointer_type(add.side_2)) { - a = tuple_api->tuple_create(expr); - break; + a = convert_pointer_arith(expr, expr->type); } - case expr2t::constant_union_id: + else if (int_encoding) { - // Get size - const constant_union2t &cu = to_constant_union2t(expr); - const std::vector &dt_memb = cu.datatype_members; - expr2tc src_expr = - dt_memb.empty() ? gen_zero(get_uint_type(0)) : dt_memb[0]; - #ifndef NDEBUG - if (!cu.init_field.empty()) - { - const union_type2t &ut = to_union_type(expr->type); - unsigned c = ut.get_component_number(cu.init_field); - /* Can only initialize unions by expressions of same type as init_field */ - assert(src_expr->type->type_id == ut.members[c]->type_id); - } - #endif - a = convert_ast(typecast2tc( - get_uint_type(type_byte_size_bits(expr->type).to_uint64()), - bitcast2tc( - get_uint_type(type_byte_size_bits(src_expr->type).to_uint64()), - src_expr))); - break; + a = mk_add(args[0], args[1]); } - case expr2t::constant_vector_id: + else { - a = array_create(expr); - break; + a = mk_bvadd(args[0], args[1]); } - case expr2t::constant_array_id: - case expr2t::constant_array_of_id: + break; + } + case expr2t::sub_id: + { + const sub2t &sub = to_sub2t(expr); + if ( + is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || + is_pointer_type(sub.side_2)) { - const array_type2t &arr = to_array_type(expr->type); - if (!array_api->can_init_infinite_arrays && arr.size_is_infinite) - { - smt_sortt sort = convert_sort(expr->type); - - // Don't honour inifinite sized array initializers. Modelling only. - // If we have an array of tuples and no tuple support, use tuple_fresh. - // Otherwise, mk_fresh. - if (is_tuple_ast_type(arr.subtype)) - a = tuple_api->tuple_fresh(sort); - else - a = mk_fresh( - sort, - "inf_array", - convert_sort(get_flattened_array_subtype(expr->type))); - break; - } - - expr2tc flat_expr = expr; - if ( - is_array_type(get_array_subtype(expr->type)) && is_constant_array2t(expr)) - flat_expr = flatten_array_body(expr); - - if (is_struct_type(arr.subtype) || is_pointer_type(arr.subtype)) - { - // Domain sort may be mesed with: - smt_sortt domain = mk_int_bv_sort( - int_encoding ? config.ansi_c.int_width - : calculate_array_domain_width(arr)); - - a = tuple_array_create_despatch(flat_expr, domain); - } - else - a = array_create(flat_expr); - break; + a = convert_pointer_arith(expr, expr->type); } - case expr2t::add_id: + else if (int_encoding) { - const add2t &add = to_add2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(add.side_1) || - is_pointer_type(add.side_2)) - { - a = !use_old_encoding ? - convert_slhv_opts(expr, args) : - convert_pointer_arith(expr, expr->type); - } - else if (int_encoding) - { - a = mk_add(args[0], args[1]); - } - else - { - a = mk_bvadd(args[0], args[1]); - } - break; + a = mk_sub(args[0], args[1]); } - case expr2t::sub_id: + else { - const sub2t &sub = to_sub2t(expr); - if ( - is_pointer_type(expr->type) || is_pointer_type(sub.side_1) || - is_pointer_type(sub.side_2)) - { - a = !use_old_encoding ? - convert_slhv_opts(expr, args) : - convert_pointer_arith(expr, expr->type); - } - else if (int_encoding) - { - a = mk_sub(args[0], args[1]); - } - else - { - a = mk_bvsub(args[0], args[1]); - } - break; + a = mk_bvsub(args[0], args[1]); } - case expr2t::mul_id: + break; + } + case expr2t::mul_id: + { + // Fixedbvs are handled separately + if (is_fixedbv_type(expr) && !int_encoding) { - // Fixedbvs are handled separately - if (is_fixedbv_type(expr) && !int_encoding) - { - auto mul = to_mul2t(expr); - auto fbvt = to_fixedbv_type(mul.type); + auto mul = to_mul2t(expr); + auto fbvt = to_fixedbv_type(mul.type); - unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; + unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; - args[0] = mk_sign_ext(convert_ast(mul.side_1), fraction_bits); - args[1] = mk_sign_ext(convert_ast(mul.side_2), fraction_bits); + args[0] = mk_sign_ext(convert_ast(mul.side_1), fraction_bits); + args[1] = mk_sign_ext(convert_ast(mul.side_2), fraction_bits); - a = mk_bvmul(args[0], args[1]); - a = mk_extract(a, fbvt.width + fraction_bits - 1, fraction_bits); - } - else if (int_encoding) - { - a = mk_mul(args[0], args[1]); - } - else - { - a = mk_bvmul(args[0], args[1]); - } - break; + a = mk_bvmul(args[0], args[1]); + a = mk_extract(a, fbvt.width + fraction_bits - 1, fraction_bits); + } + else if (int_encoding) + { + a = mk_mul(args[0], args[1]); } - case expr2t::div_id: + else { - auto d = to_div2t(expr); + a = mk_bvmul(args[0], args[1]); + } + break; + } + case expr2t::div_id: + { + auto d = to_div2t(expr); - // Fixedbvs are handled separately - if (is_fixedbv_type(expr) && !int_encoding) - { - auto fbvt = to_fixedbv_type(d.type); + // Fixedbvs are handled separately + if (is_fixedbv_type(expr) && !int_encoding) + { + auto fbvt = to_fixedbv_type(d.type); - unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; + unsigned int fraction_bits = fbvt.width - fbvt.integer_bits; - args[1] = mk_sign_ext(convert_ast(d.side_2), fraction_bits); + args[1] = mk_sign_ext(convert_ast(d.side_2), fraction_bits); - smt_astt zero = mk_smt_bv(BigInt(0), fraction_bits); - smt_astt op0 = convert_ast(d.side_1); + smt_astt zero = mk_smt_bv(BigInt(0), fraction_bits); + smt_astt op0 = convert_ast(d.side_1); - args[0] = mk_concat(op0, zero); + args[0] = mk_concat(op0, zero); - // Sorts. - a = mk_bvsdiv(args[0], args[1]); - a = mk_extract(a, fbvt.width - 1, 0); - } - else if (int_encoding) - { - a = mk_div(args[0], args[1]); - } - else if (is_unsignedbv_type(d.side_1) && is_unsignedbv_type(d.side_2)) - { - a = mk_bvudiv(args[0], args[1]); - } - else - { - assert(is_signedbv_type(d.side_1) && is_signedbv_type(d.side_2)); - a = mk_bvsdiv(args[0], args[1]); - } - break; + // Sorts. + a = mk_bvsdiv(args[0], args[1]); + a = mk_extract(a, fbvt.width - 1, 0); } - case expr2t::ieee_add_id: + else if (int_encoding) { - if (int_encoding) - { - a = mk_add( - convert_ast(to_ieee_add2t(expr).side_1), - convert_ast(to_ieee_add2t(expr).side_2)); - } - else - { - assert(is_floatbv_type(expr)); - a = fp_api->mk_smt_fpbv_add( - convert_ast(to_ieee_add2t(expr).side_1), - convert_ast(to_ieee_add2t(expr).side_2), - convert_rounding_mode(to_ieee_add2t(expr).rounding_mode)); - } - break; + a = mk_div(args[0], args[1]); } - case expr2t::ieee_sub_id: + else if (is_unsignedbv_type(d.side_1) && is_unsignedbv_type(d.side_2)) { - assert(is_floatbv_type(expr)); - if (int_encoding) - { - a = mk_sub( - convert_ast(to_ieee_sub2t(expr).side_1), - convert_ast(to_ieee_sub2t(expr).side_2)); - } - else - { - a = fp_api->mk_smt_fpbv_sub( - convert_ast(to_ieee_sub2t(expr).side_1), - convert_ast(to_ieee_sub2t(expr).side_2), - convert_rounding_mode(to_ieee_sub2t(expr).rounding_mode)); - } - break; + a = mk_bvudiv(args[0], args[1]); } - case expr2t::ieee_mul_id: + else { - assert(is_floatbv_type(expr)); - if (int_encoding) - { - a = mk_mul( - convert_ast(to_ieee_mul2t(expr).side_1), - convert_ast(to_ieee_mul2t(expr).side_2)); - } - else - { - a = fp_api->mk_smt_fpbv_mul( - convert_ast(to_ieee_mul2t(expr).side_1), - convert_ast(to_ieee_mul2t(expr).side_2), - convert_rounding_mode(to_ieee_mul2t(expr).rounding_mode)); - } - break; + assert(is_signedbv_type(d.side_1) && is_signedbv_type(d.side_2)); + a = mk_bvsdiv(args[0], args[1]); } - case expr2t::ieee_div_id: + break; + } + case expr2t::ieee_add_id: + { + if (int_encoding) { - assert(is_floatbv_type(expr)); - if (int_encoding) - { - a = mk_div( - convert_ast(to_ieee_div2t(expr).side_1), - convert_ast(to_ieee_div2t(expr).side_2)); - } - else - { - a = fp_api->mk_smt_fpbv_div( - convert_ast(to_ieee_div2t(expr).side_1), - convert_ast(to_ieee_div2t(expr).side_2), - convert_rounding_mode(to_ieee_div2t(expr).rounding_mode)); - } - break; + a = mk_add( + convert_ast(to_ieee_add2t(expr).side_1), + convert_ast(to_ieee_add2t(expr).side_2)); } - case expr2t::ieee_fma_id: + else { assert(is_floatbv_type(expr)); - if (int_encoding) - { - a = mk_add( - mk_mul( - convert_ast(to_ieee_fma2t(expr).value_1), - convert_ast(to_ieee_fma2t(expr).value_2)), - convert_ast(to_ieee_fma2t(expr).value_3)); - } - else - { - a = fp_api->mk_smt_fpbv_fma( - convert_ast(to_ieee_fma2t(expr).value_1), - convert_ast(to_ieee_fma2t(expr).value_2), - convert_ast(to_ieee_fma2t(expr).value_3), - convert_rounding_mode(to_ieee_fma2t(expr).rounding_mode)); - } - break; + a = fp_api->mk_smt_fpbv_add( + convert_ast(to_ieee_add2t(expr).side_1), + convert_ast(to_ieee_add2t(expr).side_2), + convert_rounding_mode(to_ieee_add2t(expr).rounding_mode)); } - case expr2t::ieee_sqrt_id: + break; + } + case expr2t::ieee_sub_id: + { + assert(is_floatbv_type(expr)); + if (int_encoding) { - assert(is_floatbv_type(expr)); - // TODO: no integer mode implementation - a = fp_api->mk_smt_fpbv_sqrt( - convert_ast(to_ieee_sqrt2t(expr).value), - convert_rounding_mode(to_ieee_sqrt2t(expr).rounding_mode)); - break; + a = mk_sub( + convert_ast(to_ieee_sub2t(expr).side_1), + convert_ast(to_ieee_sub2t(expr).side_2)); } - case expr2t::modulus_id: + else { - auto m = to_modulus2t(expr); - - if (int_encoding) - { - a = mk_mod(args[0], args[1]); - } - else if (is_fixedbv_type(m.side_1) && is_fixedbv_type(m.side_2)) - { - a = mk_bvsmod(args[0], args[1]); - } - else if (is_unsignedbv_type(m.side_1) && is_unsignedbv_type(m.side_2)) - { - a = mk_bvumod(args[0], args[1]); - } - else - { - assert(is_signedbv_type(m.side_1) || is_signedbv_type(m.side_2)); - a = mk_bvsmod(args[0], args[1]); - } - break; + a = fp_api->mk_smt_fpbv_sub( + convert_ast(to_ieee_sub2t(expr).side_1), + convert_ast(to_ieee_sub2t(expr).side_2), + convert_rounding_mode(to_ieee_sub2t(expr).rounding_mode)); } - case expr2t::index_id: + break; + } + case expr2t::ieee_mul_id: + { + assert(is_floatbv_type(expr)); + if (int_encoding) { - a = convert_array_index(expr); - break; + a = mk_mul( + convert_ast(to_ieee_mul2t(expr).side_1), + convert_ast(to_ieee_mul2t(expr).side_2)); } - case expr2t::with_id: + else { - const with2t &with = to_with2t(expr); - - // We reach here if we're with'ing a struct, not an array. Or a bool. - if (is_struct_type(expr) || is_pointer_type(expr)) - { - unsigned int idx = get_member_name_field(expr->type, with.update_field); - smt_astt srcval = convert_ast(with.source_value); - - #ifndef NDEBUG - const struct_union_data &data = get_type_def(with.type); - assert(idx < data.members.size() && "Out of bounds with expression"); - // Base type eq examines pointer types to closely - assert( - (base_type_eq(data.members[idx], with.update_value->type, ns) || - (is_pointer_type(data.members[idx]) && - is_pointer_type(with.update_value))) && - "Assigned tuple member has type mismatch"); - #endif - - a = srcval->update(this, convert_ast(with.update_value), idx); - } - else if (is_union_type(expr)) - { - uint64_t bits = type_byte_size_bits(expr->type).to_uint64(); - const union_type2t &tu = to_union_type(expr->type); - assert(is_constant_string2t(with.update_field)); - unsigned c = - tu.get_component_number(to_constant_string2t(with.update_field).value); - uint64_t mem_bits = type_byte_size_bits(tu.members[c]).to_uint64(); - expr2tc upd = bitcast2tc( - get_uint_type(mem_bits), typecast2tc(tu.members[c], with.update_value)); - if (mem_bits < bits) - upd = concat2tc( - get_uint_type(bits), - extract2tc( - get_uint_type(bits - mem_bits), - with.source_value, - bits - 1, - mem_bits), - upd); - a = convert_ast(upd); - } - else - { - a = convert_array_store(expr); - } - break; + a = fp_api->mk_smt_fpbv_mul( + convert_ast(to_ieee_mul2t(expr).side_1), + convert_ast(to_ieee_mul2t(expr).side_2), + convert_rounding_mode(to_ieee_mul2t(expr).rounding_mode)); } - case expr2t::member_id: + break; + } + case expr2t::ieee_div_id: + { + assert(is_floatbv_type(expr)); + if (int_encoding) { - a = convert_member(expr); - break; + a = mk_div( + convert_ast(to_ieee_div2t(expr).side_1), + convert_ast(to_ieee_div2t(expr).side_2)); } - case expr2t::same_object_id: + else { - const same_object2t& so = to_same_object2t(expr); - // Two projects, then comparison. - if (use_old_encoding) { - args[0] = args[0]->project(this, 0); - args[1] = args[1]->project(this, 0); - a = mk_eq(args[0], args[1]); - } else { - a = convert_slhv_opts(expr, args); - } - break; + a = fp_api->mk_smt_fpbv_div( + convert_ast(to_ieee_div2t(expr).side_1), + convert_ast(to_ieee_div2t(expr).side_2), + convert_rounding_mode(to_ieee_div2t(expr).rounding_mode)); } - case expr2t::pointer_offset_id: + break; + } + case expr2t::ieee_fma_id: + { + assert(is_floatbv_type(expr)); + if (int_encoding) { - const pointer_offset2t &obj = to_pointer_offset2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type(*ptr)) - ptr = &to_typecast2t(*ptr).from; - - args[0] = convert_ast(*ptr); - a = !use_old_encoding ? args[0] : args[0]->project(this, 0); - break; + a = mk_add( + mk_mul( + convert_ast(to_ieee_fma2t(expr).value_1), + convert_ast(to_ieee_fma2t(expr).value_2)), + convert_ast(to_ieee_fma2t(expr).value_3)); } - case expr2t::pointer_object_id: + else { - const pointer_object2t &obj = to_pointer_object2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) - ptr = &to_typecast2t(*ptr).from; - - args[0] = convert_ast(*ptr); - a = !use_old_encoding ? args[0] : args[0]->project(this, 0); - break; + a = fp_api->mk_smt_fpbv_fma( + convert_ast(to_ieee_fma2t(expr).value_1), + convert_ast(to_ieee_fma2t(expr).value_2), + convert_ast(to_ieee_fma2t(expr).value_3), + convert_rounding_mode(to_ieee_fma2t(expr).rounding_mode)); } - case expr2t::pointer_capability_id: - { - assert(config.ansi_c.cheri); - const pointer_capability2t &obj = to_pointer_capability2t(expr); - // Potentially walk through some typecasts - const expr2tc *ptr = &obj.ptr_obj; - while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) - ptr = &to_typecast2t(*ptr).from; + break; + } + case expr2t::ieee_sqrt_id: + { + assert(is_floatbv_type(expr)); + // TODO: no integer mode implementation + a = fp_api->mk_smt_fpbv_sqrt( + convert_ast(to_ieee_sqrt2t(expr).value), + convert_rounding_mode(to_ieee_sqrt2t(expr).rounding_mode)); + break; + } + case expr2t::modulus_id: + { + auto m = to_modulus2t(expr); - args[0] = convert_ast(*ptr); - a = args[0]->project(this, 2); - break; - } - case expr2t::typecast_id: - { - a = convert_typecast(expr); - break; - } - case expr2t::nearbyint_id: - { - assert(is_floatbv_type(expr)); - a = fp_api->mk_smt_nearbyint_from_float( - convert_ast(to_nearbyint2t(expr).from), - convert_rounding_mode(to_nearbyint2t(expr).rounding_mode)); - break; - } - case expr2t::if_id: - { - // Only attempt to handle struct.s - const if2t &if_ref = to_if2t(expr); - args[0] = convert_ast(if_ref.cond); - args[1] = convert_ast(if_ref.true_value); - args[2] = convert_ast(if_ref.false_value); - a = args[1]->ite(this, args[0], args[2]); - break; - } - case expr2t::isnan_id: - { - a = convert_is_nan(expr); - break; - } - case expr2t::isinf_id: - { - a = convert_is_inf(expr); - break; - } - case expr2t::isnormal_id: - { - a = convert_is_normal(expr); - break; - } - case expr2t::isfinite_id: + if (int_encoding) { - a = convert_is_finite(expr); - break; + a = mk_mod(args[0], args[1]); } - case expr2t::signbit_id: + else if (is_fixedbv_type(m.side_1) && is_fixedbv_type(m.side_2)) { - a = convert_signbit(expr); - break; + a = mk_bvsmod(args[0], args[1]); } - case expr2t::popcount_id: + else if (is_unsignedbv_type(m.side_1) && is_unsignedbv_type(m.side_2)) { - a = convert_popcount(expr); - break; + a = mk_bvumod(args[0], args[1]); } - case expr2t::bswap_id: + else { - a = convert_bswap(expr); - break; + assert(is_signedbv_type(m.side_1) || is_signedbv_type(m.side_2)); + a = mk_bvsmod(args[0], args[1]); } - case expr2t::overflow_id: + break; + } + case expr2t::index_id: + { + a = convert_array_index(expr); + break; + } + case expr2t::with_id: + { + const with2t &with = to_with2t(expr); + + // We reach here if we're with'ing a struct, not an array. Or a bool. + if (is_struct_type(expr) || is_pointer_type(expr)) { - a = overflow_arith(expr); - break; + unsigned int idx = get_member_name_field(expr->type, with.update_field); + smt_astt srcval = convert_ast(with.source_value); + +#ifndef NDEBUG + const struct_union_data &data = get_type_def(with.type); + assert(idx < data.members.size() && "Out of bounds with expression"); + // Base type eq examines pointer types to closely + assert( + (base_type_eq(data.members[idx], with.update_value->type, ns) || + (is_pointer_type(data.members[idx]) && + is_pointer_type(with.update_value))) && + "Assigned tuple member has type mismatch"); +#endif + + a = srcval->update(this, convert_ast(with.update_value), idx); + } + else if (is_union_type(expr)) + { + uint64_t bits = type_byte_size_bits(expr->type).to_uint64(); + const union_type2t &tu = to_union_type(expr->type); + assert(is_constant_string2t(with.update_field)); + unsigned c = + tu.get_component_number(to_constant_string2t(with.update_field).value); + uint64_t mem_bits = type_byte_size_bits(tu.members[c]).to_uint64(); + expr2tc upd = bitcast2tc( + get_uint_type(mem_bits), typecast2tc(tu.members[c], with.update_value)); + if (mem_bits < bits) + upd = concat2tc( + get_uint_type(bits), + extract2tc( + get_uint_type(bits - mem_bits), + with.source_value, + bits - 1, + mem_bits), + upd); + a = convert_ast(upd); } - case expr2t::overflow_cast_id: + else { - a = overflow_cast(expr); - break; + a = convert_array_store(expr); } - case expr2t::overflow_neg_id: - { - a = overflow_neg(expr); - break; + break; + } + case expr2t::member_id: + { + a = convert_member(expr); + break; + } + case expr2t::same_object_id: + { + // Two projects, then comparison. + args[0] = args[0]->project(this, 0); + args[1] = args[1]->project(this, 0); + a = mk_eq(args[0], args[1]); + break; + } + case expr2t::pointer_offset_id: + { + const pointer_offset2t &obj = to_pointer_offset2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type(*ptr)) + ptr = &to_typecast2t(*ptr).from; + + args[0] = convert_ast(*ptr); + a = args[0]->project(this, 1); + break; + } + case expr2t::pointer_object_id: + { + const pointer_object2t &obj = to_pointer_object2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) + ptr = &to_typecast2t(*ptr).from; + + args[0] = convert_ast(*ptr); + a = args[0]->project(this, 0); + break; + } + case expr2t::pointer_capability_id: + { + assert(config.ansi_c.cheri); + const pointer_capability2t &obj = to_pointer_capability2t(expr); + // Potentially walk through some typecasts + const expr2tc *ptr = &obj.ptr_obj; + while (is_typecast2t(*ptr) && !is_pointer_type((*ptr))) + ptr = &to_typecast2t(*ptr).from; + + args[0] = convert_ast(*ptr); + a = args[0]->project(this, 2); + break; + } + case expr2t::typecast_id: + { + a = convert_typecast(expr); + break; + } + case expr2t::nearbyint_id: + { + assert(is_floatbv_type(expr)); + a = fp_api->mk_smt_nearbyint_from_float( + convert_ast(to_nearbyint2t(expr).from), + convert_rounding_mode(to_nearbyint2t(expr).rounding_mode)); + break; + } + case expr2t::if_id: + { + // Only attempt to handle struct.s + const if2t &if_ref = to_if2t(expr); + args[0] = convert_ast(if_ref.cond); + args[1] = convert_ast(if_ref.true_value); + args[2] = convert_ast(if_ref.false_value); + a = args[1]->ite(this, args[0], args[2]); + break; + } + case expr2t::isnan_id: + { + a = convert_is_nan(expr); + break; + } + case expr2t::isinf_id: + { + a = convert_is_inf(expr); + break; + } + case expr2t::isnormal_id: + { + a = convert_is_normal(expr); + break; + } + case expr2t::isfinite_id: + { + a = convert_is_finite(expr); + break; + } + case expr2t::signbit_id: + { + a = convert_signbit(expr); + break; + } + case expr2t::popcount_id: + { + a = convert_popcount(expr); + break; + } + case expr2t::bswap_id: + { + a = convert_bswap(expr); + break; + } + case expr2t::overflow_id: + { + a = overflow_arith(expr); + break; + } + case expr2t::overflow_cast_id: + { + a = overflow_cast(expr); + break; + } + case expr2t::overflow_neg_id: + { + a = overflow_neg(expr); + break; + } + case expr2t::byte_extract_id: + { + a = convert_byte_extract(expr); + break; + } + case expr2t::byte_update_id: + { + a = convert_byte_update(expr); + break; + } + case expr2t::address_of_id: + { + a = convert_addr_of(expr); + break; + } + case expr2t::equality_id: + { + /* Compare the representations directly. + * + * This also applies to pointer-typed expressions which are represented as + * (object, offset) structs, i.e., two pointers compare equal iff both + * members are the same. + * + * 'offset' is between 0 and the size of the object, both inclusively. This + * is in line with what's allowed by C99 and what current GCC assumes + * regarding the one-past the end pointer: + * + * Two pointers compare equal if and only if both are null pointers, both + * are pointers to the same object (including a pointer to an object and a + * subobject at its beginning) or function, both are pointers to one past + * the last element of the same array object, or one is a pointer to one + * past the end of one array object and the other is a pointer to the + * start of a different array object that happens to immediately follow + * the first array object in the address space. + * + * It's not strictly what Clang does, though, but de-facto, C compilers do + * perform optimizations based on provenance, i.e., "one past the end + * pointers cannot alias another object" as soon as it *cannot* be proven + * that they do. Sigh. For instance + * makes for a "fun" + * read illuminating how reasoning works from a certain compiler's + * writers' points of view. + * + * C++ has changed this one-past behaviour in [expr.eq] to "unspecified" + * + * and C might eventually follow the same path. + * + * CHERI-C semantics say that only addresses should be compared, but this + * might also change in the future, see e.g. + * . + * + * TODO: As languages begin to differ in their pointer equality semantics, + * we could move pointer comparisons to symex in order to express + * them properly according to the input language. + */ + + auto eq = to_equality2t(expr); + + if ( + is_floatbv_type(eq.side_1) && is_floatbv_type(eq.side_2) && !int_encoding) + a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); + else + a = args[0]->eq(this, args[1]); + break; + } + case expr2t::notequal_id: + { + // Handle all kinds of structs by inverted equality. The only that's really + // going to turn up is pointers though. + + auto neq = to_notequal2t(expr); + + if ( + is_floatbv_type(neq.side_1) && is_floatbv_type(neq.side_2) && + !int_encoding) + a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); + else + a = args[0]->eq(this, args[1]); + a = mk_not(a); + break; + } + case expr2t::shl_id: + { + const shl2t &shl = to_shl2t(expr); + if (shl.side_1->type->get_width() != shl.side_2->type->get_width()) + { + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(shl.side_1->type, shl.side_2); + args[1] = convert_ast(cast); } - case expr2t::byte_extract_id: + + if (int_encoding) { - a = convert_byte_extract(expr); - break; + // Raise 2^shift, then multiply first operand by that value. If it's + // negative, what to do? FIXME. + smt_astt powval = int_shift_op_array->select(this, shl.side_2); + args[1] = powval; + a = mk_mul(args[0], args[1]); } - case expr2t::byte_update_id: + else { - a = convert_byte_update(expr); - break; + a = mk_bvshl(args[0], args[1]); } - case expr2t::address_of_id: + break; + } + case expr2t::ashr_id: + { + const ashr2t &ashr = to_ashr2t(expr); + if (ashr.side_1->type->get_width() != ashr.side_2->type->get_width()) { - a = convert_addr_of(expr); - break; + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(ashr.side_1->type, ashr.side_2); + args[1] = convert_ast(cast); } - case expr2t::equality_id: - { - /* Compare the representations directly. - * - * This also applies to pointer-typed expressions which are represented as - * (object, offset) structs, i.e., two pointers compare equal iff both - * members are the same. - * - * 'offset' is between 0 and the size of the object, both inclusively. This - * is in line with what's allowed by C99 and what current GCC assumes - * regarding the one-past the end pointer: - * - * Two pointers compare equal if and only if both are null pointers, both - * are pointers to the same object (including a pointer to an object and a - * subobject at its beginning) or function, both are pointers to one past - * the last element of the same array object, or one is a pointer to one - * past the end of one array object and the other is a pointer to the - * start of a different array object that happens to immediately follow - * the first array object in the address space. - * - * It's not strictly what Clang does, though, but de-facto, C compilers do - * perform optimizations based on provenance, i.e., "one past the end - * pointers cannot alias another object" as soon as it *cannot* be proven - * that they do. Sigh. For instance - * makes for a "fun" - * read illuminating how reasoning works from a certain compiler's - * writers' points of view. - * - * C++ has changed this one-past behaviour in [expr.eq] to "unspecified" - * - * and C might eventually follow the same path. - * - * CHERI-C semantics say that only addresses should be compared, but this - * might also change in the future, see e.g. - * . - * - * TODO: As languages begin to differ in their pointer equality semantics, - * we could move pointer comparisons to symex in order to express - * them properly according to the input language. - */ - - auto eq = to_equality2t(expr); - - if ( - is_floatbv_type(eq.side_1) && is_floatbv_type(eq.side_2) && !int_encoding) - a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); - else - a = args[0]->eq(this, args[1]); - break; + + if (int_encoding) + { + // Raise 2^shift, then divide first operand by that value. If it's + // negative, I suspect the correct operation is to latch to -1, + smt_astt powval = int_shift_op_array->select(this, ashr.side_2); + args[1] = powval; + a = mk_div(args[0], args[1]); } - case expr2t::notequal_id: + else { - // Handle all kinds of structs by inverted equality. The only that's really - // going to turn up is pointers though. - - auto neq = to_notequal2t(expr); - - if ( - is_floatbv_type(neq.side_1) && is_floatbv_type(neq.side_2) && - !int_encoding) - a = fp_api->mk_smt_fpbv_eq(args[0], args[1]); - else - a = args[0]->eq(this, args[1]); - a = mk_not(a); - break; + a = mk_bvashr(args[0], args[1]); } - case expr2t::shl_id: + break; + } + case expr2t::lshr_id: + { + const lshr2t &lshr = to_lshr2t(expr); + if (lshr.side_1->type->get_width() != lshr.side_2->type->get_width()) { - const shl2t &shl = to_shl2t(expr); - if (shl.side_1->type->get_width() != shl.side_2->type->get_width()) - { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(shl.side_1->type, shl.side_2); - args[1] = convert_ast(cast); - } + // frontend doesn't cast the second operand up to the width of + // the first, which SMT does not enjoy. + expr2tc cast = typecast2tc(lshr.side_1->type, lshr.side_2); + args[1] = convert_ast(cast); + } - if (int_encoding) - { - // Raise 2^shift, then multiply first operand by that value. If it's - // negative, what to do? FIXME. - smt_astt powval = int_shift_op_array->select(this, shl.side_2); - args[1] = powval; - a = mk_mul(args[0], args[1]); - } - else - { - a = mk_bvshl(args[0], args[1]); - } - break; + if (int_encoding) + { + // Raise 2^shift, then divide first operand by that value. If it's + // negative, I suspect the correct operation is to latch to -1, + smt_astt powval = int_shift_op_array->select(this, lshr.side_2); + args[1] = powval; + a = mk_div(args[0], args[1]); } - case expr2t::ashr_id: + else { - const ashr2t &ashr = to_ashr2t(expr); - if (ashr.side_1->type->get_width() != ashr.side_2->type->get_width()) - { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(ashr.side_1->type, ashr.side_2); - args[1] = convert_ast(cast); - } - - if (int_encoding) - { - // Raise 2^shift, then divide first operand by that value. If it's - // negative, I suspect the correct operation is to latch to -1, - smt_astt powval = int_shift_op_array->select(this, ashr.side_2); - args[1] = powval; - a = mk_div(args[0], args[1]); - } - else - { - a = mk_bvashr(args[0], args[1]); - } - break; + a = mk_bvlshr(args[0], args[1]); } - case expr2t::lshr_id: + break; + } + case expr2t::abs_id: + { + const abs2t &abs = to_abs2t(expr); + if (is_unsignedbv_type(abs.value)) { - const lshr2t &lshr = to_lshr2t(expr); - if (lshr.side_1->type->get_width() != lshr.side_2->type->get_width()) - { - // frontend doesn't cast the second operand up to the width of - // the first, which SMT does not enjoy. - expr2tc cast = typecast2tc(lshr.side_1->type, lshr.side_2); - args[1] = convert_ast(cast); - } - - if (int_encoding) - { - // Raise 2^shift, then divide first operand by that value. If it's - // negative, I suspect the correct operation is to latch to -1, - smt_astt powval = int_shift_op_array->select(this, lshr.side_2); - args[1] = powval; - a = mk_div(args[0], args[1]); - } - else - { - a = mk_bvlshr(args[0], args[1]); - } - break; + // No need to do anything. + a = args[0]; } - case expr2t::abs_id: + else if (is_floatbv_type(abs.value) && !int_encoding) { - const abs2t &abs = to_abs2t(expr); - if (is_unsignedbv_type(abs.value)) - { - // No need to do anything. - a = args[0]; - } - else if (is_floatbv_type(abs.value) && !int_encoding) - { - a = fp_api->mk_smt_fpbv_abs(args[0]); - } - else - { - expr2tc lt = lessthan2tc(abs.value, gen_zero(abs.value->type)); - expr2tc neg = neg2tc(abs.value->type, abs.value); - expr2tc ite = if2tc(abs.type, lt, neg, abs.value); + a = fp_api->mk_smt_fpbv_abs(args[0]); + } + else + { + expr2tc lt = lessthan2tc(abs.value, gen_zero(abs.value->type)); + expr2tc neg = neg2tc(abs.value->type, abs.value); + expr2tc ite = if2tc(abs.type, lt, neg, abs.value); - a = convert_ast(ite); - } - break; + a = convert_ast(ite); + } + break; + } + case expr2t::lessthan_id: + { + const lessthan2t < = to_lessthan2t(expr); + // Pointer relation: + if (is_pointer_type(lt.side_1)) + { + a = convert_ptr_cmp(lt.side_1, lt.side_2, expr); } - case expr2t::lessthan_id: + else if (int_encoding) { - const lessthan2t < = to_lessthan2t(expr); - // Pointer relation: - if (is_pointer_type(lt.side_1)) - { - a = convert_ptr_cmp(lt.side_1, lt.side_2, expr); - } - else if (int_encoding) - { - a = mk_lt(args[0], args[1]); - } - else if (is_floatbv_type(lt.side_1) && is_floatbv_type(lt.side_2)) - { - a = fp_api->mk_smt_fpbv_lt(args[0], args[1]); - } - else if (is_fixedbv_type(lt.side_1) && is_fixedbv_type(lt.side_2)) - { - a = mk_bvslt(args[0], args[1]); - } - else if (is_unsignedbv_type(lt.side_1) && is_unsignedbv_type(lt.side_2)) - { - a = mk_bvult(args[0], args[1]); - } - else - { - assert(is_signedbv_type(lt.side_1) && is_signedbv_type(lt.side_2)); - a = mk_bvslt(args[0], args[1]); - } - break; + a = mk_lt(args[0], args[1]); } - case expr2t::lessthanequal_id: + else if (is_floatbv_type(lt.side_1) && is_floatbv_type(lt.side_2)) { - const lessthanequal2t <e = to_lessthanequal2t(expr); - // Pointer relation: - if (is_pointer_type(lte.side_1)) - { - a = convert_ptr_cmp(lte.side_1, lte.side_2, expr); - } - else if (int_encoding) - { - a = mk_le(args[0], args[1]); - } - else if (is_floatbv_type(lte.side_1) && is_floatbv_type(lte.side_2)) - { - a = fp_api->mk_smt_fpbv_lte(args[0], args[1]); - } - else if (is_fixedbv_type(lte.side_1) && is_fixedbv_type(lte.side_2)) - { - a = mk_bvsle(args[0], args[1]); - } - else if (is_unsignedbv_type(lte.side_1) && is_unsignedbv_type(lte.side_2)) - { - a = mk_bvule(args[0], args[1]); - } - else - { - assert(is_signedbv_type(lte.side_1) && is_signedbv_type(lte.side_2)); - a = mk_bvsle(args[0], args[1]); - } - break; + a = fp_api->mk_smt_fpbv_lt(args[0], args[1]); } - case expr2t::greaterthan_id: + else if (is_fixedbv_type(lt.side_1) && is_fixedbv_type(lt.side_2)) { - const greaterthan2t > = to_greaterthan2t(expr); - // Pointer relation: - if (is_pointer_type(gt.side_1)) - { - a = convert_ptr_cmp(gt.side_1, gt.side_2, expr); - } - else if (int_encoding) - { - a = mk_gt(args[0], args[1]); - } - else if (is_floatbv_type(gt.side_1) && is_floatbv_type(gt.side_2)) - { - a = fp_api->mk_smt_fpbv_gt(args[0], args[1]); - } - else if (is_fixedbv_type(gt.side_1) && is_fixedbv_type(gt.side_2)) - { - a = mk_bvsgt(args[0], args[1]); - } - else if (is_unsignedbv_type(gt.side_1) && is_unsignedbv_type(gt.side_2)) - { - a = mk_bvugt(args[0], args[1]); - } - else - { - assert(is_signedbv_type(gt.side_1) && is_signedbv_type(gt.side_2)); - a = mk_bvsgt(args[0], args[1]); - } - break; + a = mk_bvslt(args[0], args[1]); } - case expr2t::greaterthanequal_id: + else if (is_unsignedbv_type(lt.side_1) && is_unsignedbv_type(lt.side_2)) { - const greaterthanequal2t >e = to_greaterthanequal2t(expr); - // Pointer relation: - if (is_pointer_type(gte.side_1)) - { - a = convert_ptr_cmp(gte.side_1, gte.side_2, expr); - } - else if (int_encoding) - { - a = mk_ge(args[0], args[1]); - } - else if (is_floatbv_type(gte.side_1) && is_floatbv_type(gte.side_2)) - { - a = fp_api->mk_smt_fpbv_gte(args[0], args[1]); - } - else if (is_fixedbv_type(gte.side_1) && is_fixedbv_type(gte.side_2)) - { - a = mk_bvsge(args[0], args[1]); - } - else if (is_unsignedbv_type(gte.side_1) && is_unsignedbv_type(gte.side_2)) - { - a = mk_bvuge(args[0], args[1]); - } - else - { - assert(is_signedbv_type(gte.side_1) && is_signedbv_type(gte.side_2)); - a = mk_bvsge(args[0], args[1]); - } - break; + a = mk_bvult(args[0], args[1]); } - case expr2t::concat_id: + else { - assert( - !int_encoding && - "Concatenate encountered in integer mode; unimplemented (and funky)"); - a = mk_concat(args[0], args[1]); - break; + assert(is_signedbv_type(lt.side_1) && is_signedbv_type(lt.side_2)); + a = mk_bvslt(args[0], args[1]); } - case expr2t::implies_id: + break; + } + case expr2t::lessthanequal_id: + { + const lessthanequal2t <e = to_lessthanequal2t(expr); + // Pointer relation: + if (is_pointer_type(lte.side_1)) { - a = mk_implies(args[0], args[1]); - break; + a = convert_ptr_cmp(lte.side_1, lte.side_2, expr); } - case expr2t::bitand_id: + else if (int_encoding) { - assert(!int_encoding); - a = mk_bvand(args[0], args[1]); - break; + a = mk_le(args[0], args[1]); } - case expr2t::bitor_id: + else if (is_floatbv_type(lte.side_1) && is_floatbv_type(lte.side_2)) { - assert(!int_encoding); - a = mk_bvor(args[0], args[1]); - break; + a = fp_api->mk_smt_fpbv_lte(args[0], args[1]); } - case expr2t::bitxor_id: + else if (is_fixedbv_type(lte.side_1) && is_fixedbv_type(lte.side_2)) { - assert(!int_encoding); - a = mk_bvxor(args[0], args[1]); - break; + a = mk_bvsle(args[0], args[1]); } - case expr2t::bitnand_id: + else if (is_unsignedbv_type(lte.side_1) && is_unsignedbv_type(lte.side_2)) { - assert(!int_encoding); - a = mk_bvnand(args[0], args[1]); - break; + a = mk_bvule(args[0], args[1]); } - case expr2t::bitnor_id: + else { - assert(!int_encoding); - a = mk_bvnor(args[0], args[1]); - break; + assert(is_signedbv_type(lte.side_1) && is_signedbv_type(lte.side_2)); + a = mk_bvsle(args[0], args[1]); } - case expr2t::bitnxor_id: + break; + } + case expr2t::greaterthan_id: + { + const greaterthan2t > = to_greaterthan2t(expr); + // Pointer relation: + if (is_pointer_type(gt.side_1)) { - assert(!int_encoding); - a = mk_bvnxor(args[0], args[1]); - break; + a = convert_ptr_cmp(gt.side_1, gt.side_2, expr); } - case expr2t::bitnot_id: + else if (int_encoding) { - assert(!int_encoding); - a = mk_bvnot(args[0]); - break; + a = mk_gt(args[0], args[1]); } - case expr2t::not_id: + else if (is_floatbv_type(gt.side_1) && is_floatbv_type(gt.side_2)) { - assert(is_bool_type(expr)); - a = mk_not(args[0]); - break; + a = fp_api->mk_smt_fpbv_gt(args[0], args[1]); } - case expr2t::neg_id: + else if (is_fixedbv_type(gt.side_1) && is_fixedbv_type(gt.side_2)) { - const neg2t &neg = to_neg2t(expr); - if (int_encoding) - { - a = mk_neg(args[0]); - } - else if (is_floatbv_type(neg.value)) - { - a = fp_api->mk_smt_fpbv_neg(args[0]); - } - else - { - a = mk_bvneg(args[0]); - } - break; + a = mk_bvsgt(args[0], args[1]); } - case expr2t::and_id: + else if (is_unsignedbv_type(gt.side_1) && is_unsignedbv_type(gt.side_2)) { - a = mk_and(args[0], args[1]); - break; + a = mk_bvugt(args[0], args[1]); } - case expr2t::or_id: + else { - a = mk_or(args[0], args[1]); - break; + assert(is_signedbv_type(gt.side_1) && is_signedbv_type(gt.side_2)); + a = mk_bvsgt(args[0], args[1]); } - case expr2t::xor_id: + break; + } + case expr2t::greaterthanequal_id: + { + const greaterthanequal2t >e = to_greaterthanequal2t(expr); + // Pointer relation: + if (is_pointer_type(gte.side_1)) { - a = mk_xor(args[0], args[1]); - break; + a = convert_ptr_cmp(gte.side_1, gte.side_2, expr); } - case expr2t::bitcast_id: + else if (int_encoding) { - a = convert_bitcast(expr); - break; + a = mk_ge(args[0], args[1]); } - case expr2t::extract_id: + else if (is_floatbv_type(gte.side_1) && is_floatbv_type(gte.side_2)) { - const extract2t &ex = to_extract2t(expr); - a = convert_ast(ex.from); - if (ex.from->type->get_width() == ex.upper - ex.lower + 1) - return a; - a = mk_extract(a, ex.upper, ex.lower); - break; + a = fp_api->mk_smt_fpbv_gte(args[0], args[1]); } - case expr2t::code_comma_id: + else if (is_fixedbv_type(gte.side_1) && is_fixedbv_type(gte.side_2)) { - /* - TODO: for some reason comma expressions survive when they are under - * RETURN statements. They should have been taken care of at the GOTO - * level. Remove this code once we do! - - the expression on the right side will become the value of the entire comma-separated expression. - - e.g. - return side_1, side_2; - equals to - side1; - return side_2; - */ - const code_comma2t &cm = to_code_comma2t(expr); - a = convert_ast(cm.side_2); - break; + a = mk_bvsge(args[0], args[1]); } - default: + else if (is_unsignedbv_type(gte.side_1) && is_unsignedbv_type(gte.side_2)) { - log_error("Couldn't convert expression in unrecognised format\n{}", *expr); - abort(); + a = mk_bvuge(args[0], args[1]); + } + else + { + assert(is_signedbv_type(gte.side_1) && is_signedbv_type(gte.side_2)); + a = mk_bvsge(args[0], args[1]); } + break; + } + case expr2t::concat_id: + { + assert( + !int_encoding && + "Concatenate encountered in integer mode; unimplemented (and funky)"); + a = mk_concat(args[0], args[1]); + break; + } + case expr2t::implies_id: + { + a = mk_implies(args[0], args[1]); + break; + } + case expr2t::bitand_id: + { + assert(!int_encoding); + a = mk_bvand(args[0], args[1]); + break; + } + case expr2t::bitor_id: + { + assert(!int_encoding); + a = mk_bvor(args[0], args[1]); + break; + } + case expr2t::bitxor_id: + { + assert(!int_encoding); + a = mk_bvxor(args[0], args[1]); + break; + } + case expr2t::bitnand_id: + { + assert(!int_encoding); + a = mk_bvnand(args[0], args[1]); + break; + } + case expr2t::bitnor_id: + { + assert(!int_encoding); + a = mk_bvnor(args[0], args[1]); + break; + } + case expr2t::bitnxor_id: + { + assert(!int_encoding); + a = mk_bvnxor(args[0], args[1]); + break; + } + case expr2t::bitnot_id: + { + assert(!int_encoding); + a = mk_bvnot(args[0]); + break; + } + case expr2t::not_id: + { + assert(is_bool_type(expr)); + a = mk_not(args[0]); + break; + } + case expr2t::neg_id: + { + const neg2t &neg = to_neg2t(expr); + if (int_encoding) + { + a = mk_neg(args[0]); + } + else if (is_floatbv_type(neg.value)) + { + a = fp_api->mk_smt_fpbv_neg(args[0]); + } + else + { + a = mk_bvneg(args[0]); + } + break; + } + case expr2t::and_id: + { + a = mk_and(args[0], args[1]); + break; + } + case expr2t::or_id: + { + a = mk_or(args[0], args[1]); + break; + } + case expr2t::xor_id: + { + a = mk_xor(args[0], args[1]); + break; + } + case expr2t::bitcast_id: + { + a = convert_bitcast(expr); + break; + } + case expr2t::extract_id: + { + const extract2t &ex = to_extract2t(expr); + a = convert_ast(ex.from); + if (ex.from->type->get_width() == ex.upper - ex.lower + 1) + return a; + a = mk_extract(a, ex.upper, ex.lower); + break; + } + case expr2t::code_comma_id: + { + /* + TODO: for some reason comma expressions survive when they are under + * RETURN statements. They should have been taken care of at the GOTO + * level. Remove this code once we do! + + the expression on the right side will become the value of the entire comma-separated expression. + + e.g. + return side_1, side_2; + equals to + side1; + return side_2; + */ + const code_comma2t &cm = to_code_comma2t(expr); + a = convert_ast(cm.side_2); + break; + } + default: + log_error("Couldn't convert expression in unrecognised format\n{}", *expr); + abort(); } struct smt_cache_entryt entry = {expr, a, ctx_level}; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 1614a9cc..cdadff99 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -199,7 +199,7 @@ smt_sortt z3_slhv_convt::convert_slhv_sorts(const type2tc &type) smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) { - // log_status("------------------------------- convert ast -----------------------------"); + // log_debug("SLHV", "------------------------------- convert ast -----------------------------"); // expr->dump(); smt_cachet::const_iterator cache_result = smt_cache.find(expr); @@ -375,9 +375,9 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) struct smt_cache_entryt entry = {expr, a, ctx_level}; smt_cache.insert(entry); - // log_status("====================== converted reuslt: "); + // log_debug("SLHV", "====================== converted reuslt: "); // a->dump(); - // log_status("-------------------------------------------------------------------------"); + // log_debug("SLHV", "-------------------------------------------------------------------------"); return a; } @@ -467,7 +467,7 @@ z3_slhv_convt::convert_slhv_opts( !to_intheap_type(fieldof.source_heap->type).is_region || is_nil_expr(to_intheap_type(fieldof.source_heap->type).location)) { - log_status("Incomplete intheap type for field of"); + log_error("Incomplete intheap type for field of"); fieldof.dump(); abort(); } @@ -627,7 +627,7 @@ z3_slhv_convt::convert_slhv_opts( } default: { - log_status("Invalid SLHV operations!!!"); + log_error("Invalid SLHV operations!!!"); abort(); } } @@ -650,6 +650,7 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) log_error("Wrong symbol for projection"); expr->dump(); + abort(); } else if (is_location_of2t(expr)) return this->project(to_location_of2t(expr).source_heap); diff --git a/src/solvers/z3/z3_conv.cpp b/src/solvers/z3/z3_conv.cpp index 842b4798..7b6d60da 100644 --- a/src/solvers/z3/z3_conv.cpp +++ b/src/solvers/z3/z3_conv.cpp @@ -43,7 +43,6 @@ smt_convt *create_new_z3_solver( *tuple_api = static_cast(conv); *array_api = static_cast(conv); *fp_api = static_cast(conv); - log_status("z3 solver created"); return conv; } @@ -924,7 +923,6 @@ smt_astt z3_convt::mk_array_symbol( smt_astt z3_convt::mk_smt_symbol(const std::string &name, const smt_sort *s) { - log_status("make_smt_symbol: {}", name); return new_ast( z3_ctx.constant(name.c_str(), to_solver_smt_sort(s)->s), s); } @@ -1301,8 +1299,9 @@ expr2tc z3_convt::tuple_get_array_elem( void z3_smt_ast::dump() const { std::string ast(Z3_ast_to_string(a.ctx(), a)); - log_status( - "{}\nsort is {}", ast, Z3_sort_to_string(a.ctx(), Z3_get_sort(a.ctx(), a))); + if (messaget::state.modules.count("SLHV") > 0) + log_status( + "{}\nsort is {}", ast, Z3_sort_to_string(a.ctx(), Z3_get_sort(a.ctx(), a))); } void z3_convt::dump_smt() From 373c01418d02c251dec55e5a794c1a9861f0f6db Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 28 Sep 2024 15:45:09 +0800 Subject: [PATCH 100/126] support alloca --- benchmark/case_7.c | 147 +++------------------------ src/esbmc/bmc.cpp | 2 +- src/goto-symex/builtin_functions.cpp | 11 +- src/goto-symex/symex_assign.cpp | 3 +- src/goto-symex/symex_function.cpp | 5 + src/goto-symex/symex_main.cpp | 12 ++- src/pointer-analysis/dereference.cpp | 4 +- 7 files changed, 41 insertions(+), 143 deletions(-) diff --git a/benchmark/case_7.c b/benchmark/case_7.c index 5261fdab..a67658a8 100644 --- a/benchmark/case_7.c +++ b/benchmark/case_7.c @@ -1,140 +1,23 @@ -#include "smack.h" #include -#include "memory.h" -extern void abort(void); -#include -void reach_error() { assert(0); } +extern int __VERIFIER_nondet_int(void); -#include - -void foo(char* a, char* b, int n) { - int i; - for (i = 0; i < n; i++) - a[i] = -1; - for (i = 0; i < 1; i++) - b[i] = -1; -} - -void test_1() { - char *a, *b; - int n; - n = 2; - a = malloc(n * sizeof(*a)); - b = malloc(n * sizeof(*b)); - *b++ = 0; - foo(a, b, n); - if (b[-1]) { - free(a); - free(b); - } /* invalid free (b was iterated) */ - else { - free(a); - free(b); - } /* ditto */ -} - -int recursive(int n) { - if (n == 1) return 1; - else return recursive(n - 1) + 1; -} - -void test_2() { - int t = recursive(2); -// int p = (int*) malloc(12); -// if (t == 2) { -// free(p); -// } -} - -void add_1(int* p) { - (*p) += 1; -} - -void add_2(int* p) { - *p += 2; -} - -void test_3() { - int* a = (int*)malloc(2 * sizeof(int)); - a[0] = a[1] = 0; - add_1(a); - add_2(a + 1); - int sum = 0; - int *p = (int*) malloc(12); - for (int i = 0; i < 2; ++ i) { - sum += a[i]; - } - if (sum == 3) { - free(p); - } -} - -void test_4() { - int* a = (int*)malloc(2 * sizeof(int)); - a[0] = a[1] = 0; - a[0] += 1; - a[1] += 2; - int sum = 0; - int *p = (int*) malloc(12); - for (int i = 0; i < 2; ++ i) { - sum += a[i]; - } - if (sum == 3) { - free(p); - } -} - -void test_5() { - int* a = (int*)malloc(2 * sizeof(int)); - a[0] = a[1] = 0; - add_2(a); - int *p = (int*) malloc(12); - if (a[0] == 2) { - free(p); - } -} - - -typedef struct { - void *lo; - void *hi; -} TData; - -static void alloc_data(TData *pdata) -{ - pdata->lo = malloc(16); - pdata->hi = malloc(24); -} - -static void free_data(TData *data) +int* f() { - void *lo = data->lo; - void *hi = data->hi; + int array_size = 3; - if (lo == hi) { - free(lo); - free(hi); - } - - data->lo = (void *) 0; - data->hi = (void *) 0; + int* numbers = (int*) alloca(array_size * sizeof(int)); + + for(int k = 0; k < array_size; k++) + { + numbers[k] = __VERIFIER_nondet_int(); + } + return numbers; } -int test_6() { - TData data; - alloc_data(&data); - free_data(&data); - return 0; +int main() +{ + int* p = f(); + free(p); + return 0; } - -int main() { -// Passed - test_1(); -// test_2(); -// test_3(); -// test_4(); -// test_5(); -// test_6(); - return 0; -} \ No newline at end of file diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 9705bc90..e0f9a159 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -805,7 +805,7 @@ smt_convt::resultt bmct::multi_property_check( std::string property; if (comment.find("invalid free") != std::string::npos || - comment.find("Invalid pointer freed") != std::string::npos || + comment.find("invalid pointer freed") != std::string::npos || comment.find("Operand of free must have zero pointer offset") != std::string::npos) property = "INVALID_FREE"; diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index f7341b81..da4e5d9e 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -240,7 +240,8 @@ expr2tc goto_symext::symex_mem( // create a intheap symbol for heap region symbolt symbol; symbol.name = "dynamic_heap_"+ i2string(dynamic_counter); - symbol.id = std::string("symex_dynamic::") + id2string(symbol.name); + symbol.id = std::string("symex_dynamic::") + (!is_malloc ? "alloca::" : "") + + id2string(symbol.name); symbol.lvalue = true; symbol.type = typet(typet::t_intheap); symbol.type.dynamic(true); @@ -326,8 +327,7 @@ void goto_symext::symex_free(const expr2tc &expr) // dereference failure callbacks. expr2tc tmp = code.operand; log_debug("SLHV", "tmp before dereference FREE mode: "); - if (messaget::state.modules.count("SLHV") > 0) - tmp->dump(); + if (messaget::state.modules.count("SLHV") > 0) tmp->dump(); dereference(tmp, dereferencet::FREE); // Don't rely on the output of dereference in free mode; instead fetch all // the internal dereference state for pointed at objects, and creates claims @@ -339,6 +339,8 @@ void goto_symext::symex_free(const expr2tc &expr) tmp = dereference2tc(get_uint8_type(), tmp); dereference(tmp, dereferencet::INTERNAL); + bool use_old_encoding = !options.get_bool_option("z3-slhv"); + // Only add assertions to check pointer offset if pointer check is enabled if (!options.get_bool_option("no-pointer-check")) { @@ -359,6 +361,8 @@ void goto_symext::symex_free(const expr2tc &expr) g.guard_expr(eq); claim(eq, "Operand of free must have zero pointer offset"); + if (!use_old_encoding) break; + // Check if we are not freeing an dynamic object allocated using alloca for (auto const &a : allocad) { @@ -385,7 +389,6 @@ void goto_symext::symex_free(const expr2tc &expr) } } - bool use_old_encoding = !options.get_bool_option("z3-slhv"); if(use_old_encoding){ // Clear the alloc bit. type2tc sym_type = array_type2tc(get_bool_type(), expr2tc(), true); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 53e33d31..3ef1b976 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -243,7 +243,8 @@ void goto_symext::symex_assign( const sideeffect2t &effect = to_sideeffect2t(rhs); if (options.get_bool_option("z3-slhv") && - effect.kind != sideeffect2t::malloc) + effect.kind != sideeffect2t::malloc && + effect.kind != sideeffect2t::alloca) { log_error("Dot not support this type of sedeffect"); abort(); diff --git a/src/goto-symex/symex_function.cpp b/src/goto-symex/symex_function.cpp index 3242cbab..24a85b40 100644 --- a/src/goto-symex/symex_function.cpp +++ b/src/goto-symex/symex_function.cpp @@ -571,6 +571,11 @@ void goto_symext::pop_frame() std::string::npos) symex_free(code_free2tc(l1_sym)); + if (options.get_bool_option("z3-slhv") && + it.base_name.as_string().find("return_value$___builtin_alloca") != + std::string::npos) + symex_free(code_free2tc(l1_sym)); + // Erase from level 1 propagation cur_state->value_set.erase(to_symbol2t(l1_sym).get_symbol_name()); diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 7f7c621c..2bf64ff3 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -1200,7 +1200,7 @@ void goto_symext::add_memory_leak_checks() { for (auto const &it : dynamic_memory) { - // Don't check memory leak if the object is automatically deallocated + // Don't check memory leak if the object is automatically deallocated if (it.auto_deallocd) { log_debug( @@ -1241,8 +1241,14 @@ void goto_symext::add_memory_leak_checks() cond, "dereference failure: forgotten memory: " + get_pretty_name(it.name)); } - } else { - for (auto const &it : dynamic_memory){ + } + else + { + for (auto const &it : dynamic_memory) + { + // Don't check memory leak if the object is automatically deallocated + if (it.auto_deallocd) continue; + expr2tc deallocated = equality2tc(it.obj, gen_emp()); expr2tc when = it.alloc_guard.as_expr(); expr2tc cond = implies2tc(when, deallocated); diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index e3ff60f5..2e8d1d15 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -840,8 +840,8 @@ expr2tc dereferencet::build_reference_to( tmp_guard.add(pointer_guard); // Check that the object we're accessing is actually alive and valid for this - // mode. - valid_check(value, tmp_guard, mode); + // mode. No need to check if it is internal mode. + if (!is_internal(mode)) valid_check(value, tmp_guard, mode); // Don't do anything further if we're freeing things if (is_free(mode)) From e71d340ef7e225a81632ce40d3205acad1d5fc34 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sat, 28 Sep 2024 15:56:05 +0800 Subject: [PATCH 101/126] update svcomp script --- .../esbmc-slhv-svcomp/esbmc-slhv-wrapper.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py b/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py index ef547cf4..b788f695 100755 --- a/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py +++ b/scripts/esbmc-slhv-svcomp/esbmc-slhv-wrapper.py @@ -105,26 +105,26 @@ def get_result_string(the_result): property_file = args.propertyfile benchmark = args.benchmark - # if property_file is None: - # print("Please, specify a property file") - # exit(1) + if property_file is None: + print("Please, specify a property file") + exit(1) if benchmark is None: print("Please, specify a benchmark to verify") exit(1) # Parse property files - # f = open(property_file, 'r') - # property_file_content = f.read() + f = open(property_file, 'r') + property_file_content = f.read() property = Property.memory - # if "CHECK( init(main()), LTL(G valid-free) )" in property_file_content: - # property = Property.memory - # elif "CHECK( init(main()), LTL(G valid-memcleanup) )" in property_file_content: - # property = Property.memcleanup - # else: - # print("Unsupported Property") - # exit(1) + if "CHECK( init(main()), LTL(G valid-free) )" in property_file_content: + property = Property.memory + elif "CHECK( init(main()), LTL(G valid-memcleanup) )" in property_file_content: + property = Property.memcleanup + else: + print("Unsupported Property") + exit(1) result = verify(benchmark, property) print(get_result_string(result)) \ No newline at end of file From 00d1d4aa6e32199f8430794fe687b28ab2aa0ef6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 29 Sep 2024 09:27:46 +0800 Subject: [PATCH 102/126] remove pthread program --- src/goto-symex/symex_function.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/goto-symex/symex_function.cpp b/src/goto-symex/symex_function.cpp index 24a85b40..df6922e4 100644 --- a/src/goto-symex/symex_function.cpp +++ b/src/goto-symex/symex_function.cpp @@ -269,6 +269,13 @@ void goto_symext::symex_function_call_code(const expr2tc &expr) if (!goto_function.body_available) { + const std::string func = get_pretty_name(identifier.as_string()); + if (func.find("pthread") != std::string::npos) + { + log_error("Do not support thread program"); + abort(); + } + log_warning( "no body for function {}", get_pretty_name(identifier.as_string())); From 8c21b8671458fa5fb8e30c65dbb4a043f4673fa5 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 29 Sep 2024 09:40:58 +0800 Subject: [PATCH 103/126] fix: removing pthread --- src/goto-symex/symex_function.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/goto-symex/symex_function.cpp b/src/goto-symex/symex_function.cpp index df6922e4..c71db47c 100644 --- a/src/goto-symex/symex_function.cpp +++ b/src/goto-symex/symex_function.cpp @@ -206,10 +206,14 @@ void goto_symext::symex_function_call(const expr2tc &code) { const symbol2t &func = to_symbol2t(call.function); if (has_prefix(func.get_symbol_name(), "c:@F@atexit") || + has_prefix(func.get_symbol_name(), "c:@F@pthread") || has_prefix(func.get_symbol_name(), "c:@F@memcpy") || has_prefix(func.get_symbol_name(), "c:@F@memset")) { - log_error("Do not support"); + log_error( + "Do not support function - {}", + func.get_symbol_name() + ); abort(); } } @@ -269,13 +273,6 @@ void goto_symext::symex_function_call_code(const expr2tc &expr) if (!goto_function.body_available) { - const std::string func = get_pretty_name(identifier.as_string()); - if (func.find("pthread") != std::string::npos) - { - log_error("Do not support thread program"); - abort(); - } - log_warning( "no body for function {}", get_pretty_name(identifier.as_string())); From d77777838fef5d48a297e5eb9a7fc62e97455943 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 29 Sep 2024 10:32:22 +0800 Subject: [PATCH 104/126] encoding dead semantic in SLHV --- src/goto-symex/symex_other.cpp | 39 +++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index 62ebe8b9..c4bd8acd 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -138,9 +138,42 @@ void goto_symext::symex_dead(const expr2tc code) // Call free on alloca'd objects if (identifier.as_string().find("return_value$_alloca") != std::string::npos) symex_free(code_free2tc(l1_sym)); - - // TODO : SLHV free variable like struct - // set its heap variable to be emp + + if (options.get_bool_option("z3-slhv")) + { + // Call free on alloca'd objects + if (identifier.as_string().find("return_value$__builtin_alloca") + != std::string::npos) + symex_free(code_free2tc(l1_sym)); + + if (is_struct_type(code2)) + { + std::vector::const_iterator it; + for (it = cur_state->top().local_heap_regions.begin(); + it != cur_state->top().local_heap_regions.end(); ++it) + { + expr2tc l1_reg = *it; + cur_state->top().level1.get_ident_name(l1_reg); + if (to_symbol2t(l1_sym).get_symbol_name() == + to_symbol2t(l1_reg).get_symbol_name()) + break; + } + if (it == cur_state->top().local_heap_regions.end()) + { + log_error( + "Do not record this stack struct ? - {}", + identifier.as_string() + ); + abort(); + } + + expr2tc l1_loc = location_of2tc(l1_sym); + replace_tuple(l1_loc); + symex_free(code_free2tc(l1_loc)); + + cur_state->top().local_heap_regions.erase(it); + } + } // Erase from level 1 propagation cur_state->value_set.erase(to_symbol2t(l1_sym).get_symbol_name()); From d0ed292ed9d0e94d0e582d0cb375d0378e747679 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 29 Sep 2024 18:07:04 +0800 Subject: [PATCH 105/126] fix alignment --- src/goto-symex/builtin_functions.cpp | 14 +-- src/goto-symex/symex_assign.cpp | 9 +- src/irep2/irep2_type.cpp | 23 ++--- src/irep2/irep2_type.h | 3 +- src/pointer-analysis/dereference.cpp | 124 ++++++++++++++++++++------- src/pointer-analysis/dereference.h | 6 +- src/solvers/z3-slhv/z3_slhv_conv.cpp | 6 +- 7 files changed, 117 insertions(+), 68 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index da4e5d9e..0eec7eb0 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -362,7 +362,7 @@ void goto_symext::symex_free(const expr2tc &expr) claim(eq, "Operand of free must have zero pointer offset"); if (!use_old_encoding) break; - + // Check if we are not freeing an dynamic object allocated using alloca for (auto const &a : allocad) { @@ -1831,16 +1831,8 @@ type2tc goto_symext::create_heap_region_type( _heap_type.total_bytes = bytes; const struct_type2t &_type = to_struct_type(type); _heap_type.field_types.clear(); - const std::vector &inner_types = _type.get_structure_members(); - const std::vector &inner_field_names = _type.get_structure_member_names(); - for (unsigned int i = 0; i < inner_field_names.size(); i++) - { - const std::string &field_name = inner_field_names[i].as_string(); - if (field_name.find("anon_pad") != std::string::npos) continue; - _heap_type.field_types.push_back( - is_pointer_type(inner_types[i]) ? get_intloc_type() : get_int64_type() - ); - } + for (auto const &it : _type.members) + _heap_type.field_types.push_back(it); } else _heap_type.field_types.push_back(empty_type2tc()); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 3ef1b976..02966449 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -213,6 +213,13 @@ void goto_symext::symex_assign( replace_nondet(lhs); replace_nondet(rhs); + log_debug("SLHV", "after replace : lhs = rhs"); + if (messaget::state.modules.count("SLHV") > 0) + { + lhs->dump(); + rhs->dump(); + } + intrinsic_races_check_dereference(lhs); log_debug("SLHV", "dereference lhs write"); dereference(lhs, dereferencet::WRITE); @@ -224,7 +231,7 @@ void goto_symext::symex_assign( replace_dynamic_allocation(rhs); log_debug("SLHV", "replace done"); - log_debug("SLHV", "after deref and replace : lhs = rhs"); + log_debug("SLHV", "after deref : lhs = rhs"); if (messaget::state.modules.count("SLHV") > 0) { lhs->dump(); diff --git a/src/irep2/irep2_type.cpp b/src/irep2/irep2_type.cpp index 099d6b28..9e492197 100644 --- a/src/irep2/irep2_type.cpp +++ b/src/irep2/irep2_type.cpp @@ -189,10 +189,13 @@ unsigned int intheap_type2t::get_width() const throw symbolic_type_excp(); } -bool intheap_type2t::do_alignment(unsigned int access_sz) +bool intheap_type2t::do_alignment(const type2tc &type) { if (is_aligned) return false; - if (total_bytes % access_sz != 0) + unsigned int access_sz = type->get_width(); + if (access_sz % 8 != 0) access_sz = -1; + else access_sz /= 8; + if (access_sz == -1 || total_bytes % access_sz != 0) { log_error("Do not support unaligned access"); abort(); @@ -200,25 +203,11 @@ bool intheap_type2t::do_alignment(unsigned int access_sz) unsigned int num_of_fields = total_bytes / access_sz; if (!field_types.empty()) field_types.clear(); for (unsigned int i = 0; i < num_of_fields; i++) - field_types.push_back(get_empty_type()); + field_types.push_back(type); is_aligned = true; return true; } -bool intheap_type2t::set_field_type(unsigned int field, const type2tc &type) -{ - if (field >= field_types.size()) - { - log_error("Out of fields size"); - abort(); - } - if (!is_empty_type(field_types[field])) return false; - field_types[field] = - (is_pointer_type(type) || is_intloc_type(type)) ? - get_intloc_type() : get_int64_type(); - return true; -} - unsigned int intloc_type2t::get_width() const { throw symbolic_type_excp(); diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index c0a57fba..33094930 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -420,8 +420,7 @@ class intheap_type2t : public intheap_type_methods intheap_type2t(const intheap_type2t &ref) = default; unsigned int get_width() const override; - bool do_alignment(unsigned int access_sz); - bool set_field_type(unsigned int field, const type2tc &type); + bool do_alignment(const type2tc &type); static std::string field_names[esbmct::num_type_fields]; }; diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 2e8d1d15..b7234e46 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -165,7 +165,8 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) dereference_expr(deref.value, guard, dereferencet::READ); expr2tc tmp_obj = deref.value; - expr2tc result = dereference(tmp_obj, deref.type, guard, mode, expr2tc()); + expr2tc result = + dereference(tmp_obj, deref.type, guard, mode, expr2tc(), deref.type); expr = result; break; } @@ -389,7 +390,13 @@ expr2tc dereferencet::dereference_expr_nonscalar( // first make sure there are no dereferences in there dereference_expr(deref.value, guard, dereferencet::READ); - return dereference(deref.value, base->type, guard, mode, offset_to_scalar); + return + dereference( + deref.value, base->type, + guard, mode, + offset_to_scalar, + deref.type + ); } if (is_typecast2t(expr)) @@ -460,7 +467,8 @@ expr2tc dereferencet::dereference( const type2tc &to_type, const guardt &guard, modet mode, - const expr2tc &lexical_offset) + const expr2tc &lexical_offset, + const type2tc &deref_type) { log_debug("SLHV", "------------ dereferencing pointer ------------"); if (messaget::state.modules.count("SLHV") > 0) @@ -471,6 +479,10 @@ expr2tc dereferencet::dereference( log_debug("SLHV", "with lexical offset : "); lexical_offset->dump(); } + log_debug("SLHV", "to type : "); + to_type->dump(); + log_debug("SLHV", "deref type : {}", !is_nil_type(deref_type)); + if (!is_nil_type(deref_type)) deref_type->dump(); } internal_items.clear(); @@ -513,8 +525,24 @@ expr2tc dereferencet::dereference( { expr2tc new_value, pointer_guard; + expr2tc new_target = target; + if (options.get_bool_option("z3-slhv") && !is_nil_type(deref_type)) + { + // set intheap type + if (!is_free(mode) && !is_internal(mode) && + !is_unknown2t(new_target) && + !is_invalid2t(new_target) && + is_object_descriptor2t(new_target)) + { + object_descriptor2t &o = to_object_descriptor2t(new_target); + expr2tc &object = o.object; + if (is_intheap_type(object)) + set_intheap_type(object, deref_type); + } + } + new_value = build_reference_to( - target, mode, src, type, guard, lexical_offset, pointer_guard); + new_target, mode, src, type, guard, lexical_offset, pointer_guard); if (is_nil_expr(new_value)) continue; @@ -652,6 +680,8 @@ expr2tc dereferencet::build_reference_to( deref_expr->dump(); log_debug("SLHV", "|------------ points to ------------->"); what->dump(); + log_debug("SLHV", "with type : "); + type->dump(); log_debug("SLHV", "|------------------------------------|"); } @@ -822,20 +852,6 @@ expr2tc dereferencet::build_reference_to( abort(); } - if (is_intheap_type(value)) - { - intheap_type2t &_type = to_intheap_type(value->type); - - if (!is_free(mode) && !is_internal(mode)) - { - int access_sz = type->get_width() / 8; - // Do alignment - bool has_changed = _type.do_alignment(access_sz); - if (has_changed) - dereference_callback.update_heap_type(_type); - } - } - pointer_guard = same_object2tc(deref_expr, location_of2tc(value)); tmp_guard.add(pointer_guard); @@ -1236,27 +1252,23 @@ void dereferencet::build_deref_slhv( int field = to_constant_int2t(offset).value.to_uint64(); intheap_type2t &_type = to_intheap_type(heap_region->type); - unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); + // unsigned int access_sz = type_byte_size(type, &ns).to_uint64(); if (!_type.is_aligned) { - log_error("heap region must be aligned"); + log_error("Do not support unaligned access yet!"); abort(); } - if (field >= _type.field_types.size() || field < 0 || - access_sz != _type.total_bytes / _type.field_types.size()) + if (field >= _type.field_types.size() || field < 0) { - // Out of bound or unaligned + // Out of bound value = expr2tc(); } else { value = field_of2tc(type, value, gen_ulong(field)); - // update field type - if (_type.set_field_type(field, type)) - dereference_callback.update_heap_type(_type); - } + } } else { @@ -2537,12 +2549,28 @@ void dereferencet::check_heap_region_access( abort(); } - expr2tc size = gen_ulong(_type.field_types.size()); - offset_cond = - and2tc( - greaterthanequal2tc(offset, gen_ulong(0)), - lessthanequal2tc(offset, size) - ); + if (!is_constant_int2t(offset)) + { + log_error("offset must be constant"); + abort(); + } + + int _field = to_constant_int2t(offset).value.to_int64(); + + if (_field < 0 || _field >= _type.field_types.size()) + offset_cond = constant_bool2tc(false); + else + { + unsigned int _offset_bits = 0; + // Get the highest bit + for (unsigned int i = 0; i <= _field; i++) + _offset_bits += _type.field_types[i]->get_width(); + + expr2tc total_bits = gen_ulong(_type.total_bytes * 8); + expr2tc offset_bits = gen_ulong(_offset_bits); + + offset_cond = lessthanequal2tc(offset_bits, total_bits); + } } else { @@ -2683,3 +2711,33 @@ expr2tc dereferencet::extract_bits_from_byte_array( simplify(result); return result; } + +void dereferencet::set_intheap_type(expr2tc &heap_region, const type2tc &ty) +{ + if (!is_intheap_type(heap_region)) return; + + intheap_type2t &_type = to_intheap_type(heap_region->type); + + if (_type.is_aligned) return; + + if (is_struct_type(ty)) + { + const struct_type2t &_ty = to_struct_type(ty); + + _type.field_types.clear(); + for (auto const &it : _ty.members) + _type.field_types.push_back(it); + _type.is_aligned = true; + dereference_callback.update_heap_type(_type); + return; + } + + if (is_scalar_type(ty)) + { + if (_type.do_alignment(ty)) + dereference_callback.update_heap_type(_type); + return; + } + + // Do more analysis +} \ No newline at end of file diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index a5766e54..bbf25d8f 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -282,7 +282,8 @@ class dereferencet const type2tc &type, const guardt &guard, modet mode, - const expr2tc &extra_offset); + const expr2tc &extra_offset, + const type2tc &deref_type = type2tc()); /** Does the given expression have a dereference in it somewhere? * @param expr The expression to check for existance of a dereference. @@ -566,6 +567,9 @@ class dereferencet modet mode, unsigned long alignment = 0); + // SLHV - set intheap type + void set_intheap_type(expr2tc &heap_region, const type2tc &ty); + public: void set_block_assertions(void) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index cdadff99..e12a6ff5 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -418,11 +418,11 @@ z3_slhv_convt::convert_slhv_opts( { smt_astt loc = i == 0 ? base_loc : mk_locadd(base_loc, mk_smt_int(BigInt(i))); smt_sortt sort = - is_intloc_type(_type.field_types[i]) ? + is_pointer_type(_type.field_types[i]) ? mk_intloc_sort() : mk_int_sort(); std::string name = mk_fresh_name( - is_intloc_type(_type.field_types[i]) ? + is_pointer_type(_type.field_types[i]) ? "tmp_loc::" : "tmp_val::"); smt_astt v = mk_fresh(sort, name); pt_vec.push_back(mk_pt(loc, v)); @@ -557,7 +557,7 @@ z3_slhv_convt::convert_slhv_opts( source_loc : mk_locadd(source_loc, convert_ast(field)); smt_sortt s1; - if (is_intloc_type(_type.field_types[_field])) + if (is_pointer_type(_type.field_types[_field])) s1 = mk_intloc_sort(); else s1 = mk_int_sort(); From 4bd4267aedda18352948570d494ca9116090a35a Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 11:50:01 +0800 Subject: [PATCH 106/126] remove padded field and record its width --- src/goto-symex/builtin_functions.cpp | 21 +++++++++++++++-- src/goto-symex/symex_assign.cpp | 9 ++++++-- src/irep2/irep2_type.cpp | 5 +++- src/irep2/irep2_type.h | 3 +++ src/pointer-analysis/dereference.cpp | 28 +++++++++++++++++------ src/solvers/smt/smt_casts.cpp | 4 ---- src/solvers/z3-slhv/z3_slhv_conv.cpp | 34 +++++++++++++++++++++++++++- src/solvers/z3-slhv/z3_slhv_conv.h | 5 +++- 8 files changed, 91 insertions(+), 18 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 0eec7eb0..5a975377 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -1819,6 +1819,9 @@ type2tc goto_symext::create_heap_region_type( unsigned int bytes, const expr2tc &loc) { + log_debug("SLHV", "Create heap region with type : "); + if (messaget::state.modules.count("SLHV") > 0) type->dump(); + type2tc heap_type = get_intheap_type(); intheap_type2t &_heap_type = to_intheap_type(heap_type); _heap_type.location = loc; @@ -1831,8 +1834,22 @@ type2tc goto_symext::create_heap_region_type( _heap_type.total_bytes = bytes; const struct_type2t &_type = to_struct_type(type); _heap_type.field_types.clear(); - for (auto const &it : _type.members) - _heap_type.field_types.push_back(it); + const std::vector &inner_types = _type.get_structure_members(); + const std::vector &inner_field_names = _type.get_structure_member_names(); + _heap_type.field_types.push_back(inner_types[0]); + for (unsigned int i = 1; i < inner_field_names.size(); i++) + { + const std::string &field_name = inner_field_names[i].as_string(); + if (has_prefix(inner_field_names[i], "anon")) + _heap_type.pads.push_back(inner_types[i]->get_width()); + else + { + _heap_type.field_types.push_back(inner_types[i]); + _heap_type.pads.push_back(0); + } + } + if (!has_prefix(inner_field_names.back(), "anon")) + _heap_type.pads.push_back(0); } else _heap_type.field_types.push_back(empty_type2tc()); diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 02966449..15ff2f90 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -994,8 +994,13 @@ void goto_symext::replace_pointer_airth(expr2tc &expr) const struct_type2t &struct_type = to_struct_type(member.source_value->type); - expr2tc field = gen_ulong(struct_type.get_component_number(member.member)); - + unsigned int idx = struct_type.get_component_number(member.member); + unsigned int count_pad = 0; + for (unsigned int i = 0; i < idx; i++) + count_pad += has_prefix(struct_type.member_names[i], "anon"); + idx -= count_pad; + + expr2tc field = gen_ulong(idx); expr = field_of2tc(member.type, member.source_value, field); } } diff --git a/src/irep2/irep2_type.cpp b/src/irep2/irep2_type.cpp index 9e492197..a36cfb76 100644 --- a/src/irep2/irep2_type.cpp +++ b/src/irep2/irep2_type.cpp @@ -192,7 +192,7 @@ unsigned int intheap_type2t::get_width() const bool intheap_type2t::do_alignment(const type2tc &type) { if (is_aligned) return false; - unsigned int access_sz = type->get_width(); + int access_sz = type->get_width(); if (access_sz % 8 != 0) access_sz = -1; else access_sz /= 8; if (access_sz == -1 || total_bytes % access_sz != 0) @@ -203,7 +203,10 @@ bool intheap_type2t::do_alignment(const type2tc &type) unsigned int num_of_fields = total_bytes / access_sz; if (!field_types.empty()) field_types.clear(); for (unsigned int i = 0; i < num_of_fields; i++) + { field_types.push_back(type); + pads.push_back(0); + } is_aligned = true; return true; } diff --git a/src/irep2/irep2_type.h b/src/irep2/irep2_type.h index 33094930..519f9971 100644 --- a/src/irep2/irep2_type.h +++ b/src/irep2/irep2_type.h @@ -226,6 +226,9 @@ class intheap_data : public type2t bool is_region; bool is_aligned; bool is_alloced; + + // Hide + std::vector pads; // Type mangling: typedef esbmct::field_traits diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index b7234e46..2bab141a 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -682,6 +682,8 @@ expr2tc dereferencet::build_reference_to( what->dump(); log_debug("SLHV", "with type : "); type->dump(); + log_debug("SLHV", "offset - {}", !is_nil_expr(lexical_offset)); + if (!is_nil_expr(lexical_offset)) lexical_offset->dump(); log_debug("SLHV", "|------------------------------------|"); } @@ -838,10 +840,6 @@ expr2tc dereferencet::build_reference_to( } else { value = object; - if (messaget::state.modules.count("SLHV") > 0 && - !is_nil_expr(lexical_offset)) - lexical_offset->dump(); - guardt tmp_guard(guard); if (!is_intheap_type(value) && !is_pointer_type(value) && @@ -2564,7 +2562,7 @@ void dereferencet::check_heap_region_access( unsigned int _offset_bits = 0; // Get the highest bit for (unsigned int i = 0; i <= _field; i++) - _offset_bits += _type.field_types[i]->get_width(); + _offset_bits += _type.field_types[i]->get_width() + _type.pads[i]; expr2tc total_bits = gen_ulong(_type.total_bytes * 8); expr2tc offset_bits = gen_ulong(_offset_bits); @@ -2725,8 +2723,24 @@ void dereferencet::set_intheap_type(expr2tc &heap_region, const type2tc &ty) const struct_type2t &_ty = to_struct_type(ty); _type.field_types.clear(); - for (auto const &it : _ty.members) - _type.field_types.push_back(it); + const std::vector &inner_types = + _ty.get_structure_members(); + const std::vector &inner_field_names = + _ty.get_structure_member_names(); + _type.field_types.push_back(inner_types[0]); + for (unsigned int i = 1; i < inner_field_names.size(); i++) + { + const std::string &field_name = inner_field_names[i].as_string(); + if (has_prefix(inner_field_names[i], "anon")) + _type.pads.push_back(inner_types[i]->get_width()); + else + { + _type.field_types.push_back(inner_types[i]); + _type.pads.push_back(0); + } + } + if (!has_prefix(inner_field_names.back(), "anon")) + _type.pads.push_back(0); _type.is_aligned = true; dereference_callback.update_heap_type(_type); return; diff --git a/src/solvers/smt/smt_casts.cpp b/src/solvers/smt/smt_casts.cpp index 24031213..6e82338d 100644 --- a/src/solvers/smt/smt_casts.cpp +++ b/src/solvers/smt/smt_casts.cpp @@ -650,10 +650,6 @@ smt_astt smt_convt::convert_typecast(const expr2tc &expr) { const typecast2t &cast = to_typecast2t(expr); - if (is_intloc_type(cast.from->type) && is_pointer_type(cast.type) || - is_pointer_type(cast.from->type) && is_intloc_type(cast.type)) - return convert_ast(cast.from); - if ( int_encoding && is_floatbv_type(cast.from->type) && is_floatbv_type(cast.type)) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index e12a6ff5..b767718a 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -163,6 +163,15 @@ smt_astt z3_slhv_convt::mk_locadd(smt_astt l, smt_astt o) ); } +smt_astt z3_slhv_convt::mk_loc2int(smt_astt l) +{ + assert(l->sort->id == SMT_SORT_INTLOC); +// return new_ast( +// z3::loc2int(to_solver_smt_ast(l)->a), +// this->mk_intloc_sort() +// ); +} + BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed) { log_error("SLHV does not support bv"); @@ -287,7 +296,7 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) } case expr2t::typecast_id: { - a = convert_typecast(expr); + a = convert_slhv_typecast(expr); break; } case expr2t::if_id: @@ -633,6 +642,29 @@ z3_slhv_convt::convert_slhv_opts( } } +smt_astt z3_slhv_convt::convert_slhv_typecast(const expr2tc &expr) +{ + if (!is_typecast2t(expr)) + { + log_error("Wrong typecast expr"); + expr->dump(); + abort(); + } + + const typecast2t &cast = to_typecast2t(expr); + + return convert_ast(cast.from); + + smt_astt a = convert_ast(cast.from); + + // TODO: add support loc2int + if ((is_pointer_type(cast.from->type) || is_intloc_type(cast.from->type)) && + (is_signedbv_type(cast.type) || is_unsignedbv_type(cast.type))) + return mk_loc2int(a); + + return a; +} + smt_astt z3_slhv_convt::project(const expr2tc &expr) { if (is_constant_intloc2t(expr)) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.h b/src/solvers/z3-slhv/z3_slhv_conv.h index 85928dc2..0997f58f 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.h +++ b/src/solvers/z3-slhv/z3_slhv_conv.h @@ -31,8 +31,9 @@ class z3_slhv_convt : public z3_convt { smt_astt mk_uplus(smt_astt ht1, smt_astt ht2); smt_astt mk_uplus(std::vector hts); smt_astt mk_subh(smt_astt ht1, smt_astt ht2); - smt_astt mk_disjh(smt_astt ht1, smt_astt ); + smt_astt mk_disjh(smt_astt ht1, smt_astt ht2); smt_astt mk_locadd(smt_astt l, smt_astt o); + smt_astt mk_loc2int(smt_astt l); // value obtaining from solver, not supported here BigInt get_bv(smt_astt a, bool is_signed) override; @@ -55,6 +56,8 @@ class z3_slhv_convt : public z3_convt { void print_smt_formulae(std::ostream& dest); std::vector assertions; + + smt_astt convert_slhv_typecast(const expr2tc &expr); }; #endif \ No newline at end of file From 8667aac791a4b004c686182b0eae94809fda7df6 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 13:34:29 +0800 Subject: [PATCH 107/126] fix if expr in pt --- src/goto-symex/dynamic_allocation.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 379479c3..2b6e497f 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -74,7 +74,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) get_int64_type(), std::string("SOME_SIZE_") + std::to_string(nondet_counter) ); - + expr2tc pt = points_to2tc(loc, size_sym); expr2tc disj = disjh2tc(alloc_size_heap); to_disjh2t(disj).do_disjh(pt); @@ -126,6 +126,8 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) } else { + expr2tc ptr_obj = ptr.ptr_obj; + expr2tc alloc_size_heap; migrate_expr(symbol_expr(*ns.lookup(alloc_size_heap_name)), alloc_size_heap); @@ -139,16 +141,16 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) expr2tc loc; expr2tc extra_eq; - if (!is_if2t(obj_expr)) - loc = obj_expr; + if (!is_if2t(ptr_obj)) + loc = ptr_obj; else { loc = symbol2tc( - get_int64_type(), + get_intloc_type(), std::string("assigned_loc_") + std::to_string(nondet_counter) ); - extra_eq = equality2tc(loc, obj_expr); + extra_eq = equality2tc(loc, ptr_obj); } expr2tc pt = points_to2tc(loc, size_sym); From e71c108ad0c8f8d7dea73987cd1fc86b13e1bc2f Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 15:50:26 +0800 Subject: [PATCH 108/126] fix ite in pt --- src/goto-symex/builtin_functions.cpp | 2 +- src/goto-symex/dynamic_allocation.cpp | 2 +- src/pointer-analysis/dereference.cpp | 22 ++++++++++++++++++---- src/pointer-analysis/dereference.h | 9 ++++++++- src/solvers/z3-slhv/z3_slhv_conv.cpp | 9 ++++++++- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 5a975377..42d07c57 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -401,7 +401,7 @@ void goto_symext::symex_free(const expr2tc &expr) symex_assign(code_assign2tc(valid_index_expr, falsity), true); } else { expr2tc free_ptr = code.operand; - dereference(free_ptr, dereferencet::READ); + dereference(free_ptr, dereferencet::RAW_READ); expr2tc when = gen_false_expr(); for(auto const& item : internal_deref_items) diff --git a/src/goto-symex/dynamic_allocation.cpp b/src/goto-symex/dynamic_allocation.cpp index 2b6e497f..db4e3d0a 100644 --- a/src/goto-symex/dynamic_allocation.cpp +++ b/src/goto-symex/dynamic_allocation.cpp @@ -148,7 +148,7 @@ void goto_symext::default_replace_dynamic_allocation(expr2tc &expr) loc = symbol2tc( get_intloc_type(), - std::string("assigned_loc_") + std::to_string(nondet_counter) + std::string("_assigned_loc_") + std::to_string(nondet_counter) ); extra_eq = equality2tc(loc, ptr_obj); } diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 2bab141a..3702bd0f 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -162,7 +162,9 @@ void dereferencet::dereference_expr(expr2tc &expr, guardt &guard, modet mode) assert(is_dereference2t(expr)); dereference2t &deref = to_dereference2t(expr); // first make sure there are no dereferences in there - dereference_expr(deref.value, guard, dereferencet::READ); + modet read_mod = + is_raw_read(mode) ? dereferencet::RAW_READ : dereferencet::READ; + dereference_expr(deref.value, guard, read_mod); expr2tc tmp_obj = deref.value; expr2tc result = @@ -388,7 +390,9 @@ expr2tc dereferencet::dereference_expr_nonscalar( dereference2t &deref = to_dereference2t(expr); // first make sure there are no dereferences in there - dereference_expr(deref.value, guard, dereferencet::READ); + modet read_mod = + is_raw_read(mode) ? dereferencet::RAW_READ : dereferencet::READ; + dereference_expr(deref.value, guard, read_mod); return dereference( @@ -483,6 +487,13 @@ expr2tc dereferencet::dereference( to_type->dump(); log_debug("SLHV", "deref type : {}", !is_nil_type(deref_type)); if (!is_nil_type(deref_type)) deref_type->dump(); + + log_debug( + "SLHV", + "mode - {}", + is_internal(mode) ? "internal" : + is_free(mode) ? "free" : + is_raw_read(mode) ? "raw_read" : "deref"); } internal_items.clear(); @@ -855,7 +866,8 @@ expr2tc dereferencet::build_reference_to( // Check that the object we're accessing is actually alive and valid for this // mode. No need to check if it is internal mode. - if (!is_internal(mode)) valid_check(value, tmp_guard, mode); + if (!is_internal(mode) && !is_raw_read(mode)) + valid_check(value, tmp_guard, mode); // Don't do anything further if we're freeing things if (is_free(mode)) @@ -911,7 +923,8 @@ expr2tc dereferencet::build_reference_to( } // other checks may be added later - check_heap_region_access(value, final_offset, type, tmp_guard, mode); + if (!is_raw_read(mode)) + check_heap_region_access(value, final_offset, type, tmp_guard, mode); build_deref_slhv(value, final_offset, type, tmp_guard, mode, alignment); @@ -2296,6 +2309,7 @@ void dereferencet::valid_check( : "invalid dereference pointer"; // deref failure will replace heap region with heap contains // that indicates the reigon is avaliable. + log_debug("SLHV", "add valid check : {}", foo); dereference_failure("pointer dereference", foo, tmp_guard); return; } diff --git a/src/pointer-analysis/dereference.h b/src/pointer-analysis/dereference.h index bbf25d8f..84ed6856 100644 --- a/src/pointer-analysis/dereference.h +++ b/src/pointer-analysis/dereference.h @@ -222,7 +222,8 @@ class dereferencet WRITE, /// The result of the expression will be written to. FREE, /// The referred to object will be freed. INTERNAL, /// Calling code only wants the internal value-set data. - } op : 2; + RAW_READ, /// The dereference will not generate assertions. + } op : 3; /** * Whether the access is performed in a non-standard, known-unaligned way @@ -255,12 +256,18 @@ class dereferencet { return m.op == INTERNAL; } + + friend bool is_raw_read(const modet &m) + { + return m.op == RAW_READ; + } }; static const constexpr modet READ = {modet::READ, false}; static const constexpr modet WRITE = {modet::WRITE, false}; static const constexpr modet FREE = {modet::FREE, false}; static const constexpr modet INTERNAL = {modet::INTERNAL, false}; + static const constexpr modet RAW_READ = {modet::RAW_READ, false}; /** Take an expression and dereference it. * This will descend through the whole of the expression given, and diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index b767718a..eb002dbe 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -620,7 +620,14 @@ z3_slhv_convt::convert_slhv_opts( smt_astt h1 = mk_fresh(h->sort, mk_fresh_name(std::string("_tmp_heap_"))); smt_astt v1 = mk_fresh(mk_int_sort(), mk_fresh_name(std::string("_tmp_val_"))); - smt_astt heap_state = mk_eq(h, mk_uplus(h1, mk_pt(l, v1))); + smt_astt nl = + mk_fresh( + mk_intloc_sort(), + mk_fresh_name(std::string("_assigned_loc_")) + ); + smt_astt heap_state = + mk_and(mk_eq(nl, l), mk_eq(h, mk_uplus(h1, mk_pt(nl, v1)))); + assert_ast(heap_state); return h1; From 0414e1dd00f90bfc325e83912cfc34835f1d829d Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 16:16:39 +0800 Subject: [PATCH 109/126] fix script typo --- scripts/x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/x.py b/scripts/x.py index 364c5c2e..0feda27f 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -162,7 +162,7 @@ def run_expriment_on(benchmark_root): compile() elif sys.argv[1] == "--run": run_on(sys.argv[2], sys.argv[3:]) - elif sys.argv[1] == "--expriment": + elif sys.argv[1] == "--experiment": run_expriment_on(sys.argv[2]) elif sys.argv[1] == "--help": help() From 98196d7b47e7306ee2623078b06fbc242d571d85 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 16:30:32 +0800 Subject: [PATCH 110/126] update script --- scripts/x.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 0feda27f..84da5e83 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -38,7 +38,7 @@ def collect_one_assert(info): prt = info[2].split(" ") res["Property"] = prt[1] res["Result"] = prt[3] - res["Time"] = prt[5] + res["Time"] = prt[5].replace('s', '') return res @@ -48,6 +48,7 @@ def analysis_result(log): flag = "--- Result ---" assert_results = [] + total_time = 0 is_collecting = False with open(log) as log_file: info_buf = [] @@ -58,12 +59,17 @@ def analysis_result(log): continue else: is_collecting = False - assert_results.append(collect_one_assert(info_buf)) + one_res = collect_one_assert(info_buf) + assert_results.append(one_res) info_buf.clear() + + # collect time for each assertion + total_time += float(one_res["Time"]) + if not is_collecting: continue info_buf.append(line.strip()) - return assert_results + return (assert_results, total_time) def run_on(cprog, extra_args): assert(os.path.exists(cprog)) @@ -83,7 +89,7 @@ def run_on(cprog, extra_args): "--output", vcc_log, "--multi-property", - "--z3-slhv", + "--z3-slhv" ] if "--debug" in extra_args: @@ -97,11 +103,13 @@ def run_on(cprog, extra_args): print(f"Command: {cmd}") os.system(cmd) - result = analysis_result(t_log) + (result, total_time) = analysis_result(t_log) for d in result: res = [k + ": " + v for k, v in list(d.items())] print("{:<10} {:<12} {:<25} {:<15} {:<10}".format(*res)) + print(f"Total time: {round(total_time, 3)}") + return result def collect_results(cprog): From db41e673e3c7b9bde21961f1e8fa08705af49710 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 16:58:39 +0800 Subject: [PATCH 111/126] calculate totaltime for each case --- scripts/x.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/x.py b/scripts/x.py index 84da5e83..1fb734a3 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -135,11 +135,22 @@ def generate_csv(results): w.writeheader() for cprog, assert_results in results.items(): is_head = True + total_time = 0 for assert_result in assert_results: new_row = {'File': cprog if is_head else ''} is_head = False + total_time += float(assert_result["Time"]) new_row.update(assert_result) w.writerow(new_row) + new_row = { + "File": '', + "Line": '', + "Column": '', + "Property": '', + "Result": 'Totaltime', + "Time": total_time + } + w.writerow(new_row) def run_expriment_on(benchmark_root): From 4caf35952450419506de9563d83cd5a8689a2e63 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 17:08:18 +0800 Subject: [PATCH 112/126] support loc2int --- src/solvers/z3-slhv/z3_slhv_conv.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index eb002dbe..1be5dbf6 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -166,10 +166,10 @@ smt_astt z3_slhv_convt::mk_locadd(smt_astt l, smt_astt o) smt_astt z3_slhv_convt::mk_loc2int(smt_astt l) { assert(l->sort->id == SMT_SORT_INTLOC); -// return new_ast( -// z3::loc2int(to_solver_smt_ast(l)->a), -// this->mk_intloc_sort() -// ); + return new_ast( + z3::loc2int(to_solver_smt_ast(l)->a), + this->mk_int_sort() + ); } BigInt z3_slhv_convt::get_bv(smt_astt a, bool is_signed) @@ -660,11 +660,8 @@ smt_astt z3_slhv_convt::convert_slhv_typecast(const expr2tc &expr) const typecast2t &cast = to_typecast2t(expr); - return convert_ast(cast.from); - smt_astt a = convert_ast(cast.from); - // TODO: add support loc2int if ((is_pointer_type(cast.from->type) || is_intloc_type(cast.from->type)) && (is_signedbv_type(cast.type) || is_unsignedbv_type(cast.type))) return mk_loc2int(a); From 1ae4e494a29c461ff2f950f9dae441dd74a7c7dd Mon Sep 17 00:00:00 2001 From: zhuyt Date: Mon, 30 Sep 2024 17:40:09 +0800 Subject: [PATCH 113/126] update script --- scripts/x.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/x.py b/scripts/x.py index 1fb734a3..91f639b9 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -174,7 +174,9 @@ def run_expriment_on(benchmark_root): if __name__ == '__main__': if not os.path.exists(output_root): os.mkdir(output_root) + if not os.path.exists(log_root): os.mkdir(log_root) + if not os.path.exists(vcc_log): os.mkdir(vcc_root) if sys.argv[1] == "--compile": From cbb29bb52e1f9696da06ee2d059f438392f7d179 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 1 Oct 2024 10:37:29 +0800 Subject: [PATCH 114/126] disable building error trace --- src/esbmc/bmc.cpp | 8 ++++---- src/solvers/z3-slhv/z3_slhv_conv.cpp | 2 +- src/solvers/z3/z3_conv.cpp | 11 +++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index e0f9a159..2648c4f7 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -785,9 +785,8 @@ smt_convt::resultt bmct::multi_property_check( fine_timet sat_stop = current_time(); log_status( - "Solving claim '{}' with solver {}", - claim.claim_msg, - runtime_solver->solver_text()); + "Solving claim {} with solver {}", + i, runtime_solver->solver_text()); log_status( "Runtime decision procedure: {}s", time2string(sat_stop - sat_start)); @@ -831,7 +830,8 @@ smt_convt::resultt bmct::multi_property_check( // If an assertion instance is verified to be violated if (result == smt_convt::P_SATISFIABLE) { - if (runtime_solver->solver_text() == "Z3-slhv") { + if (options.get_bool_option("z3-slhv") || + options.get_bool_option("result-only")) { final_result = result; fail_fast_cnt++; return; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 1be5dbf6..ea110590 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -54,7 +54,7 @@ z3_slhv_convt::~z3_slhv_convt() { delete_all_asts(); } smt_convt::resultt z3_slhv_convt::dec_solve() { const std::string &path = options.get_option("output"); - if (path != "-") + if (options.get_bool_option("show-vcc") && path != "-") { std::ofstream out(path, std::ios_base::app); out << "SMT formulas for VCCs:\n"; diff --git a/src/solvers/z3/z3_conv.cpp b/src/solvers/z3/z3_conv.cpp index 7b6d60da..c4b02aad 100644 --- a/src/solvers/z3/z3_conv.cpp +++ b/src/solvers/z3/z3_conv.cpp @@ -84,6 +84,17 @@ void z3_convt::pop_ctx() smt_convt::resultt z3_convt::dec_solve() { + const std::string &path = options.get_option("output"); + if (options.get_bool_option("show-vcc") && path != "-") + { + std::ofstream out(path, std::ios_base::app); + out << "SMT formulas for VCCs:\n"; + for(z3::expr expr : solver.assertions()) { + out << expr.to_string() << '\n'; + } + out.close(); + } + pre_solve(); z3::check_result result = solver.check(); From d8a86350f9e90d2d52be7570c649be3ec9826c57 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 1 Oct 2024 11:28:53 +0800 Subject: [PATCH 115/126] update x.py for running esbmc --- scripts/x.py | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 91f639b9..631aacdd 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -22,6 +22,27 @@ def compile(): def help(): os.system(f"{esbmc_slhv} -h") + cmds = { + "--compile" : ('',"Compile esbmc"), + "--run" : ("file extra_args","Only test a single file 'file'"), + "--experiment": ("path extra_args", "Run on a benchmark 'path'"), + "--help": ('', "Show help information"), + } + + args = { + "--esbmc" : "Disable SLHV and use default esbmc with solver Z3", + "--debug" : "Output debug info of SLHV", + "--std-out" : "Output info in std::out" + } + + print("Commands for x.py:") + for cmd in cmds.items(): + cmdline = [cmd[0] + ' ' + cmd[1][0], cmd[1][1]] + print(" {:<35} {:<50}".format(*cmdline)) + print("Extra args:") + for arg in args.items(): + print(" {:<35} {:<50}".format(*arg)) + def collect_one_assert(info): assert(len(info) == 3) res = {} @@ -81,23 +102,25 @@ def run_on(cprog, extra_args): esbmc_slhv, cprog, "--no-library", - "--ir", "--force-malloc-success", "--memory-leak-check", "--result-only", "--show-vcc", "--output", vcc_log, - "--multi-property", - "--z3-slhv" + "--multi-property" ] + if "--esbmc" in extra_args: + args.append("--z3") + else: + args.append("--z3-slhv") + if "--debug" in extra_args: args.append("--verbosity SLHV:8") - redirect_arg = [">", t_log] if "--std-out" not in extra_args: - args += redirect_arg + args += [">", t_log] cmd = " ".join(args) print(f"Command: {cmd}") @@ -153,7 +176,7 @@ def generate_csv(results): w.writerow(new_row) -def run_expriment_on(benchmark_root): +def run_expriment_on(benchmark_root, extra_args): assert(os.path.exists(benchmark_root)) cprogs = [] @@ -166,7 +189,7 @@ def run_expriment_on(benchmark_root): results = {} for cprog in cprogs: cprog_path = os.path.join(benchmark_root, cprog) - results[cprog] = run_on(cprog_path, []) + results[cprog] = run_on(cprog_path, extra_args) collect_results(cprog) generate_csv(results) @@ -178,13 +201,16 @@ def run_expriment_on(benchmark_root): os.mkdir(log_root) if not os.path.exists(vcc_log): os.mkdir(vcc_root) + + if "--esbmc" in sys.argv: + csv_file = os.path.join(output_root, "results_esbmc.csv") if sys.argv[1] == "--compile": compile() elif sys.argv[1] == "--run": run_on(sys.argv[2], sys.argv[3:]) elif sys.argv[1] == "--experiment": - run_expriment_on(sys.argv[2]) + run_expriment_on(sys.argv[2], sys.argv[3:]) elif sys.argv[1] == "--help": help() else: From 7d48529843340dad4838a852d10025e92d4aaefa Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 1 Oct 2024 15:23:50 +0800 Subject: [PATCH 116/126] support constant struct --- src/goto-symex/builtin_functions.cpp | 62 +++++++++++++++---- src/goto-symex/goto_symex.h | 21 ++++++- src/goto-symex/symex_assign.cpp | 31 +++++----- src/goto-symex/symex_main.cpp | 31 ++++------ src/goto-symex/symex_other.cpp | 9 ++- src/irep2/irep2.h | 5 +- src/irep2/irep2_expr.cpp | 1 + src/irep2/irep2_expr.h | 20 ++++++ src/irep2/templates/irep2_templates.cpp | 2 + .../templates/irep2_templates_expr_data.cpp | 5 +- src/pointer-analysis/value_set.cpp | 13 ++++ src/solvers/z3-slhv/z3_slhv_conv.cpp | 37 ++++++++--- src/util/base_type.cpp | 6 +- src/util/migrate.cpp | 9 +++ 14 files changed, 186 insertions(+), 66 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 42d07c57..2e1847a4 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -1834,12 +1834,13 @@ type2tc goto_symext::create_heap_region_type( _heap_type.total_bytes = bytes; const struct_type2t &_type = to_struct_type(type); _heap_type.field_types.clear(); - const std::vector &inner_types = _type.get_structure_members(); - const std::vector &inner_field_names = _type.get_structure_member_names(); + const std::vector &inner_types = + _type.get_structure_members(); + const std::vector &inner_field_names = + _type.get_structure_member_names(); _heap_type.field_types.push_back(inner_types[0]); for (unsigned int i = 1; i < inner_field_names.size(); i++) { - const std::string &field_name = inner_field_names[i].as_string(); if (has_prefix(inner_field_names[i], "anon")) _heap_type.pads.push_back(inner_types[i]->get_width()); else @@ -1857,7 +1858,8 @@ type2tc goto_symext::create_heap_region_type( return heap_type; } -expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &flag) +expr2tc goto_symext::create_heap_region( + const sideeffect2t &effect, expr2tc &flag) { type2tc type; if (effect.kind == sideeffect2t::nondet) @@ -1871,9 +1873,7 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla type = effect.alloctype; if (is_nil_type(type)) type = char_type2(); } - - expr2tc base_loc = create_heap_region_loc(flag); - + unsigned int bytes; if (is_struct_type(type)) { @@ -1892,7 +1892,9 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla bytes = to_constant_int2t(op).value.to_uint64(); } + expr2tc base_loc = create_heap_region_loc(flag); type2tc heap_type = create_heap_region_type(type, bytes, base_loc); + if (effect.kind == sideeffect2t::nondet) to_intheap_type(heap_type).is_alloced = true; flag->type = heap_type; @@ -1900,6 +1902,31 @@ expr2tc goto_symext::create_heap_region(const sideeffect2t &effect, expr2tc &fla return heap_region2tc(heap_type, base_loc); } +expr2tc goto_symext::create_constant_heap_region( + const constant_struct2t &effect, + expr2tc &flag) +{ + type2tc type = effect.type; + unsigned int bytes = type_byte_size(type, &ns).to_uint64(); + + expr2tc base_loc = create_heap_region_loc(flag); + type2tc heap_type = create_heap_region_type(type, bytes, base_loc); + to_intheap_type(heap_type).is_alloced = true; + flag->type = heap_type; + + std::vector members; + const struct_type2t &_type = to_struct_type(type); + const std::vector &inner_field_names = + _type.get_structure_member_names(); + for (unsigned int i = 0; i < inner_field_names.size(); i++) + { + if (!has_prefix(inner_field_names[i], "anon")) + members.push_back(effect.datatype_members[i]); + } + + return constant_heap_region2tc(heap_type, members); +} + void goto_symext::symex_disj_heaps(const expr2tc &heap) { if (!is_symbol2t(heap) || !is_intheap_type(heap)) @@ -1930,18 +1957,27 @@ void goto_symext::symex_disj_heaps(const expr2tc &heap) ); } -void goto_symext::symex_nondet(const expr2tc &lhs, const expr2tc &effect) +void goto_symext::symex_stack_sideeffect(const expr2tc &lhs, const expr2tc &effect) { expr2tc new_lhs = lhs; expr2tc new_rhs = effect; - const sideeffect2t &_effect = to_sideeffect2t(effect); + if (is_sideeffect2t(effect)) + { + const sideeffect2t &_effect = to_sideeffect2t(effect); - if (_effect.kind == sideeffect2t::nondet && - !is_struct_type(_effect.type)) - replace_nondet(new_rhs); + if (_effect.kind == sideeffect2t::nondet && + !is_struct_type(_effect.type)) + replace_nondet(new_rhs); + else + new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); + } else - new_rhs = create_heap_region(to_sideeffect2t(effect), new_lhs); + { + // constan struct + const constant_struct2t &_struct = to_constant_struct2t(effect); + new_rhs = create_constant_heap_region(_struct, new_lhs); + } symex_assign(code_assign2tc(new_lhs, new_rhs)); diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 8d54f968..db612d3e 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -831,6 +831,13 @@ class goto_symext */ void replace_tuple(expr2tc &expr); + /** + * @brief Replace expr and type for SLHV + * + * @param expr + */ + void adapt_to_slhv(expr2tc &expr); + /** * @brief Create a heap region intloc * @@ -860,6 +867,18 @@ class goto_symext */ expr2tc create_heap_region(const sideeffect2t &effect, expr2tc &flag); + /** + * @brief Create a constant heap region object + * + * @param effect + * @param flag + * @return expr2tc + */ + expr2tc create_constant_heap_region( + const constant_struct2t &effect, + expr2tc &flag + ); + /** * @brief Encode disjointness among all heap regions * @@ -873,7 +892,7 @@ class goto_symext * @param lhs * @param effect */ - void symex_nondet(const expr2tc &lhs, const expr2tc &effect); + void symex_stack_sideeffect(const expr2tc &lhs, const expr2tc &effect); /** * Fetch reference to global dynamic object counter. diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 15ff2f90..84a59f9e 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -187,25 +187,14 @@ void goto_symext::symex_assign( expr2tc rhs = code.source; if (options.get_bool_option("z3-slhv")) { - replace_null(lhs); - replace_null(rhs); - - replace_pointer_airth(lhs); - replace_pointer_airth(rhs); - - replace_address_of(lhs); - replace_address_of(rhs); - - replace_tuple(lhs); - replace_tuple(rhs); - - replace_typecast(lhs); - replace_typecast(rhs); + adapt_to_slhv(lhs); + adapt_to_slhv(rhs); if (is_sideeffect2t(rhs) && - to_sideeffect2t(rhs).kind == sideeffect2t::nondet) + to_sideeffect2t(rhs).kind == sideeffect2t::nondet || + is_constant_struct2t(rhs)) { - symex_nondet(lhs, rhs); + symex_stack_sideeffect(lhs, rhs); return; } } @@ -1048,4 +1037,14 @@ void goto_symext::replace_tuple(expr2tc &expr) expr->type = create_heap_region_type(expr->type, bytes, base_loc); to_intheap_type(expr->type).is_alloced = true; } +} + + +void goto_symext::adapt_to_slhv(expr2tc &expr) +{ + replace_null(expr); + replace_pointer_airth(expr); + replace_address_of(expr); + replace_tuple(expr); + replace_typecast(expr); } \ No newline at end of file diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 2bf64ff3..26c44dfd 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -188,11 +188,7 @@ void goto_symext::symex_step(reachability_treet &art) log_debug("SLHV", " >>>>>>>> goto symex: GOTO"); expr2tc tmp(instruction.guard); if (options.get_bool_option("z3-slhv")) - { - replace_null(tmp); - replace_pointer_airth(tmp); - replace_typecast(tmp); - } + adapt_to_slhv(tmp); replace_nondet(tmp); if (messaget::state.modules.count("SLHV") > 0) tmp->dump(); @@ -227,10 +223,8 @@ void goto_symext::symex_step(reachability_treet &art) } if (options.get_bool_option("z3-slhv")) - { - replace_null(thecode); - replace_typecast(thecode); - } + adapt_to_slhv(thecode); + symex_return(thecode); } @@ -274,9 +268,15 @@ void goto_symext::symex_step(reachability_treet &art) { log_debug("SLHV", " >>>>>>>> goto symex: FUNCTION_CALL"); expr2tc deref_code = instruction.code; + + if (options.get_bool_option("z3-slhv")) + adapt_to_slhv(deref_code); + replace_nondet(deref_code); code_function_call2t &call = to_code_function_call2t(deref_code); + + if (messaget::state.modules.count("SLHV") > 0) call.dump(); if (!is_nil_expr(call.ret)) { @@ -410,11 +410,8 @@ void goto_symext::symex_assume() expr2tc cond = cur_state->source.pc->guard; if (options.get_bool_option("z3-slhv")) - { - replace_null(cond); - replace_pointer_airth(cond); - replace_typecast(cond); - } + adapt_to_slhv(cond); + replace_nondet(cond); dereference(cond, dereferencet::READ); replace_dynamic_allocation(cond); @@ -440,10 +437,8 @@ void goto_symext::symex_assert() expr2tc tmp = instruction.guard; if (options.get_bool_option("z3-slhv")) - { - replace_null(tmp); - replace_typecast(tmp); - } + adapt_to_slhv(tmp); + replace_nondet(tmp); intrinsic_races_check_dereference(tmp); diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index c4bd8acd..457c978b 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -7,12 +7,9 @@ void goto_symext::symex_other(const expr2tc code) { expr2tc code2 = code; + if (options.get_bool_option("z3-slhv")) - { - replace_null(code2); - replace_pointer_airth(code2); - replace_typecast(code2); - } + adapt_to_slhv(code2); if (is_code_expression2t(code2)) { @@ -55,8 +52,10 @@ void goto_symext::symex_decl(const expr2tc code) { assert(is_code_decl2t(code)); expr2tc code2 = code; + if (options.get_bool_option("z3-slhv")) replace_null(code2); + replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::READ); diff --git a/src/irep2/irep2.h b/src/irep2/irep2.h index bdc232c5..087c9be5 100644 --- a/src/irep2/irep2.h +++ b/src/irep2/irep2.h @@ -41,7 +41,8 @@ #define ESBMC_LIST_OF_EXPRS \ BOOST_PP_LIST_CONS(constant_int, \ BOOST_PP_LIST_CONS(constant_intloc, \ - BOOST_PP_LIST_CONS(constant_intheap, \ + BOOST_PP_LIST_CONS(constant_intheap, \ + BOOST_PP_LIST_CONS(constant_heap_region, \ BOOST_PP_LIST_CONS(constant_fixedbv, \ BOOST_PP_LIST_CONS(constant_floatbv, \ BOOST_PP_LIST_CONS(constant_bool, \ @@ -154,7 +155,7 @@ BOOST_PP_LIST_CONS(signbit, \ BOOST_PP_LIST_CONS(concat, \ BOOST_PP_LIST_CONS(extract, \ - BOOST_PP_LIST_NIL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + BOOST_PP_LIST_NIL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) #define ESBMC_LIST_OF_TYPES \ BOOST_PP_LIST_CONS(bool, \ diff --git a/src/irep2/irep2_expr.cpp b/src/irep2/irep2_expr.cpp index fea8e4df..b940f6ce 100644 --- a/src/irep2/irep2_expr.cpp +++ b/src/irep2/irep2_expr.cpp @@ -13,6 +13,7 @@ static const char *expr_names[] = { "constant_int", "constant_intloc", "constant_intheap", + "constant_heap_region", "constant_fixedbv", "constant_floatbv", "constant_bool", diff --git a/src/irep2/irep2_expr.h b/src/irep2/irep2_expr.h index efa48dd2..c941832c 100644 --- a/src/irep2/irep2_expr.h +++ b/src/irep2/irep2_expr.h @@ -1659,6 +1659,7 @@ class extract_data : public expr2t irep_typedefs(constant_int, constant_int_data); irep_typedefs(constant_intloc, constant_intloc_data); irep_typedefs(constant_intheap, constant_intheap_data); +irep_typedefs(constant_heap_region, constant_datatype_data); irep_typedefs(constant_fixedbv, constant_fixedbv_data); irep_typedefs(constant_floatbv, constant_floatbv_data); irep_typedefs(constant_struct, constant_datatype_data); @@ -1799,6 +1800,8 @@ class constant_int2t : public constant_int_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +/* ================================ SLHV ================================ */ + class constant_intloc2t : public constant_intloc_expr_methods { public: @@ -1827,6 +1830,23 @@ class constant_intheap2t : public constant_intheap_expr_methods static std::string field_names[esbmct::num_type_fields]; }; +class constant_heap_region2t : public constant_heap_region_expr_methods +{ +public: + constant_heap_region2t( + const type2tc &type, + const std::vector &members) + : constant_heap_region_expr_methods( + type, constant_heap_region_id, members) + { + } + constant_heap_region2t(const constant_heap_region2t &ref) = default; + + static std::string field_names[esbmct::num_type_fields]; +}; + +/* ================================ SLHV ================================ */ + /** Constant fixedbv class. Records a fixed-width number in what I assume * to be mantissa/exponent form, but which is described throughout CBMC code * as fraction/integer parts. Stored in a fixedbvt. diff --git a/src/irep2/templates/irep2_templates.cpp b/src/irep2/templates/irep2_templates.cpp index e87554e2..8f889522 100644 --- a/src/irep2/templates/irep2_templates.cpp +++ b/src/irep2/templates/irep2_templates.cpp @@ -46,6 +46,8 @@ std::string constant_intloc2t::field_names[esbmct::num_type_fields] = {"value", "is_nil", "", "", ""}; std::string constant_intheap2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; +std::string constant_heap_region2t::field_names[esbmct::num_type_fields] = + {"members", "", "", "", ""}; std::string constant_fixedbv2t::field_names[esbmct::num_type_fields] = {"value", "", "", "", ""}; std::string constant_floatbv2t::field_names[esbmct::num_type_fields] = diff --git a/src/irep2/templates/irep2_templates_expr_data.cpp b/src/irep2/templates/irep2_templates_expr_data.cpp index 17f46c06..177fb6d2 100644 --- a/src/irep2/templates/irep2_templates_expr_data.cpp +++ b/src/irep2/templates/irep2_templates_expr_data.cpp @@ -1,8 +1,6 @@ #include expr_typedefs1(constant_int, constant_int_data); -expr_typedefs2(constant_intloc, constant_intloc_data); -expr_typedefs1(constant_intheap, constant_intheap_data); expr_typedefs1(constant_fixedbv, constant_fixedbv_data); expr_typedefs1(constant_floatbv, constant_floatbv_data); expr_typedefs1(constant_struct, constant_datatype_data); @@ -57,6 +55,9 @@ expr_typedefs1(code_cpp_throw_decl_end, code_cpp_throw_decl_data); expr_typedefs3(extract, extract_data); +expr_typedefs2(constant_intloc, constant_intloc_data); +expr_typedefs1(constant_intheap, constant_intheap_data); +expr_typedefs1(constant_heap_region, constant_datatype_data); expr_typedefs1(disjh, disjh_data); expr_typedefs2(points_to, points_to_data); expr_typedefs1(uplus, uplus_data); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 29d53b28..31601800 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -1266,6 +1266,19 @@ void value_sett::assign( // Heap varialbes perform as array variable. // We only update its fields that are pointers + if (is_constant_heap_region2t(rhs)) + { + const constant_heap_region2t &const_reg = to_constant_heap_region2t(rhs); + for (unsigned int i = 0; i < const_reg.datatype_members.size(); i++) + { + expr2tc rhs_field = const_reg.datatype_members[i]; + expr2tc lhs_field = + field_of2tc(rhs_field->type, lhs, gen_ulong(i)); + + assign(lhs_field, rhs_field, false); + } + } + if ((is_heap_update2t(rhs) || is_symbol2t(rhs)) && to_intheap_type(rhs->type).is_region) { diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index ea110590..6ad91d86 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -240,8 +240,9 @@ smt_astt z3_slhv_convt::convert_ast(const expr2tc &expr) smt_astt a; switch (expr->expr_id) { - case expr2t::constant_intheap_id: case expr2t::constant_intloc_id: + case expr2t::constant_intheap_id: + case expr2t::constant_heap_region_id: case expr2t::disjh_id: case expr2t::heap_region_id: case expr2t::location_of_id: @@ -396,10 +397,25 @@ z3_slhv_convt::convert_slhv_opts( { switch (expr->expr_id) { - case expr2t::constant_intheap_id: - return mk_emp(); case expr2t::constant_intloc_id: return mk_nil(); + case expr2t::constant_intheap_id: + return mk_emp(); + case expr2t::constant_heap_region_id: + { + const constant_heap_region2t &const_reg = to_constant_heap_region2t(expr); + const intheap_type2t &_type = to_intheap_type(expr->type); + smt_astt base_loc = convert_ast(_type.location); + + std::vector pt_vec; + for (unsigned int i = 0; i < const_reg.datatype_members.size(); i++) + { + smt_astt loc = + i == 0 ? base_loc : mk_locadd(base_loc, mk_smt_int(BigInt(i))); + pt_vec.push_back(mk_pt(loc, args[i])); + } + return pt_vec.size() == 1 ? pt_vec[0] : mk_uplus(pt_vec); + } case expr2t::disjh_id: { const disjh2t &disj = to_disjh2t(expr); @@ -423,7 +439,7 @@ z3_slhv_convt::convert_slhv_opts( std::vector pt_vec; if (_type.is_aligned) { - for (unsigned i = 0; i < _type.field_types.size(); i++) + for (unsigned int i = 0; i < _type.field_types.size(); i++) { smt_astt loc = i == 0 ? base_loc : mk_locadd(base_loc, mk_smt_int(BigInt(i))); smt_sortt sort = @@ -660,11 +676,16 @@ smt_astt z3_slhv_convt::convert_slhv_typecast(const expr2tc &expr) const typecast2t &cast = to_typecast2t(expr); - smt_astt a = convert_ast(cast.from); - - if ((is_pointer_type(cast.from->type) || is_intloc_type(cast.from->type)) && + smt_astt a; + if ((is_pointer_type(cast.from->type) && is_intloc_type(cast.type)) || + (is_pointer_type(cast.type) && is_intloc_type(cast.from->type))) + a = convert_ast(cast.from); + else if ( + (is_pointer_type(cast.from->type) || is_intloc_type(cast.from->type)) && (is_signedbv_type(cast.type) || is_unsignedbv_type(cast.type))) - return mk_loc2int(a); + return a = mk_loc2int(convert_ast(cast.from)); + else + a = convert_typecast(expr); return a; } diff --git a/src/util/base_type.cpp b/src/util/base_type.cpp index cb1e0371..f6e07a3c 100644 --- a/src/util/base_type.cpp +++ b/src/util/base_type.cpp @@ -96,7 +96,11 @@ bool base_type_eqt::base_type_eq_rec(const type2tc &type1, const type2tc &type2) if (is_struct_type(type1) && is_intheap_type(type2)) return true; - + + if (is_pointer_type(type1) && is_intloc_type(type2) || + is_intloc_type(type1) && is_pointer_type(type2)) + return true; + // loop avoidance if (is_symbol_type(type1) && is_symbol_type(type2)) { diff --git a/src/util/migrate.cpp b/src/util/migrate.cpp index 2d542601..90412569 100644 --- a/src/util/migrate.cpp +++ b/src/util/migrate.cpp @@ -2047,6 +2047,15 @@ exprt migrate_expr_back(const expr2tc &ref) constant_exprt theexpr(thetype); return theexpr; } + case expr2t::constant_heap_region_id: + { + const constant_heap_region2t &ref2 = to_constant_heap_region2t(ref); + typet thetype = migrate_type_back(ref->type); + exprt theregion("constant_heap_region", thetype); + for (auto const &it : ref2.datatype_members) + theregion.operands().push_back(migrate_expr_back(it)); + return theregion; + } case expr2t::constant_fixedbv_id: { return to_constant_fixedbv2t(ref).value.to_expr(); From 65bb0897e7ffcaaeccac84828fb0ad8e960e3491 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 1 Oct 2024 15:58:41 +0800 Subject: [PATCH 117/126] support location_of a stack variable --- src/goto-symex/goto_symex_state.cpp | 6 +++--- src/pointer-analysis/dereference.cpp | 5 ++--- src/pointer-analysis/value_set.cpp | 3 +-- src/solvers/z3-slhv/z3_slhv_conv.cpp | 6 +++--- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 2d696bdc..1b8c5321 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -281,10 +281,10 @@ void goto_symex_statet::rename(expr2tc &expr) else if (is_location_of2t(expr)) { location_of2t &locof = to_location_of2t(expr); - if (is_pointer_type(locof.source_heap)) - rename_address(locof.source_heap); - else + if (is_intheap_type(locof.source_heap)) rename(locof.source_heap); + else + rename_address(locof.source_heap); rename_type(locof.source_heap); } else diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp index 3702bd0f..d0da0a5a 100644 --- a/src/pointer-analysis/dereference.cpp +++ b/src/pointer-analysis/dereference.cpp @@ -852,9 +852,8 @@ expr2tc dereferencet::build_reference_to( value = object; guardt tmp_guard(guard); - if (!is_intheap_type(value) && - !is_pointer_type(value) && - !is_intloc_type(value)) + if (!is_intheap_type(value) && !is_intloc_type(value) && + !is_scalar_type(value)) { log_error("Do not support this tpye"); value->dump(); diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 31601800..93fb4b60 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -1278,8 +1278,7 @@ void value_sett::assign( assign(lhs_field, rhs_field, false); } } - - if ((is_heap_update2t(rhs) || is_symbol2t(rhs)) + else if ((is_heap_update2t(rhs) || is_symbol2t(rhs)) && to_intheap_type(rhs->type).is_region) { unsigned int _field = -1; diff --git a/src/solvers/z3-slhv/z3_slhv_conv.cpp b/src/solvers/z3-slhv/z3_slhv_conv.cpp index 6ad91d86..c8e96426 100644 --- a/src/solvers/z3-slhv/z3_slhv_conv.cpp +++ b/src/solvers/z3-slhv/z3_slhv_conv.cpp @@ -478,8 +478,8 @@ z3_slhv_convt::convert_slhv_opts( loc = convert_ast(_type.location); } else if (is_symbol2t(locof.source_heap) && - (is_pointer_type(locof.source_heap) || - is_intloc_type(locof.source_heap))) + (is_intloc_type(locof.source_heap) || + is_scalar_type(locof.source_heap))) { std::string loc_name = to_symbol2t(locof.source_heap).get_symbol_name() + std::string("_LOC_"); @@ -710,7 +710,7 @@ smt_astt z3_slhv_convt::project(const expr2tc &expr) abort(); } else if (is_location_of2t(expr)) - return this->project(to_location_of2t(expr).source_heap); + return convert_ast(expr); else if (is_field_of2t(expr)) return convert_ast(expr); else if (is_typecast2t(expr)) From 8af081d0e520f5d19ea194c38e7a02503111a043 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 1 Oct 2024 17:47:13 +0800 Subject: [PATCH 118/126] fix renaming location_of --- src/esbmc/bmc.cpp | 2 +- src/goto-symex/goto_symex_state.cpp | 5 +-- src/goto-symex/slice.cpp | 52 ++++++++++++++++++++--------- src/goto-symex/slice.h | 12 ------- src/goto-symex/symex_assign.cpp | 2 +- 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/esbmc/bmc.cpp b/src/esbmc/bmc.cpp index 2648c4f7..a3af2a07 100644 --- a/src/esbmc/bmc.cpp +++ b/src/esbmc/bmc.cpp @@ -733,7 +733,7 @@ smt_convt::resultt bmct::multi_property_check( &is_fail_fast, &fail_fast_limit, &fail_fast_cnt](const size_t &i) { - + //"multi-fail-fast n": stop after first n SATs found. if (is_fail_fast && fail_fast_cnt >= fail_fast_limit) return; diff --git a/src/goto-symex/goto_symex_state.cpp b/src/goto-symex/goto_symex_state.cpp index 1b8c5321..94c86e59 100644 --- a/src/goto-symex/goto_symex_state.cpp +++ b/src/goto-symex/goto_symex_state.cpp @@ -281,10 +281,7 @@ void goto_symex_statet::rename(expr2tc &expr) else if (is_location_of2t(expr)) { location_of2t &locof = to_location_of2t(expr); - if (is_intheap_type(locof.source_heap)) - rename(locof.source_heap); - else - rename_address(locof.source_heap); + rename_address(locof.source_heap); rename_type(locof.source_heap); } else diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 0f96e3f8..555b0cef 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -10,10 +10,21 @@ static bool no_slice(const symbol2t &sym) template bool symex_slicet::get_symbols(const expr2tc &expr) { - bool res = false; if (is_heap_region2t(expr)) return false; + if (is_location_of2t(expr)) + { + const location_of2t &locof = to_location_of2t(expr); + if (is_intheap_type(locof.source_heap)) + return + get_symbols( + to_intheap_type(locof.source_heap->type).location); + else + return false; + } + + bool res = false; // Recursively look if any of the operands has a inner symbol expr->foreach_operand([this, &res](const expr2tc &e) { if (!is_nil_expr(e)) @@ -43,7 +54,31 @@ void symex_slicet::run_on_assume(symex_target_equationt::SSA_stept &SSA_step) if (is_disjh2t(SSA_step.cond)) { disjh2t &disj = to_disjh2t(SSA_step.cond); - if (!get_symbols(disj.source_heap)) + + bool is_sliced = false; + if (!get_symbols(disj.source_heap) && + !get_symbols( + to_intheap_type(disj.source_heap->type).location)) + is_sliced = true; + else + { + get_symbols(disj.source_heap); + int cnt = 0; + for (unsigned int i = 0; i < disj.other_heaps.size(); i++) + { + const expr2tc ® = disj.other_heaps[i]; + if (get_symbols(reg) || + get_symbols(to_intheap_type(reg->type).location)) + { + cnt++; + get_symbols(reg); + disj.is_sliced[i] = false; + } + } + is_sliced |= (cnt == 0); + } + + if (is_sliced) { SSA_step.ignore = true; ++sliced; @@ -252,17 +287,4 @@ expr2tc symex_slicet::get_nondet_symbol(const expr2tc &expr) default: return expr2tc(); } -} - -void symex_slicet::run_on_disjhs(symex_target_equationt::SSA_stepst &eq) -{ - for (auto &step : eq) - { - if (step.ignore) continue; - if (!step.is_assume()) continue; - if (!is_disjh2t(step.cond)) continue; - disjh2t &disj = to_disjh2t(step.cond); - for (unsigned int i = 0; i < disj.other_heaps.size(); i++) - disj.is_sliced[i] = !get_symbols(disj.other_heaps[i]); - } } \ No newline at end of file diff --git a/src/goto-symex/slice.h b/src/goto-symex/slice.h index a75ad111..04c5b423 100644 --- a/src/goto-symex/slice.h +++ b/src/goto-symex/slice.h @@ -104,9 +104,6 @@ class symex_slicet : public slicer run_on_step(step); } - // added needed heap vars for their disjointness - run_on_disjhs(eq); - fine_timet algorithm_stop = current_time(); log_status( "Slicing time: {}s (removed {} assignments)", @@ -226,15 +223,6 @@ class symex_slicet : public slicer * @param SSA_step an renumber step */ void run_on_renumber(symex_target_equationt::SSA_stept &SSA_step) override; - -private: - - /** - * @brief Add disjointness of connected heap variables - * - * @param eq - */ - void run_on_disjhs(symex_target_equationt::SSA_stepst &eq); }; #endif diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 84a59f9e..89131b35 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -907,7 +907,7 @@ void goto_symext::symex_assign_fieldof( symex_assign_rec(heap_region, full_lhs, update_heap, full_rhs, guard, hidden); - symex_disj_heaps(heap_region); + // symex_disj_heaps(heap_region); } void goto_symext::replace_nondet(expr2tc &expr) From 9c3a04456181fe481c9b2cff0a45acb185ca0cd7 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 3 Oct 2024 12:05:22 +0800 Subject: [PATCH 119/126] fix disjointness --- src/goto-symex/builtin_functions.cpp | 7 ++++--- src/goto-symex/slice.cpp | 30 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/goto-symex/builtin_functions.cpp b/src/goto-symex/builtin_functions.cpp index 2e1847a4..a142e6f2 100644 --- a/src/goto-symex/builtin_functions.cpp +++ b/src/goto-symex/builtin_functions.cpp @@ -1938,9 +1938,10 @@ void goto_symext::symex_disj_heaps(const expr2tc &heap) expr2tc l0_heap = heap; cur_state->get_original_name(l0_heap); expr2tc disj = disjh2tc(l0_heap); - - for (auto const &it : cur_state->top().local_heap_regions) - to_disjh2t(disj).do_disjh(it); + + for (auto const& frame : cur_state->call_stack) + for (auto const &it : frame.local_heap_regions) + to_disjh2t(disj).do_disjh(it); for (auto const &it : dynamic_memory) to_disjh2t(disj).do_disjh(it.obj); diff --git a/src/goto-symex/slice.cpp b/src/goto-symex/slice.cpp index 555b0cef..8e10b418 100644 --- a/src/goto-symex/slice.cpp +++ b/src/goto-symex/slice.cpp @@ -16,7 +16,12 @@ bool symex_slicet::get_symbols(const expr2tc &expr) if (is_location_of2t(expr)) { const location_of2t &locof = to_location_of2t(expr); - if (is_intheap_type(locof.source_heap)) + if (is_field_of2t(locof.source_heap)) + return + get_symbols(location_of2tc( + to_field_of2t(locof.source_heap).source_heap + )); + else if (is_intheap_type(locof.source_heap)) return get_symbols( to_intheap_type(locof.source_heap->type).location); @@ -119,6 +124,29 @@ void symex_slicet::run_on_assignment(symex_target_equationt::SSA_stept &SSA_step assert(is_symbol2t(SSA_step.lhs)); // TODO: create an option to ignore nondet symbols (test case generation) + if (is_intheap_type(SSA_step.lhs) && + !is_nil_expr(to_intheap_type(SSA_step.lhs->type).location)) + { + const symbol2t &sym = to_symbol2t(SSA_step.lhs); + const intheap_type2t &ty = to_intheap_type(SSA_step.lhs->type); + + // If we access the location of a heap region, we add the + // first variable with ;l2_num = 1' to build the disjointness. + if (sym.level2_num == 1 && get_symbols(ty.location) || + get_symbols(SSA_step.lhs)) + { + get_symbols(SSA_step.guard); + get_symbols(SSA_step.cond); + } + else + { + SSA_step.ignore = true; + ++sliced; + } + return; + } + + if (!get_symbols(SSA_step.lhs)) { // Should we add nondet to the dependency list (mostly for test cases)? From cc7efe6cae6fde92c5edd34f7323fee8ad1704cb Mon Sep 17 00:00:00 2001 From: zhuyt Date: Thu, 3 Oct 2024 13:20:26 +0800 Subject: [PATCH 120/126] support struct assignment --- src/goto-symex/symex_assign.cpp | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/goto-symex/symex_assign.cpp b/src/goto-symex/symex_assign.cpp index 89131b35..efbc7122 100644 --- a/src/goto-symex/symex_assign.cpp +++ b/src/goto-symex/symex_assign.cpp @@ -302,6 +302,44 @@ void goto_symext::symex_assign_rec( { if (is_symbol2t(lhs)) { + if (is_intheap_type(lhs) && is_intheap_type(rhs) && is_symbol2t(rhs)) + { + const intheap_type2t &lhs_ty = to_intheap_type(lhs->type); + const intheap_type2t &rhs_ty = to_intheap_type(rhs->type); + if (lhs_ty.is_alloced) + { + if (!rhs_ty.is_alloced || + lhs_ty.field_types.size() != rhs_ty.field_types.size()) + { + log_error("Wrong assignment for heap varaible"); + rhs->dump(); + abort(); + } + + std::string lhs_loc = to_symbol2t(lhs_ty.location).get_symbol_name(); + std::string rhs_loc = to_symbol2t(rhs_ty.location).get_symbol_name(); + + // Copy fields of struct/... + if (lhs_loc != rhs_loc) + { + for (unsigned int i = 0; i < lhs_ty.field_types.size(); i++) + { + if (lhs_ty.field_types[i] != rhs_ty.field_types[i]) + { + log_status("Dismatch type info"); + abort(); + } + + expr2tc lhs_field = field_of2tc(lhs_ty.field_types[i], lhs, gen_ulong(i)); + expr2tc rhs_field = field_of2tc(lhs_ty.field_types[i], rhs, gen_ulong(i)); + + symex_assign_rec(lhs_field, lhs, rhs_field, rhs, guard, false); + } + return; + } + } + } + log_debug("SLHV", " xxxxxxxxx symex assign symbol xxxxxxxxx "); symex_assign_symbol(lhs, full_lhs, rhs, full_rhs, guard, hidden); log_debug("SLHV", " xxxxxxxxx symex assign symbol xxxxxxxxx "); From 62a03d1ef9f5bd5788fbfbe2bc4f21a68aafce5b Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 4 Oct 2024 14:37:52 +0800 Subject: [PATCH 121/126] update x.py --- scripts/x.py | 112 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 631aacdd..0cfd4ca7 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -69,7 +69,10 @@ def analysis_result(log): flag = "--- Result ---" assert_results = [] + formulas = 0 total_time = 0 + mi_time = float(901) + mx_time = float(0) is_collecting = False with open(log) as log_file: info_buf = [] @@ -85,12 +88,16 @@ def analysis_result(log): info_buf.clear() # collect time for each assertion - total_time += float(one_res["Time"]) + time = float(one_res["Time"]) + total_time += time + mi_time = min(mi_time, time) + mx_time = max(mx_time, time) + formulas += 1 if not is_collecting: continue info_buf.append(line.strip()) - return (assert_results, total_time) + return (assert_results, formulas, total_time, mi_time, mx_time) def run_on(cprog, extra_args): assert(os.path.exists(cprog)) @@ -108,7 +115,8 @@ def run_on(cprog, extra_args): "--show-vcc", "--output", vcc_log, - "--multi-property" + "--multi-property", + # "--no-slice" ] if "--esbmc" in extra_args: @@ -120,18 +128,22 @@ def run_on(cprog, extra_args): args.append("--verbosity SLHV:8") if "--std-out" not in extra_args: - args += [">", t_log] + args += [">", t_log, "2>&1"] cmd = " ".join(args) print(f"Command: {cmd}") os.system(cmd) - (result, total_time) = analysis_result(t_log) + (result, formulas, total_time, mi_time, mx_time) = analysis_result(t_log) for d in result: res = [k + ": " + v for k, v in list(d.items())] print("{:<10} {:<12} {:<25} {:<15} {:<10}".format(*res)) - print(f"Total time: {round(total_time, 3)}") + print(f"Formulas: {formulas}, \ + Total time: {round(total_time, 3)}, \ + Average time: {round(total_time / formulas, 3)} \ + Min time: {round(mi_time, 3)}, \ + Max time: {round(mx_time, 3)}") return result @@ -156,25 +168,101 @@ def generate_csv(results): header = ["File", "Line", "Column", "Property", "Result", "Time"] w = csv.DictWriter(f, header) w.writeheader() + formulas = [0, 0] + total_time = [0.0, 0.0] + mi_time = [-1.0, -1.0] + mx_time = [-1.0, -1.0] for cprog, assert_results in results.items(): is_head = True - total_time = 0 + i_formulas = [0, 0] + i_total_time = [0.0, 0.0] + i_mi_time = [-1.0, -1.0] + i_mx_time = [-1.0, -1.0] for assert_result in assert_results: new_row = {'File': cprog if is_head else ''} is_head = False - total_time += float(assert_result["Time"]) + + time = float(assert_result["Time"]) + r = 0 if assert_result["Result"] == "sat" else 1 + i_formulas[r] += 1 + i_total_time[r] += time + + if i_mi_time[r] == -1.0: + i_mi_time[r] = time + else: + i_mi_time[r] = min(i_mi_time[r], time) + + if i_mx_time[r] == -1.0: + i_mx_time[r] = time + else: + i_mx_time[r] = max(i_mx_time[r], time) + + formulas[r] += 1 + total_time[r] += time + + if mi_time[r] == -1.0: + mi_time[r] = time + else: + mi_time[r] = min(mi_time[r], time) + + if mx_time[r] == -1.0: + mx_time[r] = time + else: + mx_time[r] = max(mx_time[r], time) + new_row.update(assert_result) w.writerow(new_row) + + i_sat_ave = round(i_total_time[0] / i_formulas[0], 3) if i_formulas[0] != 0 else '-' + i_unsat_ave = round(i_total_time[1] / i_formulas[1], 3) + + mit = ['-', '-'] + mxt = ['-', '-'] + + if i_mi_time[0] != -1.0: mit[0] = round(i_mi_time[0], 3) + if i_mi_time[1] != -1.0: mit[1] = round(i_mi_time[1], 3) + if i_mx_time[0] != -1.0: mxt[0] = round(i_mx_time[0], 3) + if i_mx_time[1] != -1.0: mxt[1] = round(i_mx_time[1], 3) + new_row = { + "File": f'Formulas(sat/unsat): {i_formulas[0]}/{i_formulas[1]}', + "Line": f'Average(sat/unsat): {i_sat_ave}/{i_unsat_ave}', + "Column": f'Min_time(sat/unsat): {mit[0]}/{mit[1]}', + "Property": f'Max_time(sat/unsat): {mxt[0]}/{mxt[1]}', + "Result": '', + "Time": '', + } + w.writerow(new_row) + + new_row = { "File": '', "Line": '', "Column": '', "Property": '', - "Result": 'Totaltime', - "Time": total_time - } - w.writerow(new_row) + "Result": '', + "Time": '', + } + w.writerow(new_row) + sat_ave = round(total_time[0] / formulas[0], 3) + unsat_ave = round(total_time[1] / formulas[1], 3) + + mit = ['-', '-'] + mxt = ['-', '-'] + + if mi_time[0] != -1.0: mit[0] = round(mi_time[0], 3) + if mi_time[1] != -1.0: mit[1] = round(mi_time[1], 3) + if mx_time[0] != -1.0: mxt[0] = round(mx_time[0], 3) + if mx_time[1] != -1.0: mxt[1] = round(mx_time[1], 3) + new_row = { + "File": f'Formulas(sat/unsat): {formulas[0]}/{formulas[1]}', + "Line": f'Average(sat/unsat): {sat_ave}/{unsat_ave}', + "Column": f'Min_time(sat/unsat): {mit[0]}/{mit[1]}', + "Property": f'Max_time(sat/unsat): {mxt[0]}/{mxt[1]}', + "Result": '', + "Time": '', + } + w.writerow(new_row) def run_expriment_on(benchmark_root, extra_args): assert(os.path.exists(benchmark_root)) From 347852a3a0428765b8770bbcce78514ce2eb7e21 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 4 Oct 2024 21:22:00 +0800 Subject: [PATCH 122/126] add statistic of atomic heap terms --- scripts/x.py | 166 ++++++++++++++++++++++++++++----------------------- 1 file changed, 90 insertions(+), 76 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 0cfd4ca7..3db8ed39 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -3,6 +3,7 @@ import os import sys import csv +import matplotlib.pyplot as plt esbmc_slhv_root = "./esbmc" esbmc_slhv_build = os.path.join(esbmc_slhv_root, "build") @@ -15,6 +16,8 @@ vcc_log = os.path.join(output_root, "vcc.log") csv_file = os.path.join(output_root, "results.csv") +aht_plt_file = os.path.join(output_root, "aht_fig.svg") + def compile(): os.system(f"cd {esbmc_slhv_build } && cmake --build .") @@ -43,7 +46,7 @@ def help(): for arg in args.items(): print(" {:<35} {:<50}".format(*arg)) -def collect_one_assert(info): +def collect_one_assert(info, aht): assert(len(info) == 3) res = {} @@ -55,9 +58,16 @@ def collect_one_assert(info): res["Line"] = location[4] res["Column"] = location[6] - # Property & Result & Time + + + # Property prt = info[2].split(" ") res["Property"] = prt[1] + + # Atomic heap term + res["Aht"] = aht + + # Result & Time res["Result"] = prt[3] res["Time"] = prt[5].replace('s', '') @@ -67,37 +77,34 @@ def analysis_result(log): assert(os.path.exists(log)) flag = "--- Result ---" - + assert_results = [] - formulas = 0 - total_time = 0 - mi_time = float(901) - mx_time = float(0) + total_time = 0.0 is_collecting = False with open(log) as log_file: info_buf = [] + aht = '-' for line in log_file: + + if "Number of aht:" in line: + aht = int(line.strip().split(' ')[3]) + if line.find(flag) != -1: if not is_collecting: is_collecting = True continue else: is_collecting = False - one_res = collect_one_assert(info_buf) + one_res = collect_one_assert(info_buf, aht) assert_results.append(one_res) + aht = '-' info_buf.clear() - - # collect time for each assertion - time = float(one_res["Time"]) - total_time += time - mi_time = min(mi_time, time) - mx_time = max(mx_time, time) - formulas += 1 + total_time += float(one_res["Time"]) if not is_collecting: continue info_buf.append(line.strip()) - return (assert_results, formulas, total_time, mi_time, mx_time) + return (assert_results, total_time) def run_on(cprog, extra_args): assert(os.path.exists(cprog)) @@ -134,16 +141,12 @@ def run_on(cprog, extra_args): print(f"Command: {cmd}") os.system(cmd) - (result, formulas, total_time, mi_time, mx_time) = analysis_result(t_log) + (result, total_time) = analysis_result(t_log) for d in result: - res = [k + ": " + v for k, v in list(d.items())] - print("{:<10} {:<12} {:<25} {:<15} {:<10}".format(*res)) + res = [k + ": " + str(v) for k, v in list(d.items())] + print("{:<10} {:<12} {:<25} {:<10} {:<15} {:<10}".format(*res)) - print(f"Formulas: {formulas}, \ - Total time: {round(total_time, 3)}, \ - Average time: {round(total_time / formulas, 3)} \ - Min time: {round(mi_time, 3)}, \ - Max time: {round(mx_time, 3)}") + print(f"Total time: {round(total_time, 3)}") return result @@ -160,77 +163,69 @@ def collect_results(cprog): os.system(f"cp {vcc_log} {vcc_path}") print(f"Result for {cprog}: {log_path} {vcc_path}") - def generate_csv(results): print(f"Write to {csv_file}") with open(csv_file, "w") as f: - header = ["File", "Line", "Column", "Property", "Result", "Time"] + header = ["File", "Line", "Column", "Property", "Aht", "Result", "Time"] w = csv.DictWriter(f, header) w.writeheader() formulas = [0, 0] total_time = [0.0, 0.0] - mi_time = [-1.0, -1.0] - mx_time = [-1.0, -1.0] + mi_time = ['-', '-'] + mx_time = ['-', '-'] + + formulas_with_aht = 0 + total_ahts = 0 + mi_aht = '-' + mx_aht = '-' for cprog, assert_results in results.items(): is_head = True - i_formulas = [0, 0] - i_total_time = [0.0, 0.0] - i_mi_time = [-1.0, -1.0] - i_mx_time = [-1.0, -1.0] + i_total_time = 0.0 for assert_result in assert_results: new_row = {'File': cprog if is_head else ''} is_head = False + new_row.update(assert_result) + w.writerow(new_row) time = float(assert_result["Time"]) + i_total_time += time r = 0 if assert_result["Result"] == "sat" else 1 - i_formulas[r] += 1 - i_total_time[r] += time - - if i_mi_time[r] == -1.0: - i_mi_time[r] = time - else: - i_mi_time[r] = min(i_mi_time[r], time) - - if i_mx_time[r] == -1.0: - i_mx_time[r] = time - else: - i_mx_time[r] = max(i_mx_time[r], time) formulas[r] += 1 total_time[r] += time - if mi_time[r] == -1.0: + time = round(time, 3) + if mi_time[r] == '-': mi_time[r] = time else: mi_time[r] = min(mi_time[r], time) - if mx_time[r] == -1.0: + if mx_time[r] == '-': mx_time[r] = time else: mx_time[r] = max(mx_time[r], time) - new_row.update(assert_result) - w.writerow(new_row) - - i_sat_ave = round(i_total_time[0] / i_formulas[0], 3) if i_formulas[0] != 0 else '-' - i_unsat_ave = round(i_total_time[1] / i_formulas[1], 3) - - mit = ['-', '-'] - mxt = ['-', '-'] + # Aht + if str(assert_result["Aht"]) != '-': + aht = assert_result["Aht"] + formulas_with_aht += 1 + total_ahts += aht + + if mi_aht == '-': mi_aht = aht + else: mi_aht = min(mi_aht, aht) - if i_mi_time[0] != -1.0: mit[0] = round(i_mi_time[0], 3) - if i_mi_time[1] != -1.0: mit[1] = round(i_mi_time[1], 3) - if i_mx_time[0] != -1.0: mxt[0] = round(i_mx_time[0], 3) - if i_mx_time[1] != -1.0: mxt[1] = round(i_mx_time[1], 3) + if mx_aht == '-': mx_aht = aht + else: mx_aht = max(mx_aht, aht) new_row = { - "File": f'Formulas(sat/unsat): {i_formulas[0]}/{i_formulas[1]}', - "Line": f'Average(sat/unsat): {i_sat_ave}/{i_unsat_ave}', - "Column": f'Min_time(sat/unsat): {mit[0]}/{mit[1]}', - "Property": f'Max_time(sat/unsat): {mxt[0]}/{mxt[1]}', - "Result": '', - "Time": '', + "File": '', + "Line": '', + "Column": '', + "Property": '', + "Aht": '', + "Result": 'Totaltime:', + "Time": f'{round(i_total_time, 3)}', } w.writerow(new_row) @@ -239,6 +234,7 @@ def generate_csv(results): "Line": '', "Column": '', "Property": '', + "Aht": '', "Result": '', "Time": '', } @@ -247,23 +243,39 @@ def generate_csv(results): sat_ave = round(total_time[0] / formulas[0], 3) unsat_ave = round(total_time[1] / formulas[1], 3) - mit = ['-', '-'] - mxt = ['-', '-'] - - if mi_time[0] != -1.0: mit[0] = round(mi_time[0], 3) - if mi_time[1] != -1.0: mit[1] = round(mi_time[1], 3) - if mx_time[0] != -1.0: mxt[0] = round(mx_time[0], 3) - if mx_time[1] != -1.0: mxt[1] = round(mx_time[1], 3) new_row = { "File": f'Formulas(sat/unsat): {formulas[0]}/{formulas[1]}', "Line": f'Average(sat/unsat): {sat_ave}/{unsat_ave}', - "Column": f'Min_time(sat/unsat): {mit[0]}/{mit[1]}', - "Property": f'Max_time(sat/unsat): {mxt[0]}/{mxt[1]}', - "Result": '', - "Time": '', + "Column": f'Min_time(sat/unsat): {mi_time[0]}/{mi_time[1]}', + "Property": f'Max_time(sat/unsat): {mx_time[0]}/{mx_time[1]}', + "Aht": f'Formulas_with_aht: {formulas_with_aht}', + "Result": f'Average_aht: {total_ahts // formulas_with_aht}', + "Time": f'Min/Max(aht): {mi_aht}/{mx_aht}', } w.writerow(new_row) +def generate_aht_plt(results): + x = [] + y = [] + for _, assert_results in results.items(): + for assert_result in assert_results: + if str(assert_result["Aht"]) == '-': continue + + x.append(int(assert_result["Aht"])) + y.append(float(assert_result["Time"])) + + plt.scatter(x, y, color="blue") + xticks = [10, 20, 30, 40, 50, 60] + plt.xticks(xticks) + yticks = [5, 10, 15, 20 ,25] + plt.yticks=(yticks) + plt.xlabel("number of atomic heap terms") + plt.ylabel("solving time(s)") + + plt.show() + plt.savefig(aht_plt_file) + plt.clf() + def run_expriment_on(benchmark_root, extra_args): assert(os.path.exists(benchmark_root)) @@ -280,7 +292,9 @@ def run_expriment_on(benchmark_root, extra_args): results[cprog] = run_on(cprog_path, extra_args) collect_results(cprog) - generate_csv(results) + generate_csv(results) + generate_aht_plt(results) + if __name__ == '__main__': if not os.path.exists(output_root): From a4a253313619dbf88d400bcc350182d6411c1879 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Sun, 6 Oct 2024 12:53:29 +0800 Subject: [PATCH 123/126] save aht svg correctly --- scripts/x.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 3db8ed39..7ebb4f89 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -271,10 +271,8 @@ def generate_aht_plt(results): plt.yticks=(yticks) plt.xlabel("number of atomic heap terms") plt.ylabel("solving time(s)") - - plt.show() plt.savefig(aht_plt_file) - plt.clf() + plt.show() def run_expriment_on(benchmark_root, extra_args): assert(os.path.exists(benchmark_root)) From 025a44def3f1e67749915e154c8dd7520d7f2c13 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Tue, 8 Oct 2024 11:13:59 +0800 Subject: [PATCH 124/126] add theory solving statistics --- scripts/x.py | 55 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/scripts/x.py b/scripts/x.py index 7ebb4f89..c7ccc75e 100755 --- a/scripts/x.py +++ b/scripts/x.py @@ -174,6 +174,11 @@ def generate_csv(results): total_time = [0.0, 0.0] mi_time = ['-', '-'] mx_time = ['-', '-'] + + theory_solving_formulas = [0, 0] + theory_solving_total_time = [0.0, 0.0] + theory_solving_mi_time = ['-', '-'] + theory_solving_mx_time = ['-', '-'] formulas_with_aht = 0 total_ahts = 0 @@ -206,8 +211,25 @@ def generate_csv(results): else: mx_time[r] = max(mx_time[r], time) - # Aht + # Entering theory solving if str(assert_result["Aht"]) != '-': + time = float(assert_result["Time"]) + + theory_solving_formulas[r] += 1 + theory_solving_total_time[r] += time + + time = round(time, 3) + if theory_solving_mi_time[r] == '-': + theory_solving_mi_time[r] = time + else: + theory_solving_mi_time[r] = min(theory_solving_mi_time[r], time) + + if theory_solving_mx_time[r] == '-': + theory_solving_mx_time[r] = time + else: + theory_solving_mx_time[r] = max(theory_solving_mx_time[r], time) + + # Atomic heap terms statistics aht = assert_result["Aht"] formulas_with_aht += 1 total_ahts += aht @@ -229,17 +251,11 @@ def generate_csv(results): } w.writerow(new_row) - new_row = { - "File": '', - "Line": '', - "Column": '', - "Property": '', - "Aht": '', - "Result": '', - "Time": '', - } + # Solving time statistics + new_row = {} w.writerow(new_row) + # Total time statistics sat_ave = round(total_time[0] / formulas[0], 3) unsat_ave = round(total_time[1] / formulas[1], 3) @@ -248,10 +264,27 @@ def generate_csv(results): "Line": f'Average(sat/unsat): {sat_ave}/{unsat_ave}', "Column": f'Min_time(sat/unsat): {mi_time[0]}/{mi_time[1]}', "Property": f'Max_time(sat/unsat): {mx_time[0]}/{mx_time[1]}', + } + w.writerow(new_row) + + new_row = {} + w.writerow(new_row) + new_row = { 'File' : 'Theory_solving'} + w.writerow(new_row) + + # Only formulas entering theory solving + theory_solving_sat_ave = round(theory_solving_total_time[0] / theory_solving_formulas[0], 3) + theory_solving_unsat_ave = round(theory_solving_total_time[1] / theory_solving_formulas[1], 3) + + new_row = { + "File": f'Formulas(sat/unsat): {theory_solving_formulas[0]}/{theory_solving_formulas[1]}', + "Line": f'Average(sat/unsat): {theory_solving_sat_ave}/{theory_solving_unsat_ave}', + "Column": f'Min_time(sat/unsat): {theory_solving_mi_time[0]}/{theory_solving_mi_time[1]}', + "Property": f'Max_time(sat/unsat): {theory_solving_mx_time[0]}/{theory_solving_mx_time[1]}', "Aht": f'Formulas_with_aht: {formulas_with_aht}', "Result": f'Average_aht: {total_ahts // formulas_with_aht}', "Time": f'Min/Max(aht): {mi_aht}/{mx_aht}', - } + } w.writerow(new_row) def generate_aht_plt(results): From f121f002f19e57b3e3e1c3d61f66b4df84576ce1 Mon Sep 17 00:00:00 2001 From: zhuyt Date: Fri, 11 Oct 2024 22:51:44 +0800 Subject: [PATCH 125/126] add bench-0125 --- benchmark/MemSafety-Arrays-C-Log.txt | 1057 ----------------- benchmark/MemSafety-Heap-C-Log.txt | 1007 ---------------- benchmark/MemSafety-Heap-I-Log.txt | 877 -------------- benchmark/MemSafety-LinkedLists-C-Log.txt | 331 ------ benchmark/case_1.out | 1 - benchmark/case_10.out | 1 - benchmark/case_11.out | 1 - benchmark/case_12.out | 1 - benchmark/case_13.out | 1 - benchmark/case_14.out | 1 - benchmark/case_15.out | 1 - benchmark/case_16.out | 1 - benchmark/case_2.out | 1 - benchmark/case_3.out | 1 - benchmark/case_4.out | 1 - benchmark/case_5.out | 1 - benchmark/case_6.out | 1 - benchmark/case_7.out | 1 - benchmark/case_8.out | 1 - benchmark/case_9.out | 1 - .../lockfree-3.1-foy2ogf6-370d5edd.bc.tmp | 0 benchmark/run_test_c.py | 185 --- benchmark/run_test_i.py | 185 --- benchmark/tacas-2025/960521-1-1-mutate.c | 15 + benchmark/tacas-2025/960521-1-2-mutate.c | 24 + benchmark/tacas-2025/960521-1-2.c | 26 + benchmark/tacas-2025/960521-1-3-mutate.c | 15 + benchmark/tacas-2025/cmp-freed-ptr-mutate.c | 19 + benchmark/tacas-2025/global-atexit-1-mutate.c | 22 + benchmark/tacas-2025/global-atexit-1.c | 19 + benchmark/tacas-2025/global-atexit-2-mutate.c | 22 + benchmark/tacas-2025/global-atexit-2.c | 20 + benchmark/tacas-2025/global-atexit-3.c | 20 + benchmark/tacas-2025/global-atexit-5.c | 30 + benchmark/tacas-2025/global-atexit.c | 28 + benchmark/tacas-2025/test-0019-1-mutate.c | 17 + benchmark/tacas-2025/test-0019-1.c | 19 + benchmark/tacas-2025/test-0019-2-mutate.c | 19 + benchmark/tacas-2025/test-0019-2.c | 20 + benchmark/tacas-2025/test-0232-1.c | 26 + benchmark/tacas-2025/test-0232-2-mutate.c | 36 + benchmark/tacas-2025/test-0232-3-mutate.c | 35 + benchmark/tacas-2025/test-0513-mutate.c | 66 + .../test-0235-3-rsv4qzsd-a33e63fa.bc.tmp | 0 benchmark/test-0236-w8ksvopc-7369e031.bc.tmp | 0 benchmark/testWitness.graphml | 39 - benchmark/{ => tests}/case_0.c | 0 benchmark/{ => tests}/case_1.c | 0 benchmark/{ => tests}/case_10.c | 0 benchmark/{ => tests}/case_11.c | 0 benchmark/{ => tests}/case_12.c | 0 benchmark/{ => tests}/case_13.c | 0 benchmark/{ => tests}/case_14.c | 0 benchmark/{ => tests}/case_15.c | 0 benchmark/{ => tests}/case_16.c | 0 benchmark/{ => tests}/case_2.c | 0 benchmark/{ => tests}/case_3.c | 0 benchmark/{ => tests}/case_4.c | 0 benchmark/{ => tests}/case_5.c | 0 benchmark/{ => tests}/case_6.c | 0 benchmark/{ => tests}/case_7.c | 0 benchmark/{ => tests}/case_8.c | 0 benchmark/{ => tests}/case_9.c | 0 63 files changed, 498 insertions(+), 3697 deletions(-) delete mode 100644 benchmark/MemSafety-Arrays-C-Log.txt delete mode 100644 benchmark/MemSafety-Heap-C-Log.txt delete mode 100644 benchmark/MemSafety-Heap-I-Log.txt delete mode 100644 benchmark/MemSafety-LinkedLists-C-Log.txt delete mode 100644 benchmark/case_1.out delete mode 100644 benchmark/case_10.out delete mode 100644 benchmark/case_11.out delete mode 100644 benchmark/case_12.out delete mode 100644 benchmark/case_13.out delete mode 100644 benchmark/case_14.out delete mode 100644 benchmark/case_15.out delete mode 100644 benchmark/case_16.out delete mode 100644 benchmark/case_2.out delete mode 100644 benchmark/case_3.out delete mode 100644 benchmark/case_4.out delete mode 100644 benchmark/case_5.out delete mode 100644 benchmark/case_6.out delete mode 100644 benchmark/case_7.out delete mode 100644 benchmark/case_8.out delete mode 100644 benchmark/case_9.out delete mode 100644 benchmark/lockfree-3.1-foy2ogf6-370d5edd.bc.tmp delete mode 100644 benchmark/run_test_c.py delete mode 100644 benchmark/run_test_i.py create mode 100644 benchmark/tacas-2025/960521-1-1-mutate.c create mode 100644 benchmark/tacas-2025/960521-1-2-mutate.c create mode 100644 benchmark/tacas-2025/960521-1-2.c create mode 100644 benchmark/tacas-2025/960521-1-3-mutate.c create mode 100644 benchmark/tacas-2025/cmp-freed-ptr-mutate.c create mode 100644 benchmark/tacas-2025/global-atexit-1-mutate.c create mode 100644 benchmark/tacas-2025/global-atexit-1.c create mode 100644 benchmark/tacas-2025/global-atexit-2-mutate.c create mode 100644 benchmark/tacas-2025/global-atexit-2.c create mode 100644 benchmark/tacas-2025/global-atexit-3.c create mode 100644 benchmark/tacas-2025/global-atexit-5.c create mode 100644 benchmark/tacas-2025/global-atexit.c create mode 100644 benchmark/tacas-2025/test-0019-1-mutate.c create mode 100644 benchmark/tacas-2025/test-0019-1.c create mode 100644 benchmark/tacas-2025/test-0019-2-mutate.c create mode 100644 benchmark/tacas-2025/test-0019-2.c create mode 100644 benchmark/tacas-2025/test-0232-1.c create mode 100644 benchmark/tacas-2025/test-0232-2-mutate.c create mode 100644 benchmark/tacas-2025/test-0232-3-mutate.c create mode 100644 benchmark/tacas-2025/test-0513-mutate.c delete mode 100644 benchmark/test-0235-3-rsv4qzsd-a33e63fa.bc.tmp delete mode 100644 benchmark/test-0236-w8ksvopc-7369e031.bc.tmp delete mode 100644 benchmark/testWitness.graphml rename benchmark/{ => tests}/case_0.c (100%) rename benchmark/{ => tests}/case_1.c (100%) rename benchmark/{ => tests}/case_10.c (100%) rename benchmark/{ => tests}/case_11.c (100%) rename benchmark/{ => tests}/case_12.c (100%) rename benchmark/{ => tests}/case_13.c (100%) rename benchmark/{ => tests}/case_14.c (100%) rename benchmark/{ => tests}/case_15.c (100%) rename benchmark/{ => tests}/case_16.c (100%) rename benchmark/{ => tests}/case_2.c (100%) rename benchmark/{ => tests}/case_3.c (100%) rename benchmark/{ => tests}/case_4.c (100%) rename benchmark/{ => tests}/case_5.c (100%) rename benchmark/{ => tests}/case_6.c (100%) rename benchmark/{ => tests}/case_7.c (100%) rename benchmark/{ => tests}/case_8.c (100%) rename benchmark/{ => tests}/case_9.c (100%) diff --git a/benchmark/MemSafety-Arrays-C-Log.txt b/benchmark/MemSafety-Arrays-C-Log.txt deleted file mode 100644 index b9017e0b..00000000 --- a/benchmark/MemSafety-Arrays-C-Log.txt +++ /dev/null @@ -1,1057 +0,0 @@ -Adding testcase [array03-alloca-2] -Adding testcase [Arrays01-EquivalentConstantIndices-1] -Adding testcase [standard_copy4_ground-1] -Adding testcase [standard_copy8_ground-1] -Adding testcase [standard_two_index_02] -Adding testcase [java_BubbleSort-alloca-1] -Adding testcase [standard_two_index_09] -Adding testcase [standard_copyInitSum2_ground-1] -Adding testcase [standard_two_index_04] -Adding testcase [standard_palindrome_ground] -Adding testcase [standard_copyInitSum2_ground-2] -Adding testcase [cstrchr-alloca-2] -Adding testcase [standard_seq_init_ground] -Adding testcase [standard_copy3_ground-1] -Adding testcase [standard_partition_ground-1] -Adding testcase [openbsd_cstrcspn-alloca-2] -Adding testcase [diff-alloca-2] -Adding testcase [standard_find_ground-1] -Adding testcase [sorting_selectionsort_2_ground] -Adding testcase [cstrcat_unsafe] -Adding testcase [rec_strlen-alloca-1] -Adding testcase [standard_running-2] -Adding testcase [openbsd_cmemrchr-alloca-2] -Adding testcase [openbsd_cstrncat-alloca-2] -Adding testcase [openbsd_cstrnlen-alloca-1] -Adding testcase [standard_strcmp_ground] -Adding testcase [openbsd_cstrstr-alloca-2] -Adding testcase [standard_init8_ground-2] -Adding testcase [standard_two_index_07] -Adding testcase [array01-alloca-2] -Adding testcase [knapsack_alloca_unsafe] -Adding testcase [standard_copy7_ground-1] -Adding testcase [standard_partition_original_ground] -Adding testcase [sanfoundry_02_ground] -Adding testcase [standard_partial_init_ground] -Adding testcase [standard_two_index_01] -Adding testcase [sanfoundry_27_ground] -Adding testcase [Arrays02-EquivalentConstantIndices] -Adding testcase [openbsd_cmemchr-alloca-2] -Adding testcase [standard_sentinel-1] -Adding testcase [reverse_array_alloca_unsafe] -Adding testcase [standard_copy3_ground-2] -Adding testcase [cstrpbrk-alloca-2] -Adding testcase [standard_init7_ground-2] -Adding testcase [bubblesort-alloca-2] -Adding testcase [standard_sentinel-2] -Adding testcase [sanfoundry_24-2] -Adding testcase [cstrspn-alloca-1] -Adding testcase [standard_copy9_ground-1] -Adding testcase [standard_copy7_ground-2] -Adding testcase [sorting_bubblesort_ground-2] -Adding testcase [subseq-alloca-2] -Adding testcase [standard_init2_ground-1] -Adding testcase [standard_copy5_ground-1] -Adding testcase [cstrpbrk_unsafe] -Adding testcase [openbsd_cmemset-alloca-1] -Adding testcase [openbsd_cstpcpy-alloca-1] -Adding testcase [standard_copy9_ground-2] -Adding testcase [standard_strcpy_ground-2] -Adding testcase [openbsd_cstrpbrk-alloca-2] -Adding testcase [array02-alloca-2] -Adding testcase [cstrncat_unsafe] -Adding testcase [standard_init8_ground-1] -Adding testcase [bubblesort_unsafe] -Adding testcase [standard_compare_ground] -Adding testcase [sanfoundry_24-1] -Adding testcase [mult_array-alloca-1] -Adding testcase [sorting_selectionsort_ground-1] -Adding testcase [insertionsort-alloca-1] -Adding testcase [openbsd_cstrcpy-alloca-2] -Adding testcase [standard_two_index_08] -Adding testcase [sorting_bubblesort_ground-1] -Adding testcase [standard_init3_ground-2] -Adding testcase [standard_copyInitSum_ground] -Adding testcase [openbsd_cstrlen-alloca-1] -Adding testcase [openbsd_cstrncmp-alloca-2] -Adding testcase [standard_strcpy_original-1] -Adding testcase [mult_array_unsafe] -Adding testcase [standard_two_index_03] -Adding testcase [Arrays03-ValueRestictsIndex-1] -Adding testcase [standard_init5_ground-2] -Adding testcase [standard_copy5_ground-2] -Adding testcase [standard_vararg_ground] -Adding testcase [strreplace-alloca-2] -Adding testcase [stroeder1-alloca-1] -Adding testcase [openbsd_cstrcmp-alloca-1] -Adding testcase [substring-alloca-2] -Adding testcase [count_down_unsafe] -Adding testcase [standard_copy2_ground-1] -Adding testcase [LexIndexValue-Array-1] -Adding testcase [LexIndexValue-Array-2] -Adding testcase [cstrncpy-alloca-2] -Adding testcase [diff_usafe] -Adding testcase [sanfoundry_43_ground] -Adding testcase [selectionsort_unsafe] -Adding testcase [standard_init5_ground-1] -Adding testcase [standard_copy6_ground-2] -Adding testcase [standard_init6_ground-2] -Adding testcase [standard_find_ground-2] -Adding testcase [standard_copyInitSum3_ground] -Adding testcase [standard_minInArray_ground-2] -Adding testcase [standard_copy6_ground-1] -Adding testcase [standard_init7_ground-1] -Adding testcase [standard_copyInit_ground] -Adding testcase [cstrcat-alloca-2] -Adding testcase [standard_init6_ground-1] -Adding testcase [standard_strcpy_original-2] -Adding testcase [standard_partition_ground-2] -Adding testcase [stroeder2-alloca-1] -Adding testcase [cstrncmp-alloca-1] -Adding testcase [reverse_array_unsafe] -Adding testcase [Arrays03-ValueRestictsIndex-2] -Adding testcase [cstrcspn-alloca-1] -Adding testcase [openbsd_cstrncpy-alloca-2] -Adding testcase [standard_init1_ground-1] -Adding testcase [standard_minInArray_ground-1] -Adding testcase [standard_init9_ground-2] -Adding testcase [standard_vector_difference_ground] -Adding testcase [standard_init3_ground-1] -Adding testcase [standard_copy2_ground-2] -Adding testcase [standard_compareModified_ground] -Adding testcase [standard_running-1] -Adding testcase [standard_two_index_06] -Adding testcase [openbsd_cstrcat-alloca-2] -Adding testcase [standard_copy1_ground-1] -Adding testcase [cstrchr_unsafe] -Adding testcase [standard_init9_ground-1] -Adding testcase [relax-2] -Adding testcase [count_down-alloca-1] -Adding testcase [standard_maxInArray_ground] -Adding testcase [openbsd_cbzero-alloca-2] -Adding testcase [lis_unsafe] -Adding testcase [standard_reverse_ground] -Adding testcase [sanfoundry_10_ground] -Adding testcase [Arrays01-EquivalentConstantIndices-2] -Adding testcase [standard_copy8_ground-2] -Adding testcase [standard_copy4_ground-2] -Adding testcase [standard_init1_ground-2] -Adding testcase [standard_init4_ground-1] -Adding testcase [lis-alloca-1] -Adding testcase [standard_allDiff2_ground] -Adding testcase [relax-1] -Adding testcase [add_last_unsafe] -Adding testcase [cstrlen-alloca-2] -Adding testcase [cstrcpy-alloca-1] -Adding testcase [cstrncat-alloca-2] -Adding testcase [openbsd_cstpncpy-alloca-1] -Adding testcase [openbsd_cstrlcpy-alloca-1] -Adding testcase [sorting_selectionsort_ground-2] -Adding testcase [add_last-alloca-1] -Adding testcase [standard_strcpy_ground-1] -Adding testcase [cstrncpy_unsafe] -Adding testcase [data_structures_set_multi_proc_ground-1] -Adding testcase [standard_copy1_ground-2] -Adding testcase [openbsd_cstrspn-alloca-2] -Adding testcase [cstrlen_unsafe] -Adding testcase [data_structures_set_multi_proc_ground-2] -Adding testcase [selectionsort-alloca-1] -Adding testcase [standard_two_index_05] -Adding testcase [NonTermination3-1] -Adding testcase [standard_password_ground] -Adding testcase [LexIndexValue-Pointer-2] -Adding testcase [standard_init4_ground-2] -Adding testcase [standard_init2_ground-2] -Adding testcase [data_structures_set_multi_proc_trivial_ground] -Adding testcase [LexIndexValue-Pointer-3] -Adding testcase [stroeder1_unsafe] -Adding testcase [sorting_bubblesort_2_ground] -Adding testcase [LexIndexValue-Pointer-1] -Adding testcase [standard_sentinel.i.v+cfa-reducer] -Adding testcase [cstrcmp-alloca-2] -Running test: [array03-alloca-2.i] -Tool: SAFE -Real: SAFE - -Running test: [Arrays01-EquivalentConstantIndices-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy4_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy8_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_two_index_02.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [java_BubbleSort-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_two_index_09.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copyInitSum2_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_two_index_04.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_palindrome_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copyInitSum2_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrchr-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_seq_init_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy3_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_partition_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [openbsd_cstrcspn-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [diff-alloca-2.i] -Tool: SAFE -Real: SAFE - -Running test: [standard_find_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sorting_selectionsort_2_ground.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [cstrcat_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [rec_strlen-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_running-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cmemrchr-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrncat-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrnlen-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_strcmp_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrstr-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init8_ground-2.i] -Tool: SAFE -Real: SAFE - -Running test: [standard_two_index_07.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [array01-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [knapsack_alloca_unsafe.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [standard_copy7_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_partition_original_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sanfoundry_02_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_partial_init_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_two_index_01.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sanfoundry_27_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [Arrays02-EquivalentConstantIndices.i] -Tool: SAFE -Real: UNSAFE - -Running test: [openbsd_cmemchr-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_sentinel-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [reverse_array_alloca_unsafe.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [standard_copy3_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [cstrpbrk-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init7_ground-2.i] -Tool: SAFE -Real: SAFE - -Running test: [bubblesort-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_sentinel-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [sanfoundry_24-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [cstrspn-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy9_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy7_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sorting_bubblesort_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [subseq-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init2_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy5_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrpbrk_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [openbsd_cmemset-alloca-1.i] -Tool: UNSAFE -Real: SAFE - -Running test: [openbsd_cstpcpy-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy9_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_strcpy_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [openbsd_cstrpbrk-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [array02-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrncat_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init8_ground-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [bubblesort_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_compare_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sanfoundry_24-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [mult_array-alloca-1.i] -Tool: UNSAFE -Real: SAFE - -Running test: [sorting_selectionsort_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [insertionsort-alloca-1.i] -Tool: UNSAFE -Real: SAFE - -Running test: [openbsd_cstrcpy-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_two_index_08.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sorting_bubblesort_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init3_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copyInitSum_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrlen-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrncmp-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_strcpy_original-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [mult_array_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_two_index_03.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [Arrays03-ValueRestictsIndex-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init5_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy5_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_vararg_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [strreplace-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [stroeder1-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrcmp-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [substring-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [count_down_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy2_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [LexIndexValue-Array-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [LexIndexValue-Array-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [cstrncpy-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [diff_usafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sanfoundry_43_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [selectionsort_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init5_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy6_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init6_ground-2.i] -Tool: SAFE -Real: SAFE - -Running test: [standard_find_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copyInitSum3_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_minInArray_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy6_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init7_ground-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [standard_copyInit_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrcat-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init6_ground-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [standard_strcpy_original-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_partition_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [stroeder2-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrncmp-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [reverse_array_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [Arrays03-ValueRestictsIndex-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [cstrcspn-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrncpy-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init1_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_minInArray_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init9_ground-2.i] -Tool: SAFE -Real: SAFE - -Running test: [standard_vector_difference_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init3_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy2_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_compareModified_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_running-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_two_index_06.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrcat-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_copy1_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrchr_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init9_ground-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [relax-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [count_down-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_maxInArray_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cbzero-alloca-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [lis_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_reverse_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sanfoundry_10_ground.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [Arrays01-EquivalentConstantIndices-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy8_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy4_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_init1_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init4_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [lis-alloca-1.i] -Tool: SAFE -Real: SAFE - -Running test: [standard_allDiff2_ground.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [relax-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [add_last_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [cstrlen-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrcpy-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrncat-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstpncpy-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [openbsd_cstrlcpy-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sorting_selectionsort_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [add_last-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_strcpy_ground-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrncpy_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [data_structures_set_multi_proc_ground-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [standard_copy1_ground-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [openbsd_cstrspn-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [cstrlen_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [data_structures_set_multi_proc_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [selectionsort-alloca-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_two_index_05.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [NonTermination3-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [standard_password_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [LexIndexValue-Pointer-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init4_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [standard_init2_ground-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [data_structures_set_multi_proc_trivial_ground.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [LexIndexValue-Pointer-3.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [stroeder1_unsafe.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sorting_bubblesort_2_ground.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [LexIndexValue-Pointer-1.i] -Tool: UNSAFE -Real: SAFE - -Running test: [standard_sentinel.i.v+cfa-reducer.i] -Tool: UNSAFE -Real: SAFE - -Running test: [cstrcmp-alloca-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Success verified: 11 -Test [array03-alloca-2] is [SAFE]: -Test [diff-alloca-2] is [SAFE]: -Test [standard_init8_ground-2] is [SAFE]: -Test [knapsack_alloca_unsafe] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [standard_sentinel-1] is [UNSAFE]: -Real error: ['def-behavior'] -Inferred error: ['INVALID_DEREF'] -Test [reverse_array_alloca_unsafe] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [standard_init7_ground-2] is [SAFE]: -Test [standard_init6_ground-2] is [SAFE]: -Test [standard_init9_ground-2] is [SAFE]: -Test [lis-alloca-1] is [SAFE]: -Test [NonTermination3-1] is [UNSAFE]: -Real error: ['termination', 'valid-deref'] -Inferred error: ['INVALID_DEREF'] - - -Unknown result: 1 -Test: sanfoundry_10_ground - - -Unmatch result: 13 -Test [Arrays02-EquivalentConstantIndices] is [UNSAFE]: -Real error: ['termination'] -Test [standard_sentinel-2] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [openbsd_cmemset-alloca-1] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [standard_init8_ground-1] is [UNSAFE]: -Real error: ['unreach-call'] -Test [mult_array-alloca-1] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [insertionsort-alloca-1] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [standard_init7_ground-1] is [UNSAFE]: -Real error: ['unreach-call'] -Test [standard_init6_ground-1] is [UNSAFE]: -Real error: ['unreach-call'] -Test [Arrays03-ValueRestictsIndex-2] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [standard_init9_ground-1] is [UNSAFE]: -Real error: ['unreach-call'] -Test [openbsd_cbzero-alloca-2] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [LexIndexValue-Pointer-1] is [SAFE]: -Inferred error: ['MemLeak'] -Test [standard_sentinel.i.v+cfa-reducer] is [SAFE]: -Inferred error: ['INVALID_DEREF'] - - -Raise exception: 146 -Arrays01-EquivalentConstantIndices-1 -standard_copy4_ground-1 -standard_copy8_ground-1 -standard_two_index_02 -java_BubbleSort-alloca-1 -standard_two_index_09 -standard_copyInitSum2_ground-1 -standard_two_index_04 -standard_palindrome_ground -standard_copyInitSum2_ground-2 -cstrchr-alloca-2 -standard_seq_init_ground -standard_copy3_ground-1 -standard_partition_ground-1 -openbsd_cstrcspn-alloca-2 -standard_find_ground-1 -sorting_selectionsort_2_ground -cstrcat_unsafe -rec_strlen-alloca-1 -standard_running-2 -openbsd_cmemrchr-alloca-2 -openbsd_cstrncat-alloca-2 -openbsd_cstrnlen-alloca-1 -standard_strcmp_ground -openbsd_cstrstr-alloca-2 -standard_two_index_07 -array01-alloca-2 -standard_copy7_ground-1 -standard_partition_original_ground -sanfoundry_02_ground -standard_partial_init_ground -standard_two_index_01 -sanfoundry_27_ground -openbsd_cmemchr-alloca-2 -standard_copy3_ground-2 -cstrpbrk-alloca-2 -bubblesort-alloca-2 -sanfoundry_24-2 -cstrspn-alloca-1 -standard_copy9_ground-1 -standard_copy7_ground-2 -sorting_bubblesort_ground-2 -subseq-alloca-2 -standard_init2_ground-1 -standard_copy5_ground-1 -cstrpbrk_unsafe -openbsd_cstpcpy-alloca-1 -standard_copy9_ground-2 -standard_strcpy_ground-2 -openbsd_cstrpbrk-alloca-2 -array02-alloca-2 -cstrncat_unsafe -bubblesort_unsafe -standard_compare_ground -sanfoundry_24-1 -sorting_selectionsort_ground-1 -openbsd_cstrcpy-alloca-2 -standard_two_index_08 -sorting_bubblesort_ground-1 -standard_init3_ground-2 -standard_copyInitSum_ground -openbsd_cstrlen-alloca-1 -openbsd_cstrncmp-alloca-2 -standard_strcpy_original-1 -mult_array_unsafe -standard_two_index_03 -Arrays03-ValueRestictsIndex-1 -standard_init5_ground-2 -standard_copy5_ground-2 -standard_vararg_ground -strreplace-alloca-2 -stroeder1-alloca-1 -openbsd_cstrcmp-alloca-1 -substring-alloca-2 -count_down_unsafe -standard_copy2_ground-1 -LexIndexValue-Array-1 -LexIndexValue-Array-2 -cstrncpy-alloca-2 -diff_usafe -sanfoundry_43_ground -selectionsort_unsafe -standard_init5_ground-1 -standard_copy6_ground-2 -standard_find_ground-2 -standard_copyInitSum3_ground -standard_minInArray_ground-2 -standard_copy6_ground-1 -standard_copyInit_ground -cstrcat-alloca-2 -standard_strcpy_original-2 -standard_partition_ground-2 -stroeder2-alloca-1 -cstrncmp-alloca-1 -reverse_array_unsafe -cstrcspn-alloca-1 -openbsd_cstrncpy-alloca-2 -standard_init1_ground-1 -standard_minInArray_ground-1 -standard_vector_difference_ground -standard_init3_ground-1 -standard_copy2_ground-2 -standard_compareModified_ground -standard_running-1 -standard_two_index_06 -openbsd_cstrcat-alloca-2 -standard_copy1_ground-1 -cstrchr_unsafe -relax-2 -count_down-alloca-1 -standard_maxInArray_ground -lis_unsafe -standard_reverse_ground -Arrays01-EquivalentConstantIndices-2 -standard_copy8_ground-2 -standard_copy4_ground-2 -standard_init1_ground-2 -standard_init4_ground-1 -standard_allDiff2_ground -relax-1 -add_last_unsafe -cstrlen-alloca-2 -cstrcpy-alloca-1 -cstrncat-alloca-2 -openbsd_cstpncpy-alloca-1 -openbsd_cstrlcpy-alloca-1 -sorting_selectionsort_ground-2 -add_last-alloca-1 -standard_strcpy_ground-1 -cstrncpy_unsafe -data_structures_set_multi_proc_ground-1 -standard_copy1_ground-2 -openbsd_cstrspn-alloca-2 -cstrlen_unsafe -data_structures_set_multi_proc_ground-2 -selectionsort-alloca-1 -standard_two_index_05 -standard_password_ground -LexIndexValue-Pointer-2 -standard_init4_ground-2 -standard_init2_ground-2 -data_structures_set_multi_proc_trivial_ground -LexIndexValue-Pointer-3 -stroeder1_unsafe -sorting_bubblesort_2_ground -cstrcmp-alloca-2 diff --git a/benchmark/MemSafety-Heap-C-Log.txt b/benchmark/MemSafety-Heap-C-Log.txt deleted file mode 100644 index 48607baa..00000000 --- a/benchmark/MemSafety-Heap-C-Log.txt +++ /dev/null @@ -1,1007 +0,0 @@ -Adding testcase [memleaks_test17_1-1] -Adding testcase [memleaks_test20-1] -Adding testcase [memleaks_test11] -Adding testcase [ArraysOfVariableLength2_-read] -Adding testcase [test-0235-3] -Adding testcase [memleaks_test1-1] -Adding testcase [test-0158-2] -Adding testcase [test-0232-2] -Adding testcase [StructInitialization2] -Adding testcase [lockfree-3.0] -Adding testcase [memleaks_test12-2] -Adding testcase [memleaks_test22_1-1] -Adding testcase [memleaks_test1-3] -Adding testcase [complex_data_creation_test01-2] -Adding testcase [memsetNonZero2_-write] -Adding testcase [memleaks_test8_2] -Adding testcase [ArraysOfVariableLength6] -Adding testcase [ArraysWithLenghtAtDeclaration] -Adding testcase [test-bitfields-1-1] -Adding testcase [memleaks_test16_1] -Adding testcase [test-0137] -Adding testcase [20020406-1] -Adding testcase [memsetNonZero2] -Adding testcase [test-0232-3] -Adding testcase [ArraysWithLenghtAtDeclaration_-read] -Adding testcase [memleaks_test22_4] -Adding testcase [memleaks_test19-1] -Adding testcase [test-bitfields-3-1] -Adding testcase [test-0019-1] -Adding testcase [test-0220] -Adding testcase [memleaks_test20-2] -Adding testcase [memleaks_test23_4] -Adding testcase [memleaks_test3-2] -Adding testcase [complex_data_creation_test01-1] -Adding testcase [memleaks_test9_2] -Adding testcase [memleaks_test22_2-1] -Adding testcase [memleaks_test16] -Adding testcase [memleaks_test18_2] -Adding testcase [test-0504] -Adding testcase [memleaks_test17_1-2] -Adding testcase [memleaks_test23_3] -Adding testcase [test-0234-1] -Adding testcase [lockfree-3.1] -Adding testcase [test-0217] -Adding testcase [memleaks_test14_2] -Adding testcase [memleaks_test17_3] -Adding testcase [test-0158-3] -Adding testcase [complex_data_creation_test02-2] -Adding testcase [memleaks_test22_1-2] -Adding testcase [memleaks_test23_2] -Adding testcase [memleaks_test14] -Adding testcase [test-0218] -Adding testcase [memleaks_test19-2] -Adding testcase [memleaks_test18_3] -Adding testcase [memleaks_test15-1] -Adding testcase [split_list_test05-1] -Adding testcase [test-bitfields-2-1] -Adding testcase [memleaks_test3-1] -Adding testcase [test-0235-1] -Adding testcase [memleaks_test9_1] -Adding testcase [memleaks_test17_2-1] -Adding testcase [memset3] -Adding testcase [memsetNonZero_-write] -Adding testcase [c.03-alloca-2] -Adding testcase [memleaks_test4-1] -Adding testcase [StructInitialization] -Adding testcase [memleaks_test22_3-2] -Adding testcase [optional_data_creation_test04-2] -Adding testcase [memleaks_test13] -Adding testcase [memleaks_test23_1] -Adding testcase [ArraysOfVariableLength_-read] -Adding testcase [lockfree-3.3] -Adding testcase [test-0513] -Adding testcase [memleaks_test5_2] -Adding testcase [test-0019-2] -Adding testcase [test-bitfields-1-2] -Adding testcase [test-0219] -Adding testcase [memleaks_test6_2] -Adding testcase [memsetNonZero3] -Adding testcase [complex_data_creation_test02-1] -Adding testcase [memleaks_test14_1] -Adding testcase [length_test03-1] -Adding testcase [memset] -Adding testcase [memleaks_test14_3] -Adding testcase [test-0134] -Adding testcase [test-bitfields-3.1-1] -Adding testcase [ArraysOfVariableLength5] -Adding testcase [test-0237] -Adding testcase [memleaks_test18_1] -Adding testcase [memleaks_test22_5] -Adding testcase [960521-1-3] -Adding testcase [test-0232-1] -Adding testcase [test-0214] -Adding testcase [memleaks_test5_1] -Adding testcase [ArraysWithLenghtAtDeclaration_-write] -Adding testcase [memleaks_test10-2] -Adding testcase [test-0235-2] -Adding testcase [test-memleak_nexttime] -Adding testcase [memsetNonZero] -Adding testcase [memleaks_test21-1] -Adding testcase [cmp-freed-ptr] -Adding testcase [memleaks_test16_2] -Adding testcase [memleaks_test22_3-1] -Adding testcase [ArraysOfVariableLength2_-write] -Adding testcase [memleaks_test11_1] -Adding testcase [memleaks_test5] -Adding testcase [memleaks_test13_2] -Adding testcase [memleaks_test9] -Adding testcase [test-0236] -Adding testcase [memleaks_test21-2] -Adding testcase [memleaks_test13_1] -Adding testcase [memleaks_test6_1] -Adding testcase [test-0102-2] -Adding testcase [memleaks_test8] -Adding testcase [ArraysOfVariableLength_-write] -Adding testcase [960521-1-1] -Adding testcase [memset2_-write] -Adding testcase [memleaks_test6_3] -Adding testcase [memleaks_test11_2] -Adding testcase [memleaks_test10-1] -Adding testcase [StructInitialization1] -Adding testcase [memset_-write] -Adding testcase [memleaks_test7-2] -Adding testcase [test-0158-1] -Adding testcase [memleaks_test18] -Adding testcase [memset3_-write] -Adding testcase [960521-1-2] -Adding testcase [memsetNonZero3_-write] -Adding testcase [test-0234-2] -Adding testcase [memleaks_test8_1] -Adding testcase [memleaks_test15-2] -Adding testcase [test-bitfields-2.1-1] -Adding testcase [lockfree-3.2] -Adding testcase [test-bitfields-3.1-2] -Adding testcase [test-bitfields-3-2] -Adding testcase [ArraysOfVariableLength2] -Adding testcase [memleaks_test12-1] -Adding testcase [test-0102-1] -Adding testcase [length_test03-2] -Adding testcase [test-bitfields-2.1-2] -Adding testcase [test-0521] -Adding testcase [optional_data_creation_test04-1] -Adding testcase [split_list_test05-2] -Adding testcase [memleaks_test6] -Adding testcase [memleaks_test4-2] -Adding testcase [memleaks_test22_2-2] -Adding testcase [memleaks_test1-2] -Adding testcase [20051113-1] -Adding testcase [memleaks_test17_2-2] -Adding testcase [memleaks_test7-1] -Adding testcase [ArraysOfVariableLength4] -Adding testcase [memset2] -Adding testcase [test-bitfields-2-2] -Adding testcase [ArraysOfVariableLength] -Running test: [memleaks_test17_1-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test20-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test11.i] -Tool: SAFE -Real: SAFE - -Running test: [ArraysOfVariableLength2_-read.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-0235-3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test1-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0158-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0232-2.i] -Tool: SAFE -Real: SAFE - -Running test: [StructInitialization2.i] -Tool: SAFE -Real: SAFE - -Running test: [lockfree-3.0.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test12-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test22_1-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test1-3.i] -Tool: SAFE -Real: SAFE - -Running test: [complex_data_creation_test01-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memsetNonZero2_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test8_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [ArraysOfVariableLength6.i] -Tool: SAFE -Real: SAFE - -Running test: [ArraysWithLenghtAtDeclaration.i] -Tool: SAFE -Real: SAFE - -Running test: [test-bitfields-1-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test16_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0137.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [20020406-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memsetNonZero2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0232-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [ArraysWithLenghtAtDeclaration_-read.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test22_4.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test19-1.i] -Tool: SAFE -Real: SAFE - -Running test: [test-bitfields-3-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-0019-1.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0220.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test20-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_4.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test3-2.i] -Tool: SAFE -Real: SAFE - -Running test: [complex_data_creation_test01-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test9_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test22_2-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test16.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test18_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0504.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test17_1-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_3.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0234-1.i] -Tool: SAFE -Real: SAFE - -Running test: [lockfree-3.1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0217.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test14_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test17_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0158-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [complex_data_creation_test02-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test22_1-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test14.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0218.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test19-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test18_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test15-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [split_list_test05-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-bitfields-2-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test3-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0235-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test9_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test17_2-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memset3.i] -Tool: SAFE -Real: SAFE - -Running test: [memsetNonZero_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [c.03-alloca-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test4-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [StructInitialization.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test22_3-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [optional_data_creation_test04-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test13.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_1.i] -Tool: SAFE -Real: SAFE - -Running test: [ArraysOfVariableLength_-read.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [lockfree-3.3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0513.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test5_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0019-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-bitfields-1-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-0219.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [memleaks_test6_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memsetNonZero3.i] -Tool: SAFE -Real: SAFE - -Running test: [complex_data_creation_test02-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test14_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [length_test03-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memset.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test14_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0134.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [test-bitfields-3.1-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [ArraysOfVariableLength5.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0237.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test18_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test22_5.i] -Tool: SAFE -Real: UNSAFE - -Running test: [960521-1-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0232-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0214.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test5_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [ArraysWithLenghtAtDeclaration_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test10-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0235-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-memleak_nexttime.i] -Tool: SAFE -Real: SAFE - -Running test: [memsetNonZero.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test21-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [cmp-freed-ptr.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test16_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test22_3-1.i] -Tool: SAFE -Real: SAFE - -Running test: [ArraysOfVariableLength2_-write.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test11_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test5.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test13_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test9.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0236.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test21-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test13_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test6_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0102-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test8.i] -Tool: SAFE -Real: SAFE - -Running test: [ArraysOfVariableLength_-write.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [960521-1-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memset2_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test6_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test11_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test10-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [StructInitialization1.i] -Tool: SAFE -Real: SAFE - -Running test: [memset_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test7-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0158-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test18.i] -Tool: SAFE -Real: SAFE - -Running test: [memset3_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [960521-1-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memsetNonZero3_-write.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-0234-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test8_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test15-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-bitfields-2.1-1.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [lockfree-3.2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-bitfields-3.1-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-bitfields-3-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [ArraysOfVariableLength2.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [memleaks_test12-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0102-1.i] -Tool: SAFE -Real: SAFE - -Running test: [length_test03-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-bitfields-2.1-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-0521.i] -Tool: SAFE -Real: SAFE - -Running test: [optional_data_creation_test04-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [split_list_test05-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test6.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test4-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test22_2-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test1-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [20051113-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test17_2-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test7-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [ArraysOfVariableLength4.i] -Tool: SAFE -Real: SAFE - -Running test: [memset2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-bitfields-2-2.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [ArraysOfVariableLength.i] -Tool: UNKNOWN -Real: SAFE - -Success verified: 66 -Test [memleaks_test11] is [SAFE]: -Test [test-0158-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0232-2] is [SAFE]: -Test [StructInitialization2] is [SAFE]: -Test [lockfree-3.0] is [SAFE]: -Test [memleaks_test12-2] is [SAFE]: -Test [memleaks_test1-3] is [SAFE]: -Test [complex_data_creation_test01-2] is [SAFE]: -Test [ArraysOfVariableLength6] is [SAFE]: -Test [ArraysWithLenghtAtDeclaration] is [SAFE]: -Test [memsetNonZero2] is [SAFE]: -Test [test-0232-3] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test19-1] is [SAFE]: -Test [test-0019-1] is [SAFE]: -Test [memleaks_test20-2] is [SAFE]: -Test [memleaks_test3-2] is [SAFE]: -Test [memleaks_test16] is [SAFE]: -Test [memleaks_test17_1-2] is [SAFE]: -Test [memleaks_test23_3] is [SAFE]: -Test [test-0234-1] is [SAFE]: -Test [test-0158-3] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test22_1-2] is [SAFE]: -Test [memleaks_test14] is [SAFE]: -Test [memset3] is [SAFE]: -Test [c.03-alloca-2] is [SAFE]: -Test [StructInitialization] is [SAFE]: -Test [memleaks_test13] is [SAFE]: -Test [memleaks_test23_1] is [SAFE]: -Test [test-0513] is [SAFE]: -Test [test-0019-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memsetNonZero3] is [SAFE]: -Test [length_test03-1] is [SAFE]: -Test [memset] is [SAFE]: -Test [ArraysOfVariableLength5] is [SAFE]: -Test [test-0237] is [SAFE]: -Test [960521-1-3] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [test-0232-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test10-2] is [SAFE]: -Test [test-0235-2] is [SAFE]: -Test [test-memleak_nexttime] is [SAFE]: -Test [memsetNonZero] is [SAFE]: -Test [cmp-freed-ptr] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test22_3-1] is [SAFE]: -Test [memleaks_test5] is [SAFE]: -Test [memleaks_test9] is [SAFE]: -Test [test-0236] is [SAFE]: -Test [memleaks_test21-2] is [SAFE]: -Test [memleaks_test8] is [SAFE]: -Test [960521-1-1] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [StructInitialization1] is [SAFE]: -Test [memleaks_test7-2] is [SAFE]: -Test [test-0158-1] is [SAFE]: -Test [memleaks_test18] is [SAFE]: -Test [960521-1-2] is [SAFE]: -Test [memleaks_test15-2] is [SAFE]: -Test [test-bitfields-3.1-2] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [test-bitfields-3-2] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [test-0102-1] is [SAFE]: -Test [test-0521] is [SAFE]: -Test [split_list_test05-2] is [SAFE]: -Test [memleaks_test6] is [SAFE]: -Test [memleaks_test4-2] is [SAFE]: -Test [memleaks_test22_2-2] is [SAFE]: -Test [memleaks_test17_2-2] is [SAFE]: -Test [ArraysOfVariableLength4] is [SAFE]: -Test [memset2] is [SAFE]: - - -Unknown result: 18 -Test: ArraysOfVariableLength2_-read -Test: test-0137 -Test: 20020406-1 -Test: test-0220 -Test: test-0217 -Test: test-0218 -Test: test-bitfields-2-1 -Test: ArraysOfVariableLength_-read -Test: test-0219 -Test: test-0134 -Test: test-0214 -Test: ArraysOfVariableLength2_-write -Test: ArraysOfVariableLength_-write -Test: test-bitfields-2.1-1 -Test: ArraysOfVariableLength2 -Test: 20051113-1 -Test: test-bitfields-2-2 -Test: ArraysOfVariableLength - - -Unmatch result: 53 -Test [memleaks_test17_1-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test20-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0235-3] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test1-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test22_1-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test8_2] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test16_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [ArraysWithLenghtAtDeclaration_-read] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test22_4] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test23_4] is [UNSAFE]: -Real error: ['valid-deref'] -Test [complex_data_creation_test01-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test9_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test22_2-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test18_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [lockfree-3.1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test14_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test17_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test23_2] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test19-2] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test18_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test15-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [split_list_test05-1] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test3-1] is [UNSAFE]: -Real error: ['valid-free'] -Test [test-0235-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test9_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test17_2-1] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test4-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test22_3-2] is [UNSAFE]: -Real error: ['valid-deref'] -Test [lockfree-3.3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test5_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test6_2] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test14_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test14_3] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test18_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test22_5] is [UNSAFE]: -Real error: ['valid-deref'] -Test [memleaks_test5_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test21-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test16_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test11_1] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test13_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test13_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test6_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0102-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test6_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test11_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test10-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0234-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test8_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [lockfree-3.2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test12-1] is [UNSAFE]: -Real error: ['valid-free'] -Test [length_test03-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test1-2] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test7-1] is [UNSAFE]: -Real error: ['valid-memtrack'] - - -Raise exception: 17 -memsetNonZero2_-write -test-bitfields-1-1 -test-bitfields-3-1 -test-0504 -complex_data_creation_test02-2 -memsetNonZero_-write -optional_data_creation_test04-2 -test-bitfields-1-2 -complex_data_creation_test02-1 -test-bitfields-3.1-1 -ArraysWithLenghtAtDeclaration_-write -memset2_-write -memset_-write -memset3_-write -memsetNonZero3_-write -test-bitfields-2.1-2 -optional_data_creation_test04-1 diff --git a/benchmark/MemSafety-Heap-I-Log.txt b/benchmark/MemSafety-Heap-I-Log.txt deleted file mode 100644 index 665a62ad..00000000 --- a/benchmark/MemSafety-Heap-I-Log.txt +++ /dev/null @@ -1,877 +0,0 @@ -Adding testcase [memleaks_test8] -Adding testcase [memleaks_test5] -Adding testcase [memleaks_test7-1] -Test case [ArraysOfVariableLength2_-read] leak of .c/.i file -Adding testcase [split_list_test05-1] -Test case [memset_-write] leak of .c/.i file -Adding testcase [length_test03-2] -Test case [StructInitialization] leak of .c/.i file -Adding testcase [test-0102-2] -Adding testcase [complex_data_creation_test01-2] -Test case [StructInitialization2] leak of .c/.i file -Adding testcase [test-bitfields-2-2] -Adding testcase [test-bitfields-3-2] -Adding testcase [test-0521] -Adding testcase [test-0220] -Adding testcase [memleaks_test12-1] -Adding testcase [memleaks_test14_1] -Adding testcase [memleaks_test8_1] -Adding testcase [memleaks_test6_2] -Adding testcase [20020406-1] -Adding testcase [memleaks_test23_2] -Adding testcase [test-0219] -Adding testcase [memleaks_test11_1] -Adding testcase [memleaks_test9_2] -Adding testcase [test-0232-1] -Adding testcase [memleaks_test11_2] -Test case [memsetNonZero3_-write] leak of .c/.i file -Adding testcase [test-0235-2] -Test case [memsetNonZero3] leak of .c/.i file -Adding testcase [length_test03-1] -Adding testcase [test-0137] -Adding testcase [test-0019-2] -Adding testcase [memleaks_test18_1] -Adding testcase [memleaks_test22_2-1] -Adding testcase [memleaks_test17_3] -Adding testcase [test-0237] -Adding testcase [memleaks_test8_2] -Adding testcase [memleaks_test10-1] -Adding testcase [memleaks_test22_1-2] -Adding testcase [test-bitfields-3-1] -Adding testcase [test-0102-1] -Adding testcase [memleaks_test20-2] -Adding testcase [memleaks_test5_2] -Adding testcase [memleaks_test1-2] -Adding testcase [memleaks_test5_1] -Adding testcase [memleaks_test23_3] -Test case [memsetNonZero2_-write] leak of .c/.i file -Adding testcase [memleaks_test6_3] -Adding testcase [memleaks_test6_1] -Test case [ArraysOfVariableLength5] leak of .c/.i file -Adding testcase [test-bitfields-2-1] -Adding testcase [test-0158-3] -Adding testcase [memleaks_test1-1] -Adding testcase [lockfree-3.3] -Adding testcase [memleaks_test19-1] -Adding testcase [memleaks_test17_2-1] -Adding testcase [test-0217] -Test case [ArraysWithLenghtAtDeclaration_-read] leak of .c/.i file -Adding testcase [test-0218] -Adding testcase [optional_data_creation_test04-2] -Adding testcase [test-0504] -Adding testcase [memleaks_test13_1] -Test case [memset] leak of .c/.i file -Adding testcase [test-0158-1] -Adding testcase [memleaks_test20-1] -Adding testcase [memleaks_test4-2] -Adding testcase [complex_data_creation_test02-1] -Adding testcase [lockfree-3.2] -Adding testcase [test-bitfields-3.1-2] -Test case [memset3] leak of .c/.i file -Adding testcase [memleaks_test12-2] -Adding testcase [memleaks_test13] -Adding testcase [20051113-1] -Adding testcase [test-bitfields-1-2] -Adding testcase [memleaks_test4-1] -Adding testcase [memleaks_test22_3-1] -Adding testcase [memleaks_test14_2] -Adding testcase [memleaks_test17_2-2] -Test case [StructInitialization1] leak of .c/.i file -Adding testcase [memleaks_test17_1-1] -Adding testcase [split_list_test05-2] -Test case [memset3_-write] leak of .c/.i file -Test case [ArraysOfVariableLength] leak of .c/.i file -Adding testcase [test-0234-2] -Adding testcase [memleaks_test15-2] -Adding testcase [memleaks_test18_3] -Adding testcase [memleaks_test9] -Test case [ArraysWithLenghtAtDeclaration_-write] leak of .c/.i file -Adding testcase [memleaks_test22_3-2] -Adding testcase [memleaks_test14_3] -Adding testcase [test-bitfields-2.1-1] -Test case [ArraysOfVariableLength2_-write] leak of .c/.i file -Adding testcase [cmp-freed-ptr] -Adding testcase [test-0134] -Adding testcase [lockfree-3.1] -Adding testcase [memleaks_test3-1] -Adding testcase [memleaks_test7-2] -Adding testcase [memleaks_test22_5] -Adding testcase [c.03-alloca-2] -Adding testcase [memleaks_test23_4] -Adding testcase [complex_data_creation_test01-1] -Adding testcase [960521-1-3] -Test case [ArraysOfVariableLength_-write] leak of .c/.i file -Adding testcase [test-bitfields-1-1] -Test case [memsetNonZero2] leak of .c/.i file -Adding testcase [test-0232-2] -Test case [ArraysOfVariableLength_-read] leak of .c/.i file -Adding testcase [memleaks_test13_2] -Adding testcase [lockfree-3.0] -Adding testcase [memleaks_test21-2] -Adding testcase [960521-1-1] -Adding testcase [memleaks_test22_1-1] -Adding testcase [memleaks_test15-1] -Adding testcase [memleaks_test22_2-2] -Test case [ArraysOfVariableLength6] leak of .c/.i file -Adding testcase [memleaks_test18_2] -Adding testcase [test-bitfields-3.1-1] -Test case [memsetNonZero] leak of .c/.i file -Adding testcase [test-memleak_nexttime] -Adding testcase [memleaks_test1-3] -Adding testcase [optional_data_creation_test04-1] -Adding testcase [memleaks_test10-2] -Adding testcase [test-0232-3] -Adding testcase [memleaks_test6] -Test case [ArraysOfVariableLength2] leak of .c/.i file -Adding testcase [memleaks_test16] -Adding testcase [960521-1-2] -Adding testcase [memleaks_test22_4] -Adding testcase [memleaks_test16_1] -Adding testcase [memleaks_test19-2] -Adding testcase [memleaks_test11] -Test case [ArraysWithLenghtAtDeclaration] leak of .c/.i file -Adding testcase [memleaks_test23_1] -Adding testcase [memleaks_test9_1] -Test case [memsetNonZero_-write] leak of .c/.i file -Adding testcase [complex_data_creation_test02-2] -Adding testcase [memleaks_test14] -Adding testcase [test-bitfields-2.1-2] -Adding testcase [test-0235-1] -Test case [memset2] leak of .c/.i file -Adding testcase [test-0234-1] -Adding testcase [memleaks_test3-2] -Test case [memset2_-write] leak of .c/.i file -Adding testcase [memleaks_test18] -Adding testcase [test-0158-2] -Test case [ArraysOfVariableLength4] leak of .c/.i file -Adding testcase [test-0513] -Adding testcase [test-0236] -Adding testcase [memleaks_test21-1] -Adding testcase [test-0235-3] -Adding testcase [test-0019-1] -Adding testcase [memleaks_test16_2] -Adding testcase [memleaks_test17_1-2] -Adding testcase [test-0214] -Running test: [memleaks_test8.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test5.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test7-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [split_list_test05-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [length_test03-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0102-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [complex_data_creation_test01-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-bitfields-2-2.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [test-bitfields-3-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0521.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0220.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test12-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test14_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test8_1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test6_2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [20020406-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test23_2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-0219.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [memleaks_test11_1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test9_2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0232-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test11_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0235-2.i] -Tool: SAFE -Real: SAFE - -Running test: [length_test03-1.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0137.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-0019-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test18_1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test22_2-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test17_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0237.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test8_2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test10-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test22_1-2.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [test-bitfields-3-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-0102-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test20-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test5_2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test1-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test5_1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test23_3.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [memleaks_test6_3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test6_1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-bitfields-2-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-0158-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test1-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [lockfree-3.3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test19-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test17_2-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0217.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-0218.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [optional_data_creation_test04-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-0504.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test13_1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-0158-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test20-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test4-2.i] -Tool: SAFE -Real: SAFE - -Running test: [complex_data_creation_test02-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [lockfree-3.2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-bitfields-3.1-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test12-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test13.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [20051113-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [test-bitfields-1-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test4-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test22_3-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test14_2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test17_2-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [memleaks_test17_1-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [split_list_test05-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0234-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test15-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test18_3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test9.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test22_3-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test14_3.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-bitfields-2.1-1.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [cmp-freed-ptr.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0134.i] -Tool: UNKNOWN -Real: SAFE - -Running test: [lockfree-3.1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test3-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test7-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [memleaks_test22_5.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [c.03-alloca-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_4.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [complex_data_creation_test01-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [960521-1-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-bitfields-1-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-0232-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test13_2.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [lockfree-3.0.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test21-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [960521-1-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test22_1-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test15-1.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [memleaks_test22_2-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test18_2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-bitfields-3.1-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-memleak_nexttime.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test1-3.i] -Tool: SAFE -Real: SAFE - -Running test: [optional_data_creation_test04-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test10-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0232-3.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test6.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test16.i] -Tool: SAFE -Real: SAFE - -Running test: [960521-1-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test22_4.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test16_1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test19-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [memleaks_test11.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test23_1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [memleaks_test9_1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [complex_data_creation_test02-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [memleaks_test14.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [test-bitfields-2.1-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [test-0235-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0234-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test3-2.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test18.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0158-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0513.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0236.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test21-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [test-0235-3.i] -Tool: SAFE -Real: UNSAFE - -Running test: [test-0019-1.i] -Tool: SAFE -Real: SAFE - -Running test: [memleaks_test16_2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [memleaks_test17_1-2.i] -Tool: SAFE -Real: SAFE - -Running test: [test-0214.i] -Tool: UNKNOWN -Real: UNSAFE - -Success verified: 59 -Test [memleaks_test8] is [SAFE]: -Test [memleaks_test5] is [SAFE]: -Test [memleaks_test7-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [complex_data_creation_test01-2] is [SAFE]: -Test [test-bitfields-3-2] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [test-0521] is [SAFE]: -Test [memleaks_test8_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test6_2] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test9_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0232-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0235-2] is [SAFE]: -Test [length_test03-1] is [SAFE]: -Test [test-0019-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test18_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0237] is [SAFE]: -Test [memleaks_test8_2] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test10-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0102-1] is [SAFE]: -Test [memleaks_test5_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test1-2] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test6_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test6_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0158-3] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test1-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test19-1] is [SAFE]: -Test [test-0158-1] is [SAFE]: -Test [memleaks_test20-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test4-2] is [SAFE]: -Test [test-bitfields-3.1-2] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [memleaks_test4-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [split_list_test05-2] is [SAFE]: -Test [memleaks_test15-2] is [SAFE]: -Test [memleaks_test9] is [SAFE]: -Test [cmp-freed-ptr] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [c.03-alloca-2] is [SAFE]: -Test [960521-1-3] is [UNSAFE]: -Real error: ['valid-deref'] -Inferred error: ['INVALID_DEREF'] -Test [test-0232-2] is [SAFE]: -Test [lockfree-3.0] is [SAFE]: -Test [960521-1-1] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [test-memleak_nexttime] is [SAFE]: -Test [memleaks_test1-3] is [SAFE]: -Test [memleaks_test10-2] is [SAFE]: -Test [test-0232-3] is [UNSAFE]: -Real error: ['valid-free'] -Inferred error: ['INVALID_FREE'] -Test [memleaks_test6] is [SAFE]: -Test [memleaks_test16] is [SAFE]: -Test [960521-1-2] is [SAFE]: -Test [memleaks_test16_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test11] is [SAFE]: -Test [memleaks_test9_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0234-1] is [SAFE]: -Test [memleaks_test3-2] is [SAFE]: -Test [memleaks_test18] is [SAFE]: -Test [test-0158-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0513] is [SAFE]: -Test [test-0236] is [SAFE]: -Test [memleaks_test21-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [test-0019-1] is [SAFE]: -Test [memleaks_test16_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Inferred error: ['MemLeak'] -Test [memleaks_test17_1-2] is [SAFE]: - - -Unknown result: 20 -Test: test-bitfields-2-2 -Test: test-0220 -Test: 20020406-1 -Test: test-0219 -Test: test-0137 -Test: memleaks_test22_2-1 -Test: memleaks_test22_1-2 -Test: memleaks_test23_3 -Test: test-bitfields-2-1 -Test: test-0217 -Test: test-0218 -Test: memleaks_test13_1 -Test: memleaks_test13 -Test: 20051113-1 -Test: test-bitfields-2.1-1 -Test: test-0134 -Test: memleaks_test23_4 -Test: memleaks_test13_2 -Test: memleaks_test15-1 -Test: test-0214 - - -Unmatch result: 22 -Test [split_list_test05-1] is [UNSAFE]: -Real error: ['valid-deref'] -Test [length_test03-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0102-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test14_1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test11_1] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test11_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test17_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [lockfree-3.3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test17_2-1] is [UNSAFE]: -Real error: ['valid-free'] -Test [lockfree-3.2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test17_2-2] is [SAFE]: -Inferred error: ['INVALID_DEREF'] -Test [memleaks_test17_1-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0234-2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test18_3] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [lockfree-3.1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test3-1] is [UNSAFE]: -Real error: ['valid-free'] -Test [memleaks_test7-2] is [SAFE]: -Inferred error: ['MemLeak'] -Test [complex_data_creation_test01-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test18_2] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [memleaks_test19-2] is [UNSAFE]: -Real error: ['valid-free'] -Test [test-0235-1] is [UNSAFE]: -Real error: ['valid-memtrack'] -Test [test-0235-3] is [UNSAFE]: -Real error: ['valid-deref'] - - -Raise exception: 26 -memleaks_test12-1 -memleaks_test23_2 -test-bitfields-3-1 -memleaks_test20-2 -memleaks_test5_1 -optional_data_creation_test04-2 -test-0504 -complex_data_creation_test02-1 -memleaks_test12-2 -test-bitfields-1-2 -memleaks_test22_3-1 -memleaks_test14_2 -memleaks_test22_3-2 -memleaks_test14_3 -memleaks_test22_5 -test-bitfields-1-1 -memleaks_test21-2 -memleaks_test22_1-1 -memleaks_test22_2-2 -test-bitfields-3.1-1 -optional_data_creation_test04-1 -memleaks_test22_4 -memleaks_test23_1 -complex_data_creation_test02-2 -memleaks_test14 -test-bitfields-2.1-2 diff --git a/benchmark/MemSafety-LinkedLists-C-Log.txt b/benchmark/MemSafety-LinkedLists-C-Log.txt deleted file mode 100644 index eacfc91a..00000000 --- a/benchmark/MemSafety-LinkedLists-C-Log.txt +++ /dev/null @@ -1,331 +0,0 @@ -Adding testcase [bubble_sort_linux-2] -Adding testcase [splice-1] -Adding testcase [list-2] -Adding testcase [dll-queue-2] -Adding testcase [sll-buckets-2] -Adding testcase [dll_circular_traversal-2] -Adding testcase [sll_nondet_insert-1] -Adding testcase [dll-reverse] -Adding testcase [splice-2] -Adding testcase [sll-simple-white-blue-2] -Adding testcase [sll-optional-1] -Adding testcase [sll-rb-cnstr_1-2] -Adding testcase [sll_length_check-2] -Test case [ddv_machzwd_inw_p] leak of .c file -Adding testcase [dll-rb-sentinel-1] -Test case [ddv_machzwd_all] leak of .c file -Adding testcase [sll-queue-2] -Adding testcase [sll-token-2] -Adding testcase [sll-reverse_simple] -Adding testcase [sll-queue-1] -Adding testcase [dll-simple-white-blue-1] -Adding testcase [sll-01-2] -Adding testcase [alternating_list-1] -Adding testcase [sll2c_remove_all_reverse] -Adding testcase [dll-01-2] -Adding testcase [dll_nondet_free_order-2] -Adding testcase [dll2c_remove_all] -Adding testcase [sll_of_sll_nondet_append-2] -Adding testcase [sll_shallow_copy-1] -Adding testcase [dll2c_insert_unequal] -Adding testcase [dancing] -Adding testcase [sll2c_prepend_unequal] -Adding testcase [dll-rb-sentinel-2] -Adding testcase [sll-sorted-2] -Adding testcase [sll-sorted-1] -Adding testcase [list_search-2] -Adding testcase [dll2n_remove_all] -Adding testcase [merge_sort-1] -Adding testcase [dll_of_dll-1] -Adding testcase [sll2c_insert_unequal] -Adding testcase [dll2c_update_all_reverse] -Adding testcase [dll-circular-1] -Adding testcase [dll-rb-cnstr_1-1] -Adding testcase [dll2c_remove_all_reverse] -Adding testcase [sll2n_insert_equal] -Test case [ddv_machzwd_outb] leak of .c file -Adding testcase [dll2n_prepend_equal] -Adding testcase [sll2n_insert_unequal] -Adding testcase [sll_to_dll_rev-1] -Adding testcase [sll2c_remove_all] -Adding testcase [dll2n_insert_unequal] -Adding testcase [dll2n_prepend_unequal] -Adding testcase [tree-2] -Adding testcase [sll-simple-white-blue-1] -Adding testcase [merge_sort-2] -Adding testcase [tree-3] -Test case [ddv_machzwd_pthread_mutex_unlock] leak of .c file -Adding testcase [sll2c_append_unequal] -Adding testcase [dll2c_insert_equal] -Adding testcase [sll-rb-cnstr_1-1] -Adding testcase [dll-sorted-2] -Adding testcase [sll2n_update_all_reverse] -Adding testcase [sll_circular_traversal-1] -Adding testcase [sll_shallow_copy-2] -Adding testcase [sll2n_update_all] -Adding testcase [dll-sorted-1] -Adding testcase [dll2n_insert_equal] -Test case [ddv_machzwd_inl_p] leak of .c file -Adding testcase [sll2c_append_equal] -Adding testcase [sll2c_update_all] -Adding testcase [sll-rb-sentinel-1] -Test case [ddv_machzwd_outl_p] leak of .c file -Adding testcase [dll-optional-2] -Adding testcase [sll-01-1] -Adding testcase [dll_nullified-2] -Adding testcase [sll2n_prepend_unequal] -Adding testcase [list_search-1] -Adding testcase [dll2n_update_all] -Adding testcase [dll-optional-1] -Adding testcase [dll2c_update_all] -Adding testcase [sll2n_append_unequal] -Adding testcase [simple-2] -Adding testcase [list_flag-2] -Adding testcase [sll2c_prepend_equal] -Adding testcase [dll-token-2] -Adding testcase [sll-circular-2] -Adding testcase [dll_nullified-1] -Adding testcase [dll-queue-1] -Adding testcase [dll_nondet_free_order-1] -Adding testcase [bubble_sort_linux-1] -Adding testcase [simple_built_from_end] -Adding testcase [dll-rb-cnstr_1-2] -Adding testcase [sll2n_prepend_equal] -Adding testcase [dll2c_prepend_equal] -Adding testcase [dll2n_append_equal] -Test case [ddv_machzwd_outw_p] leak of .c file -Adding testcase [list_flag-1] -Adding testcase [sll2n_remove_all_reverse] -Adding testcase [simple-1] -Adding testcase [dll-simple-white-blue-2] -Adding testcase [sll2c_update_all_reverse] -Adding testcase [dll2n_remove_all_reverse] -Adding testcase [dll2n_update_all_reverse] -Adding testcase [sll_to_dll_rev-2] -Adding testcase [dll-circular-2] -Adding testcase [dll2c_prepend_unequal] -Adding testcase [sll-circular-1] -Adding testcase [dll-01-1] -Adding testcase [sll_length_check-1] -Adding testcase [sll-rb-sentinel-2] -Adding testcase [tree-4] -Adding testcase [dll2c_append_equal] -Adding testcase [sll2c_insert_equal] -Test case [ddv_machzwd_inb] leak of .c file -Adding testcase [list-1] -Test case [ddv_machzwd_inl] leak of .c file -Adding testcase [sll2n_append_equal] -Adding testcase [dll_circular_traversal-1] -Adding testcase [alternating_list-2] -Adding testcase [sll2n_remove_all] -Adding testcase [sll_nondet_insert-2] -Adding testcase [dll2n_append_unequal] -Adding testcase [dll_of_dll-2] -Adding testcase [sll_of_sll_nondet_append-1] -Adding testcase [sll_circular_traversal-2] -Adding testcase [dll-token-1] -Test case [ddv_machzwd_outl] leak of .c file -Adding testcase [sll-token-1] -Adding testcase [dll2c_append_unequal] -Adding testcase [sll-optional-2] -Adding testcase [tree-1] -Adding testcase [sll-buckets-1] -Test case [ddv_machzwd_inw] leak of .c file -Test case [ddv_machzwd_inb_p] leak of .c file -Test case [ddv_machzwd_outb_p] leak of .c file -Running test: [bubble_sort_linux-2.i] -Tool: UNKNOWN -Real: UNSAFE - -Running test: [splice-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [list-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [dll-queue-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll-buckets-2.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [dll_circular_traversal-2.i] -Tool: UNSAFE -Real: SAFE - -Running test: [sll_nondet_insert-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [dll-reverse.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [splice-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll-simple-white-blue-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll-optional-1.i] -Tool: SAFE -Real: SAFE - -Running test: [sll-rb-cnstr_1-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll_length_check-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll-rb-sentinel-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll-queue-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll-token-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll-reverse_simple.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll-queue-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll-simple-white-blue-1.i] -Tool: UNSAFE -Real: UNSAFE - -Running test: [sll-01-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [alternating_list-1.i] -Tool: SAFE -Real: SAFE - -Running test: [sll2c_remove_all_reverse.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll-01-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll_nondet_free_order-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [dll2c_remove_all.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll_of_sll_nondet_append-2.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [sll_shallow_copy-1.i] -Tool: UNSAFE -Real: SAFE - -Running test: [dll2c_insert_unequal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dancing.i] -Tool: SAFE -Real: UNSAFE - -Running test: [sll2c_prepend_unequal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll-rb-sentinel-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll-sorted-2.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll-sorted-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [list_search-2.i] -Tool: SAFE -Real: UNSAFE - -Running test: [dll2n_remove_all.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [merge_sort-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [dll_of_dll-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll2c_insert_unequal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll2c_update_all_reverse.i] -Tool: SAFE -Real: SAFE - -Running test: [dll-circular-1.i] -Tool: RAISE EXCEPTION -Real: UNSAFE - -Running test: [dll-rb-cnstr_1-1.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll2c_remove_all_reverse.i] -Tool: UNSAFE -Real: SAFE - -Running test: [sll2n_insert_equal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll2n_prepend_equal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [sll2n_insert_unequal.i] -Tool: SAFE -Real: SAFE - -Running test: [sll_to_dll_rev-1.i] -Tool: SAFE -Real: UNSAFE - -Running test: [sll2c_remove_all.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll2n_insert_unequal.i] -Tool: RAISE EXCEPTION -Real: SAFE - -Running test: [dll2n_prepend_unequal.i] -Tool: RAISE EXCEPTION -Real: SAFE - diff --git a/benchmark/case_1.out b/benchmark/case_1.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_1.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_10.out b/benchmark/case_10.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_10.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_11.out b/benchmark/case_11.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_11.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_12.out b/benchmark/case_12.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_12.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_13.out b/benchmark/case_13.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_13.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_14.out b/benchmark/case_14.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_14.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_15.out b/benchmark/case_15.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_15.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_16.out b/benchmark/case_16.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_16.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_2.out b/benchmark/case_2.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_2.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_3.out b/benchmark/case_3.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_3.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_4.out b/benchmark/case_4.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_4.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_5.out b/benchmark/case_5.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_5.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_6.out b/benchmark/case_6.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_6.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_7.out b/benchmark/case_7.out deleted file mode 100644 index 2ed2d25f..00000000 --- a/benchmark/case_7.out +++ /dev/null @@ -1 +0,0 @@ -UNSAFE \ No newline at end of file diff --git a/benchmark/case_8.out b/benchmark/case_8.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_8.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/case_9.out b/benchmark/case_9.out deleted file mode 100644 index 782dd6d0..00000000 --- a/benchmark/case_9.out +++ /dev/null @@ -1 +0,0 @@ -SAFE \ No newline at end of file diff --git a/benchmark/lockfree-3.1-foy2ogf6-370d5edd.bc.tmp b/benchmark/lockfree-3.1-foy2ogf6-370d5edd.bc.tmp deleted file mode 100644 index e69de29b..00000000 diff --git a/benchmark/run_test_c.py b/benchmark/run_test_c.py deleted file mode 100644 index b89645c9..00000000 --- a/benchmark/run_test_c.py +++ /dev/null @@ -1,185 +0,0 @@ -import os -import sys -import yaml - - -class TestRunner(): - def __init__(self, path='./', propertyType='out'): - self.path = path - self.testCases = [] # triple list - self.error = {} - self.inference_error = {} - self.propertyType = propertyType - self.safeCase = set() - self.doInit() - self.success = [] - self.unmatch = [] - self.unknown = [] - self.raiseExeception = [] - - - def prework4TestCases(self, fileNames): - c_file = {} - out_file = {} - files = set() - for file_name in fileNames: - file_info = file_name.split('.') - # if len(file_info) > 2: - # print('File {} name error! should be xxx.xx'.format(file_name)) - # continue - file_type = file_info[-1] - file_name = file_name[:-len(file_type)-1] - if file_type not in {'c', self.propertyType}: - continue - files.add(file_name) - if file_type == 'c': - c_file[file_name] = True - elif file_type == self.propertyType: - out_file[file_name] = True - - for name in files: - if c_file.get(name) is None: - print('Test case [{}] leak of .c file'.format(name)) - continue - if out_file.get(name) is None: - print('Test case [{}] leak of {} file'.format(name, self.propertyType)) - continue - print('Adding testcase [{}]'.format(name)) - out_file_name = '{}.{}'.format(name, self.propertyType) - program_property = self.processPrpertyFile(out_file_name) - self.testCases.append((name, program_property)) - - def walkDict(self): - file_names = os.listdir(self.path) - self.prework4TestCases(file_names) - - def doInit(self): - self.walkDict() - - def run(self): - for name, prop in self.testCases: - try: - command = 'sesl {}/{} -ll {}/{}_IR.ll --bpl {}/{}.bpl -t --sh-mem-leak 2>1 1>>{}.log'.format(self.path, - name + '.c', - self.path, - name, - self.path, - name, - self.path + '/' + name) - # print(command, os.system(command)) - os.system(command) - except Exception as e: - print('hahahhaah') - - command = 'rm -rf main.mem.dot 1' - # print(command, os.system(command)) - os.system(command) - - def checkVerify(filePath, programName = None): - f = open(filePath) - ret = "SAFE" - for line in f.readlines(): - if 'CHECKFAILED' in line: - info = line.split(':')[-1] - self.inference_error.setdefault(programName, []).append(info.strip('\n').strip('!').strip(' ')) - ret = "UNSAFE" - if 'Exception' in line: - ret = "RAISE EXCEPTION" - if 'Stack dump' in line: - ret = "RAISE EXCEPTION" - if 'CHECKUNKNOWN' in line: - ret = "UNKNOWN" - f.close() - return ret - - file_path = self.path + '/' + name + '.log' - result = checkVerify(file_path, name) - print("Running test: [{}]".format(name + '.i')) - print("Tool: " + result + '\nReal: ' + prop + "\n") - command = 'rm -rf ' + file_path - if result != "RAISE EXCEPTION": - os.system(command) - - if result == "RAISE EXCEPTION": - self.raiseExeception.append(name) - elif result == "UNKNOWN": - self.unknown.append(name) - elif result != prop: - self.unmatch.append(name) - elif result == prop: - self.success.append(name) - - def processPrpertyFile(self, outFileName): - f = open(self.path + '/' + outFileName) - file_name = outFileName[:-4] - program_property = "UNKNOWN" - if self.propertyType == 'out': - for line in f.readlines(): - if 'UNSAFE' == line: - program_property = 'UNSAFE' - elif 'SAFE' == line: - program_property = 'SAFE' - elif self.propertyType == 'yml': - yml = yaml.load(f, Loader=yaml.FullLoader) - properties = yml['properties'] - program_property = 'SAFE' - for prop in properties: - if 'expected_verdict' in prop: - if not prop['expected_verdict']: - program_property = 'UNSAFE' - if 'subproperty' in prop: - self.error.setdefault(file_name, []).append(prop['subproperty']) - else: - prop_file = prop['property_file'] - self.error.setdefault(file_name, []).append(prop_file.split('/')[-1].split('.')[0]) - f.close() - if program_property == 'SAFE': - self.safeCase.add(file_name) - return program_property - - def printCheckInfo(self): - print("Success verified: {}".format(len(self.success))) - for suc in self.success: - prop = "UNSAFE" - if suc in self.safeCase: - prop = "SAFE" - print("Test [{}] is [{}]:".format(suc, prop)) - if suc in self.error: - print('Real error:\t', self.error[suc]) - if suc in self.inference_error: - print('Inferred error:\t', self.inference_error[suc]) - print('\n') - print("Unknown result: {}".format(len(self.unknown))) - for unk in self.unknown: - print("Test: {}".format(unk)) - print('\n') - print("Unmatch result: {}".format(len(self.unmatch))) - for unm in self.unmatch: - prop = "UNSAFE" - if unm in self.safeCase: - prop = "SAFE" - print("Test [{}] is [{}]:".format(unm, prop)) - if unm in self.error: - print('Real error:\t', self.error[unm]) - if unm in self.inference_error: - print('Inferred error:\t', self.inference_error[unm]) - print('\n') - print('Raise exception: {}'.format(len(self.raiseExeception))) - for re in self.raiseExeception: - print(re) - - def clean(self): - for name, prop in self.testCases: - ll_path = '{}/{}_IR.ll'.format(self.path, name) - bpl_path = '{}/{}.bpl'.format(self.path, name) - os.system('rm -rf {}'.format(ll_path)) - os.system('rm -rf {}'.format(bpl_path)) - - -if __name__ == "__main__": - in_path = sys.argv[1] or './' - prop_type = sys.argv[2] or 'out' - testRunner = TestRunner(in_path, prop_type) - testRunner.run() - testRunner.printCheckInfo() - testRunner.clean() diff --git a/benchmark/run_test_i.py b/benchmark/run_test_i.py deleted file mode 100644 index 8f783ab3..00000000 --- a/benchmark/run_test_i.py +++ /dev/null @@ -1,185 +0,0 @@ -import os -import sys -import yaml - - -class TestRunner(): - def __init__(self, path='./', propertyType='out'): - self.path = path - self.testCases = [] # triple list - self.error = {} - self.inference_error = {} - self.propertyType = propertyType - self.safeCase = set() - self.doInit() - self.success = [] - self.unmatch = [] - self.unknown = [] - self.raiseExeception = [] - - - def prework4TestCases(self, fileNames): - c_file = {} - out_file = {} - files = set() - for file_name in fileNames: - file_info = file_name.split('.') - # if len(file_info) > 2: - # print('File {} name error! should be xxx.xx'.format(file_name)) - # continue - file_type = file_info[-1] - file_name = file_name[:-len(file_type)-1] - if file_type not in {'i', self.propertyType}: - continue - files.add(file_name) - if file_type == 'i': - c_file[file_name] = True - elif file_type == self.propertyType: - out_file[file_name] = True - - for name in files: - if c_file.get(name) is None: - print('Test case [{}] leak of .c/.i file'.format(name)) - continue - if out_file.get(name) is None: - print('Test case [{}] leak of {} file'.format(name, self.propertyType)) - continue - print('Adding testcase [{}]'.format(name)) - out_file_name = '{}.{}'.format(name, self.propertyType) - program_property = self.processPrpertyFile(out_file_name) - self.testCases.append((name, program_property)) - - def walkDict(self): - file_names = os.listdir(self.path) - self.prework4TestCases(file_names) - - def doInit(self): - self.walkDict() - - def run(self): - for name, prop in self.testCases: - try: - command = 'sesl {}/{} -ll {}/{}_IR.ll --bpl {}/{}.bpl -t --sh-mem-leak 2>1 1>>{}.log'.format(self.path, - name + '.i', - self.path, - name, - self.path, - name, - self.path + '/' + name) - # print(command, os.system(command)) - os.system(command) - except Exception as e: - print('hahahhaah') - - command = 'rm -rf main.mem.dot 1' - # print(command, os.system(command)) - os.system(command) - - def checkVerify(filePath, programName = None): - f = open(filePath) - ret = "SAFE" - for line in f.readlines(): - if 'CHECKFAILED' in line: - info = line.split(':')[-1] - self.inference_error.setdefault(programName, []).append(info.strip('\n').strip('!').strip(' ')) - ret = "UNSAFE" - if 'Exception' in line: - ret = "RAISE EXCEPTION" - if 'Stack dump' in line: - ret = "RAISE EXCEPTION" - if 'CHECKUNKNOWN' in line: - ret = "UNKNOWN" - f.close() - return ret - - file_path = self.path + '/' + name + '.log' - result = checkVerify(file_path, name) - print("Running test: [{}]".format(name + '.i')) - print("Tool: " + result + '\nReal: ' + prop + "\n") - command = 'rm -rf ' + file_path - if result != "RAISE EXCEPTION": - os.system(command) - - if result == "RAISE EXCEPTION": - self.raiseExeception.append(name) - elif result == "UNKNOWN": - self.unknown.append(name) - elif result != prop: - self.unmatch.append(name) - elif result == prop: - self.success.append(name) - - def processPrpertyFile(self, outFileName): - f = open(self.path + '/' + outFileName) - file_name = outFileName[:-4] - program_property = "UNKNOWN" - if self.propertyType == 'out': - for line in f.readlines(): - if 'UNSAFE' == line: - program_property = 'UNSAFE' - elif 'SAFE' == line: - program_property = 'SAFE' - elif self.propertyType == 'yml': - yml = yaml.load(f, Loader=yaml.FullLoader) - properties = yml['properties'] - program_property = 'SAFE' - for prop in properties: - if 'expected_verdict' in prop: - if not prop['expected_verdict']: - program_property = 'UNSAFE' - if 'subproperty' in prop: - self.error.setdefault(file_name, []).append(prop['subproperty']) - else: - prop_file = prop['property_file'] - self.error.setdefault(file_name, []).append(prop_file.split('/')[-1].split('.')[0]) - f.close() - if program_property == 'SAFE': - self.safeCase.add(file_name) - return program_property - - def printCheckInfo(self): - print("Success verified: {}".format(len(self.success))) - for suc in self.success: - prop = "UNSAFE" - if suc in self.safeCase: - prop = "SAFE" - print("Test [{}] is [{}]:".format(suc, prop)) - if suc in self.error: - print('Real error:\t', self.error[suc]) - if suc in self.inference_error: - print('Inferred error:\t', self.inference_error[suc]) - print('\n') - print("Unknown result: {}".format(len(self.unknown))) - for unk in self.unknown: - print("Test: {}".format(unk)) - print('\n') - print("Unmatch result: {}".format(len(self.unmatch))) - for unm in self.unmatch: - prop = "UNSAFE" - if unm in self.safeCase: - prop = "SAFE" - print("Test [{}] is [{}]:".format(unm, prop)) - if unm in self.error: - print('Real error:\t', self.error[unm]) - if unm in self.inference_error: - print('Inferred error:\t', self.inference_error[unm]) - print('\n') - print('Raise exception: {}'.format(len(self.raiseExeception))) - for re in self.raiseExeception: - print(re) - - def clean(self): - for name, prop in self.testCases: - ll_path = '{}/{}_IR.ll'.format(self.path, name) - bpl_path = '{}/{}.bpl'.format(self.path, name) - os.system('rm -rf {}'.format(ll_path)) - os.system('rm -rf {}'.format(bpl_path)) - - -if __name__ == "__main__": - in_path = sys.argv[1] or './' - prop_type = sys.argv[2] or 'out' - testRunner = TestRunner(in_path, prop_type) - testRunner.run() - testRunner.printCheckInfo() - testRunner.clean() diff --git a/benchmark/tacas-2025/960521-1-1-mutate.c b/benchmark/tacas-2025/960521-1-1-mutate.c new file mode 100644 index 00000000..68d5c82d --- /dev/null +++ b/benchmark/tacas-2025/960521-1-1-mutate.c @@ -0,0 +1,15 @@ +#include +int *a, *b; +int n; +int main () +{ + n = 3; + a = malloc (n * sizeof(*a)); + b = malloc (n * sizeof(*b)); + *b++ = 0; + if (b[-1]) + { free(a); free(b); } // invalid free + else + { free(a); free(b); } + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/960521-1-2-mutate.c b/benchmark/tacas-2025/960521-1-2-mutate.c new file mode 100644 index 00000000..a2469604 --- /dev/null +++ b/benchmark/tacas-2025/960521-1-2-mutate.c @@ -0,0 +1,24 @@ +#include +int *a, *b; +int n; +void foo () +{ + int i; + for (i = 0; i < n; i++) + a[i] = -1; + // for (i = 0; i < n - 1; i++) + // b[i] = -1; +} +int main () +{ + n = 2; + a = malloc (n * sizeof(*a)); + b = malloc (n * sizeof(*b)); + *b++ = 0; + foo (); + if (b[2]) // invalid dereference + { free(a); free(b); } + else + { free(a); free(b-1); } + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/960521-1-2.c b/benchmark/tacas-2025/960521-1-2.c new file mode 100644 index 00000000..60cafd73 --- /dev/null +++ b/benchmark/tacas-2025/960521-1-2.c @@ -0,0 +1,26 @@ +#include +int *a, *b; +int n; +void foo () +{ + int i; + for (i = 0; i < n; i++) + a[i] = -1; + for (i = 0; i < n - 1; i++) + b[i] = -1; +} +int main () +{ + n = 2; + a = malloc (n * sizeof(*a)); + b = malloc (n * sizeof(*b)); + *b++ = 0; + foo (); + if (b[-1]) + { free(a); free(b); } + else + { free(a); free(b-1); } + return 0; +} + +// safe \ No newline at end of file diff --git a/benchmark/tacas-2025/960521-1-3-mutate.c b/benchmark/tacas-2025/960521-1-3-mutate.c new file mode 100644 index 00000000..5d7ef817 --- /dev/null +++ b/benchmark/tacas-2025/960521-1-3-mutate.c @@ -0,0 +1,15 @@ +#include +int *a, *b; +int n; +int main () +{ + n = 3; + a = malloc (n * sizeof(*a)); + b = malloc (n * sizeof(*b)); + *b++ = 0; + if (b[-2]) // invalid dereference + { free(a); free(b-1); } + else + { free(a); free(b-1); } + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/cmp-freed-ptr-mutate.c b/benchmark/tacas-2025/cmp-freed-ptr-mutate.c new file mode 100644 index 00000000..540e2888 --- /dev/null +++ b/benchmark/tacas-2025/cmp-freed-ptr-mutate.c @@ -0,0 +1,19 @@ + +#include + +int main() { + struct T { + struct T* next; + }; + struct T* x = ((void *)0); + struct T* y = ((void *)0); + y = malloc(sizeof(*y)); + free(y); + x = malloc(sizeof(*x)); + if (x == y) + { + free(x); + } + free(x); // invalid free + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit-1-mutate.c b/benchmark/tacas-2025/global-atexit-1-mutate.c new file mode 100644 index 00000000..5b6071cf --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-1-mutate.c @@ -0,0 +1,22 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +void free_g1() { + free(g); + g = ((void *)0); +} +void free_g2() { + if (g != ((void *)0)) + free(*g); +} +void h() { +} +int main() { + g = (int **) malloc(sizeof(int *)); + if (__VERIFIER_nondet_bool()) return 0; // memory leak + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) return 0; // memory leak + free_g1(); + free_g2(); + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit-1.c b/benchmark/tacas-2025/global-atexit-1.c new file mode 100644 index 00000000..ccb5b739 --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-1.c @@ -0,0 +1,19 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +int main() { + g = (int **) malloc(sizeof(int *)); + if (__VERIFIER_nondet_bool()) { + free(g); + g = ((void *)0); + return 0; + } + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) { + if (g != ((void *)0)) { free(*g); } + free(g); + g = ((void *)0); + return 0; + } + return 0; // memory leak +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit-2-mutate.c b/benchmark/tacas-2025/global-atexit-2-mutate.c new file mode 100644 index 00000000..29e9c403 --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-2-mutate.c @@ -0,0 +1,22 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +void free_g1() { + free(g); + g = ((void *)0); +} +void free_g2() { + if (g != ((void *)0)) + free(*g); +} +int main() { + g = (int **) malloc(sizeof(int *)); + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) return 0; // memory leak + free(*g); + free(g); + g = ((void *)0); + free_g2(); + free_g1(); + return 0; +} diff --git a/benchmark/tacas-2025/global-atexit-2.c b/benchmark/tacas-2025/global-atexit-2.c new file mode 100644 index 00000000..129fec4b --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-2.c @@ -0,0 +1,20 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +int main() { + g = (int **) malloc(sizeof(int *)); + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) { + + free(g); + g = ((void *)0); + if (g != ((void *)0)) { + free(*g); + } + return 0; // memory leak + } + free(*g); + free(g); + g = ((void *)0); + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit-3.c b/benchmark/tacas-2025/global-atexit-3.c new file mode 100644 index 00000000..3df742c6 --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-3.c @@ -0,0 +1,20 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +int main() { + g = (int **) malloc(sizeof(int *)); + if (__VERIFIER_nondet_bool()) { + return 0; // memory leak + } + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) { + if (g != ((void *)0)) { + free(*g); + } + return 0; // memory leak + } + free(*g); + free(g); + g = ((void *)0); + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit-5.c b/benchmark/tacas-2025/global-atexit-5.c new file mode 100644 index 00000000..7b7cbfcd --- /dev/null +++ b/benchmark/tacas-2025/global-atexit-5.c @@ -0,0 +1,30 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); + +int main() { + g = (int **) malloc(sizeof(int *)); + if (__VERIFIER_nondet_bool()) { + free(g); + g = ((void *)0); + return 0; + } + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) { + + if (g != ((void *)0)) { + free(*g); + } + free(g); + g = ((void *)0); + return 0; + } + free(*g); + free(g); + if (g != ((void *)0)) { + free(*g); // invalid dereference + } + free(g); // invalid free + g = ((void *)0); + return 0; +} \ No newline at end of file diff --git a/benchmark/tacas-2025/global-atexit.c b/benchmark/tacas-2025/global-atexit.c new file mode 100644 index 00000000..b98e5267 --- /dev/null +++ b/benchmark/tacas-2025/global-atexit.c @@ -0,0 +1,28 @@ +#include +extern _Bool __VERIFIER_nondet_bool(); +int **g = ((void *)0); +int main() { + g = (int **) malloc(sizeof(int *)); + if (__VERIFIER_nondet_bool()) { + free(g); + g = ((void *)0); + return 0; + } + *g = (int *) malloc(sizeof(int)); + if (__VERIFIER_nondet_bool()) { + if (g != ((void *)0)) { + free(*g); + } + free(g); + g = ((void *)0); + return 0; + } + if (g != ((void *)0)) { + free(*g); + } + free(g); + g = ((void *)0); + return 0; +} + +// safe \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0019-1-mutate.c b/benchmark/tacas-2025/test-0019-1-mutate.c new file mode 100644 index 00000000..cb65c3d1 --- /dev/null +++ b/benchmark/tacas-2025/test-0019-1-mutate.c @@ -0,0 +1,17 @@ +#include +typedef struct { + void *lo; + void *hi; +} TData; +int main() { + TData* pdata = malloc(sizeof(TData)); + pdata->lo = malloc(8); + pdata->hi = malloc(8); + void *lo = pdata->lo; + void *hi = pdata->hi; + if (lo == hi) + return 0; + free(lo); + free(hi); + return 0; // memory leak +} \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0019-1.c b/benchmark/tacas-2025/test-0019-1.c new file mode 100644 index 00000000..792e0edf --- /dev/null +++ b/benchmark/tacas-2025/test-0019-1.c @@ -0,0 +1,19 @@ +#include +typedef struct { + void *lo; + void *hi; +} TData; +int main() { + TData* pdata = malloc(sizeof(TData)); + pdata->lo = malloc(8); + pdata->hi = malloc(8); + void *lo = pdata->lo; + void *hi = pdata->hi; + if (lo == hi) return 0; + free(lo); + free(hi); + free(pdata); + return 0; +} + +// safe \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0019-2-mutate.c b/benchmark/tacas-2025/test-0019-2-mutate.c new file mode 100644 index 00000000..48c5c125 --- /dev/null +++ b/benchmark/tacas-2025/test-0019-2-mutate.c @@ -0,0 +1,19 @@ +#include +typedef struct { + void *lo; + void *hi; +} TData; +int main() { + TData* pdata = malloc(sizeof(TData)); + pdata->lo = malloc(8); + pdata->hi = malloc(8); + void *lo = pdata->lo; + void *hi = pdata->hi; + if (lo == hi) { + free(lo); + free(hi); + } + pdata->lo = (void *) 0; + pdata->hi = (void *) 0; + return 0; // memory leak +} \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0019-2.c b/benchmark/tacas-2025/test-0019-2.c new file mode 100644 index 00000000..3f7f3a43 --- /dev/null +++ b/benchmark/tacas-2025/test-0019-2.c @@ -0,0 +1,20 @@ +#include +typedef struct { + void *lo; + void *hi; +} TData; +int main() { + TData* pdata = malloc(sizeof(TData)); + pdata->lo = malloc(8); + pdata->hi = malloc(8); + void *lo = pdata->lo; + void *hi = pdata->hi; + if (lo == hi) { + free(lo); + free(hi); + } + pdata->lo = (void *) 0; + pdata->hi = (void *) 0; + free(pdata); + return 0; // memory leak +} \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0232-1.c b/benchmark/tacas-2025/test-0232-1.c new file mode 100644 index 00000000..5f3fd710 --- /dev/null +++ b/benchmark/tacas-2025/test-0232-1.c @@ -0,0 +1,26 @@ +#include +extern int __VERIFIER_nondet_int(void); +struct item { + struct item *next; + struct item *data; +}; +static void append(struct item **plist) +{ + struct item *item = malloc(sizeof *item); + item->next = *plist; + item->data = (item->next) + ? item->next->data + : malloc(sizeof *item); + *plist = item; +} +int main() +{ + struct item *list = ((void *)0); + append(&list); + if (list) { + struct item *next = list->next; + free(list); + list = next; + } + return 0; // memory leak +} \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0232-2-mutate.c b/benchmark/tacas-2025/test-0232-2-mutate.c new file mode 100644 index 00000000..3475b56c --- /dev/null +++ b/benchmark/tacas-2025/test-0232-2-mutate.c @@ -0,0 +1,36 @@ +#include +extern int __VERIFIER_nondet_int(void); +struct item { + struct item *next; + struct item *data; +}; +static void append(struct item **plist) +{ + struct item *item = malloc(sizeof *item); + item->next = *plist; + item->data = (item->next) + ? item->next->data + : malloc(sizeof *item); + *plist = item; +} +int main() +{ + struct item *list = ((void *)0); + int i = 0; + append(&list); + append(&list); + if (list) { + struct item *next = list->next; + free(list->data); + free(list); + list = next; + } + if (list) { + struct item *next = list->next; + free(list); + list = next; + } + return 0; +} + +// safe \ No newline at end of file diff --git a/benchmark/tacas-2025/test-0232-3-mutate.c b/benchmark/tacas-2025/test-0232-3-mutate.c new file mode 100644 index 00000000..cdb9adbd --- /dev/null +++ b/benchmark/tacas-2025/test-0232-3-mutate.c @@ -0,0 +1,35 @@ +#include +extern int __VERIFIER_nondet_int(void); +struct item { + struct item *next; + struct item *data; +}; +static void append(struct item **plist) +{ + struct item *item = malloc(sizeof *item); + item->next = *plist; + item->data = (item->next) + ? item->next->data + : malloc(sizeof *item); + *plist = item; +} +int main() +{ + struct item *list = ((void *)0); + append(&list); + append(&list); + if (list) { + struct item *next = list->next; + free(list->data); + free(list); + list = next; + } + if (list) { + struct item *next = list->next; + if (!next) + free(list->data); // invalid free + free(list); + list = next; + } + return 0; +} diff --git a/benchmark/tacas-2025/test-0513-mutate.c b/benchmark/tacas-2025/test-0513-mutate.c new file mode 100644 index 00000000..c85e8c77 --- /dev/null +++ b/benchmark/tacas-2025/test-0513-mutate.c @@ -0,0 +1,66 @@ +#include +extern int __VERIFIER_nondet_int(void); +struct DItem { + struct DItem* next; + int value; +}; +struct TLItem { + struct TLItem* next; + struct DItem* data; +}; +int main() { + struct TLItem* data = ((void *)0); + struct DItem* item, * item2; + struct TLItem *lItem; + // while (__VERIFIER_nondet_int()) { + item = malloc(sizeof *item); + item->next = ((void *)0); + item->value = __VERIFIER_nondet_int(); + lItem = malloc(sizeof *lItem); + lItem->next = lItem; + data = lItem; + lItem->data = item; + item = ((void *)0); + lItem = ((void *)0); + // } + if (!data) + return 0; + if(data->next != data) { + item = data->data; + item2 = data->next->data; + lItem = data->next; + data->next = lItem->next; + free(lItem); + struct DItem** dst = &data->data; + if (item && item2) { + if (item->value < item2->value) { + *dst = item; + item = item->next; + } else { + // go here + *dst = item2; + item2 = item2->next; + } + dst = &(*dst)->next; + } + if (item) { + *dst = item; + item = ((void *)0); + } else if (item2) { + *dst = item2; + item2 = ((void *)0); + } + dst = ((void *)0); + data = data->next; + } + item = data->data; + free(data); + if (item) { + item2 = item; + item = item->next; + free(item2); + } + return 0; +} + +// safe \ No newline at end of file diff --git a/benchmark/test-0235-3-rsv4qzsd-a33e63fa.bc.tmp b/benchmark/test-0235-3-rsv4qzsd-a33e63fa.bc.tmp deleted file mode 100644 index e69de29b..00000000 diff --git a/benchmark/test-0236-w8ksvopc-7369e031.bc.tmp b/benchmark/test-0236-w8ksvopc-7369e031.bc.tmp deleted file mode 100644 index e69de29b..00000000 diff --git a/benchmark/testWitness.graphml b/benchmark/testWitness.graphml deleted file mode 100644 index 24d7e561..00000000 --- a/benchmark/testWitness.graphml +++ /dev/null @@ -1,39 +0,0 @@ - - - - false - - - false - - - false - - - - - - - - - - - - - ../svcomp/memsafety/test-0137.i - - - - violation_witness - C - TOOL NAME - SPEC - ../svcomp/memsafety/test-0137.i - 64 - 2021-10-03T11:19:15Z - 1c2d362b3c58f37a9b1e964b448eb3d54c85d26676417295a73853b3a7cc716a - - true - - - diff --git a/benchmark/case_0.c b/benchmark/tests/case_0.c similarity index 100% rename from benchmark/case_0.c rename to benchmark/tests/case_0.c diff --git a/benchmark/case_1.c b/benchmark/tests/case_1.c similarity index 100% rename from benchmark/case_1.c rename to benchmark/tests/case_1.c diff --git a/benchmark/case_10.c b/benchmark/tests/case_10.c similarity index 100% rename from benchmark/case_10.c rename to benchmark/tests/case_10.c diff --git a/benchmark/case_11.c b/benchmark/tests/case_11.c similarity index 100% rename from benchmark/case_11.c rename to benchmark/tests/case_11.c diff --git a/benchmark/case_12.c b/benchmark/tests/case_12.c similarity index 100% rename from benchmark/case_12.c rename to benchmark/tests/case_12.c diff --git a/benchmark/case_13.c b/benchmark/tests/case_13.c similarity index 100% rename from benchmark/case_13.c rename to benchmark/tests/case_13.c diff --git a/benchmark/case_14.c b/benchmark/tests/case_14.c similarity index 100% rename from benchmark/case_14.c rename to benchmark/tests/case_14.c diff --git a/benchmark/case_15.c b/benchmark/tests/case_15.c similarity index 100% rename from benchmark/case_15.c rename to benchmark/tests/case_15.c diff --git a/benchmark/case_16.c b/benchmark/tests/case_16.c similarity index 100% rename from benchmark/case_16.c rename to benchmark/tests/case_16.c diff --git a/benchmark/case_2.c b/benchmark/tests/case_2.c similarity index 100% rename from benchmark/case_2.c rename to benchmark/tests/case_2.c diff --git a/benchmark/case_3.c b/benchmark/tests/case_3.c similarity index 100% rename from benchmark/case_3.c rename to benchmark/tests/case_3.c diff --git a/benchmark/case_4.c b/benchmark/tests/case_4.c similarity index 100% rename from benchmark/case_4.c rename to benchmark/tests/case_4.c diff --git a/benchmark/case_5.c b/benchmark/tests/case_5.c similarity index 100% rename from benchmark/case_5.c rename to benchmark/tests/case_5.c diff --git a/benchmark/case_6.c b/benchmark/tests/case_6.c similarity index 100% rename from benchmark/case_6.c rename to benchmark/tests/case_6.c diff --git a/benchmark/case_7.c b/benchmark/tests/case_7.c similarity index 100% rename from benchmark/case_7.c rename to benchmark/tests/case_7.c diff --git a/benchmark/case_8.c b/benchmark/tests/case_8.c similarity index 100% rename from benchmark/case_8.c rename to benchmark/tests/case_8.c diff --git a/benchmark/case_9.c b/benchmark/tests/case_9.c similarity index 100% rename from benchmark/case_9.c rename to benchmark/tests/case_9.c From 9424186a9a1321fab0ca1357c84b40689d0d2909 Mon Sep 17 00:00:00 2001 From: clexmaAtFlankerB Date: Fri, 11 Oct 2024 23:16:26 +0800 Subject: [PATCH 126/126] stage for merge --- benchmark/case_0.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/benchmark/case_0.c b/benchmark/case_0.c index b23948d9..a5159b5f 100644 --- a/benchmark/case_0.c +++ b/benchmark/case_0.c @@ -1,8 +1,37 @@ #include - -int main(){ - int * data = malloc(sizeof(int)); - int * data2 = malloc(2*sizeof(int)); - free(data); - int i = *(data + 1); +extern int __VERIFIER_nondet_int(void); +struct item { + struct item *next; + struct item *data; +}; +static void append(struct item **plist) +{ + struct item *item = malloc(sizeof *item); + item->next = *plist; + item->data = (item->next) + ? item->next->data + : malloc(sizeof *item); + *plist = item; +} +int main() +{ + struct item *list = ((void *)0); + append(&list); + append(&list); + if (list) { + struct item *next = list->next; + free(list->data); + free(list); + list = next; + } + if (list) { + struct item *next = list->next; + if (!next) + free(list->data); + free(list); + list = next; + } + return 0; } + +// invalid free 17