void goto_program_dereferencet::dereference_failure( const std::string &property, const std::string &msg, const guardt &guard) { exprt guard_expr=guard.as_expr(); if(assertions.insert(guard_expr).second) { guard_expr.make_not(); // first try simplifier on it if(options.get_bool_option("simplify")) simplify(guard_expr, ns); if(!guard_expr.is_true()) { goto_program_instruction_typet type= options.get_bool_option("assert-to-assume")?ASSUME:ASSERT; goto_programt::targett t=new_code.add_instruction(type); t->guard.swap(guard_expr); t->source_location=dereference_location; t->source_location.set_property_class(property); t->source_location.set_comment("dereference failure: "+msg); } } }
void symex_target_equationt::assignment( const guardt &guard, const symbol_exprt &ssa_lhs, const symbol_exprt &original_lhs_object, const exprt &ssa_full_lhs, const exprt &original_full_lhs, const exprt &ssa_rhs, const sourcet &source, assignment_typet assignment_type) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.ssa_lhs=ssa_lhs; SSA_step.original_lhs_object=original_lhs_object; SSA_step.ssa_full_lhs=ssa_full_lhs; SSA_step.original_full_lhs=original_full_lhs; SSA_step.ssa_rhs=ssa_rhs; SSA_step.assignment_type=assignment_type; SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_rhs); SSA_step.type=goto_trace_stept::ASSIGNMENT; SSA_step.source=source; }
void symex_target_equationt::location( const guardt &guard, const sourcet &source) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.type=goto_trace_stept::LOCATION; SSA_step.source=source; }
void symex_target_equationt::function_return( const guardt &guard, const sourcet &source) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.type=goto_trace_stept::FUNCTION_RETURN; SSA_step.source=source; }
void symex_target_equationt::function_call( const guardt &guard, const irep_idt &identifier, const sourcet &source) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.type=goto_trace_stept::FUNCTION_CALL; SSA_step.source=source; SSA_step.identifier=identifier; }
void symex_target_equationt::assumption( const guardt &guard, const exprt &cond, const sourcet &source) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.cond_expr=cond; SSA_step.type=goto_trace_stept::ASSUME; SSA_step.source=source; }
void symex_target_equationt::assertion( const guardt &guard, const exprt &cond, const std::string &msg, const sourcet &source) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.cond_expr=cond; SSA_step.type=goto_trace_stept::ASSERT; SSA_step.source=source; SSA_step.comment=msg; }
void symex_target_equationt::input( const guardt &guard, const sourcet &source, const irep_idt &input_id, const std::list<exprt> &args) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.type=goto_trace_stept::INPUT; SSA_step.source=source; SSA_step.io_args=args; SSA_step.io_id=input_id; }
void goto_checkt::add_guarded_claim( const exprt &_expr, const std::string &comment, const std::string &property_class, const source_locationt &source_location, const exprt &src_expr, const guardt &guard) { exprt expr(_expr); // first try simplifier on it if(enable_simplify) simplify(expr, ns); // throw away trivial properties? if(!retain_trivial && expr.is_true()) return; // add the guard exprt guard_expr=guard.as_expr(); exprt new_expr; if(guard_expr.is_true()) new_expr.swap(expr); else { new_expr=exprt(ID_implies, bool_typet()); new_expr.move_to_operands(guard_expr, expr); } if(assertions.insert(new_expr).second) { goto_program_instruction_typet type= enable_assert_to_assume?ASSUME:ASSERT; goto_programt::targett t=new_code.add_instruction(type); std::string source_expr_string=from_expr(ns, "", src_expr); t->guard.swap(new_expr); t->source_location=source_location; t->source_location.set_comment(comment+" in "+source_expr_string); t->source_location.set_property_class(property_class); } }
void symex_target_equationt::output_fmt( const guardt &guard, const sourcet &source, const irep_idt &output_id, const irep_idt &fmt, const std::list<exprt> &args) { SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.type=goto_trace_stept::OUTPUT; SSA_step.source=source; SSA_step.io_args=args; SSA_step.io_id=output_id; SSA_step.formatted=true; SSA_step.format_string=fmt; }
void goto_checkt::add_guarded_claim(const exprt &_expr, const std::string &comment, const std::string &property, const locationt &location, const guardt &guard) { bool all_claims = options.get_bool_option("all-claims"); exprt expr(_expr); // first try simplifier on it if (!options.get_bool_option("no-simplify")) { expr2tc tmpexpr; migrate_expr(expr, tmpexpr); base_type(tmpexpr, ns); expr = migrate_expr_back(tmpexpr); simplify(expr); } if (!all_claims && expr.is_true()) return; // add the guard exprt guard_expr = migrate_expr_back(guard.as_expr()); exprt new_expr; if (guard_expr.is_true()) new_expr.swap(expr); else { new_expr = exprt("=>", bool_typet()); new_expr.move_to_operands(guard_expr, expr); } if (assertions.insert(new_expr).second) { goto_programt::targett t = new_code.add_instruction(ASSERT); migrate_expr(new_expr, t->guard); t->location = location; t->location.comment(comment); t->location.property(property); } }
void symex_target_equationt::decl( const guardt &guard, const symbol_exprt &ssa_lhs, const symbol_exprt &original_lhs_object, const sourcet &source) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.ssa_lhs=ssa_lhs; SSA_step.ssa_full_lhs=ssa_lhs; SSA_step.original_lhs_object=original_lhs_object; SSA_step.original_full_lhs=original_lhs_object; SSA_step.type=goto_trace_stept::DECL; SSA_step.source=source; // the condition is trivially true, and only // there so we see the symbols SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_lhs); }
void rw_sett::read_write_rec( const exprt &expr, bool r, bool w, const std::string &suffix, const guardt &guard) { if(expr.id()==ID_symbol) { const symbol_exprt &symbol_expr=to_symbol_expr(expr); const symbolt *symbol; if(!ns.lookup(symbol_expr.get_identifier(), symbol)) { if(!symbol->static_lifetime) return; // ignore for now if(symbol->thread_local) return; // must ignore if(symbol->name=="c::__CPROVER_alloc" || symbol->name=="c::__CPROVER_alloc_size" || symbol->name=="c::stdin" || symbol->name=="c::stdout" || symbol->name=="c::stderr" || symbol->name=="c::sys_nerr") return; // ignore for now } irep_idt object=id2string(symbol_expr.get_identifier())+suffix; entryt &entry=entries[object]; entry.object=object; entry.r=entry.r || r; entry.w=entry.w || w; entry.guard=guard.as_expr(); } else if(expr.id()=="member")
void goto_checkt::check_rec( const exprt &expr, guardt &guard, bool address) { // we don't look into quantifiers if(expr.id()==ID_exists || expr.id()==ID_forall) return; if(address) { if(expr.id()==ID_dereference) { assert(expr.operands().size()==1); check_rec(expr.op0(), guard, false); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); check_rec(expr.op0(), guard, true); check_rec(expr.op1(), guard, false); } else { forall_operands(it, expr) check_rec(*it, guard, true); } return; } if(expr.id()==ID_address_of) { assert(expr.operands().size()==1); check_rec(expr.op0(), guard, true); return; } else if(expr.id()==ID_and || expr.id()==ID_or) { if(!expr.is_boolean()) throw "`"+expr.id_string()+"' must be Boolean, but got "+ expr.pretty(); guardt old_guard=guard; for(unsigned i=0; i<expr.operands().size(); i++) { const exprt &op=expr.operands()[i]; if(!op.is_boolean()) throw "`"+expr.id_string()+"' takes Boolean operands only, but got "+ op.pretty(); check_rec(op, guard, false); if(expr.id()==ID_or) guard.add(not_exprt(op)); else guard.add(op); } guard.swap(old_guard); return; } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three arguments"; if(!expr.op0().is_boolean()) { std::string msg= "first argument of if must be boolean, but got " +expr.op0().pretty(); throw msg; } check_rec(expr.op0(), guard, false); { guardt old_guard=guard; guard.add(expr.op0()); check_rec(expr.op1(), guard, false); guard.swap(old_guard); } { guardt old_guard=guard; guard.add(not_exprt(expr.op0())); check_rec(expr.op2(), guard, false); guard.swap(old_guard); } return; } forall_operands(it, expr) check_rec(*it, guard, false); if(expr.id()==ID_index) { bounds_check(to_index_expr(expr), guard); } else if(expr.id()==ID_div) { div_by_zero_check(to_div_expr(expr), guard); if(expr.type().id()==ID_signedbv) integer_overflow_check(expr, guard); else if(expr.type().id()==ID_floatbv) { nan_check(expr, guard); float_overflow_check(expr, guard); } } else if(expr.id()==ID_shl || expr.id()==ID_ashr || expr.id()==ID_lshr) { undefined_shift_check(to_shift_expr(expr), guard); } else if(expr.id()==ID_mod) { mod_by_zero_check(to_mod_expr(expr), guard); } else if(expr.id()==ID_plus || expr.id()==ID_minus || expr.id()==ID_mult || expr.id()==ID_unary_minus) { if(expr.type().id()==ID_signedbv || expr.type().id()==ID_unsignedbv) { if(expr.operands().size()==2 && expr.op0().type().id()==ID_pointer) pointer_overflow_check(expr, guard); else integer_overflow_check(expr, guard); } else if(expr.type().id()==ID_floatbv) { nan_check(expr, guard); float_overflow_check(expr, guard); } else if(expr.type().id()==ID_pointer) { pointer_overflow_check(expr, guard); } } else if(expr.id()==ID_typecast) conversion_check(expr, guard); else if(expr.id()==ID_le || expr.id()==ID_lt || expr.id()==ID_ge || expr.id()==ID_gt) pointer_rel_check(expr, guard); else if(expr.id()==ID_dereference) pointer_validity_check(to_dereference_expr(expr), guard); }
void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address) { if (address) { if (expr.id() == "dereference") { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, false); } else if (expr.id() == "index") { assert(expr.operands().size() == 2); check_rec(expr.op0(), guard, true); check_rec(expr.op1(), guard, false); } else { forall_operands(it, expr) check_rec(*it, guard, true); } return; } if (expr.is_address_of()) { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, true); return; } else if (expr.is_and() || expr.id() == "or") { if (!expr.is_boolean()) throw expr.id_string() + " must be Boolean, but got " + expr.pretty(); unsigned old_guards = guard.size(); for (unsigned i = 0; i < expr.operands().size(); i++) { const exprt &op = expr.operands()[i]; if (!op.is_boolean()) throw expr.id_string() + " takes Boolean operands only, but got " + op.pretty(); check_rec(op, guard, false); if (expr.id() == "or") { exprt tmp(op); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); } else { expr2tc tmp; migrate_expr(op, tmp); guard.add(tmp); } } guard.resize(old_guards); return; } else if (expr.id() == "if") { if (expr.operands().size() != 3) throw "if takes three arguments"; if (!expr.op0().is_boolean()) { std::string msg = "first argument of if must be boolean, but got " + expr.op0().to_string(); throw msg; } check_rec(expr.op0(), guard, false); { unsigned old_guard = guard.size(); expr2tc tmp; migrate_expr(expr.op0(), tmp); guard.add(tmp); check_rec(expr.op1(), guard, false); guard.resize(old_guard); } { unsigned old_guard = guard.size(); exprt tmp(expr.op0()); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); check_rec(expr.op2(), guard, false); guard.resize(old_guard); } return; } forall_operands(it, expr) check_rec(*it, guard, false); if (expr.id() == "index") { bounds_check(expr, guard); } else if (expr.id() == "/") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "+" || expr.id() == "-" || expr.id() == "*" || expr.id() == "unary-" || expr.id() == "typecast") { if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "<=" || expr.id() == "<" || expr.id() == ">=" || expr.id() == ">") { pointer_rel_check(expr, guard); } else if (expr.id() == "mod") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } }
void goto_program_dereferencet::dereference_rec( exprt &expr, guardt &guard, const value_set_dereferencet::modet mode) { if(!dereference.has_dereference(expr)) return; if(expr.id()==ID_and || expr.id()==ID_or) { if(!expr.is_boolean()) throw expr.id_string()+" must be Boolean, but got "+ expr.pretty(); guardt old_guard=guard; for(unsigned i=0; i<expr.operands().size(); i++) { exprt &op=expr.operands()[i]; if(!op.is_boolean()) throw expr.id_string()+" takes Boolean operands only, but got "+ op.pretty(); if(dereference.has_dereference(op)) dereference_rec(op, guard, value_set_dereferencet::modet::READ); if(expr.id()==ID_or) { exprt tmp(op); tmp.make_not(); guard.add(tmp); } else guard.add(op); } guard.swap(old_guard); return; } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three arguments"; if(!expr.op0().is_boolean()) { std::string msg= "first argument of if must be boolean, but got " +expr.op0().pretty(); throw msg; } dereference_rec(expr.op0(), guard, value_set_dereferencet::modet::READ); bool o1=dereference.has_dereference(expr.op1()); bool o2=dereference.has_dereference(expr.op2()); if(o1) { guardt old_guard=guard; guard.add(expr.op0()); dereference_rec(expr.op1(), guard, mode); guard.swap(old_guard); } if(o2) { guardt old_guard=guard; exprt tmp(expr.op0()); tmp.make_not(); guard.add(tmp); dereference_rec(expr.op2(), guard, mode); guard.swap(old_guard); } return; } if(expr.id()==ID_address_of || expr.id()=="reference_to") { // turn &*p to p // this has *no* side effect! assert(expr.operands().size()==1); if(expr.op0().id()==ID_dereference) { assert(expr.op0().operands().size()==1); exprt tmp; tmp.swap(expr.op0().op0()); if(tmp.type()!=expr.type()) tmp.make_typecast(expr.type()); expr.swap(tmp); } } Forall_operands(it, expr) dereference_rec(*it, guard, mode); if(expr.id()==ID_dereference) { if(expr.operands().size()!=1) throw "dereference expects one operand"; dereference_location=expr.find_source_location(); exprt tmp=dereference.dereference( expr.op0(), guard, mode); expr.swap(tmp); } else if(expr.id()==ID_index) { // this is old stuff and will go away if(expr.operands().size()!=2) throw "index expects two operands"; if(expr.op0().type().id()==ID_pointer) { dereference_location=expr.find_source_location(); exprt tmp1(ID_plus, expr.op0().type()); tmp1.operands().swap(expr.operands()); exprt tmp2=dereference.dereference(tmp1, guard, mode); tmp2.swap(expr); } } }
void rw_sett::read_write_rec( const exprt &expr, bool r, bool w, const std::string &suffix, const guardt &guard) { if(expr.id()=="symbol" && !expr.has_operands()) { const symbol_exprt &symbol_expr=to_symbol_expr(expr); const symbolt *symbol; if(!ns.lookup(symbol_expr.get_identifier(), symbol)) { if(!symbol->static_lifetime /*&& expr.type().id()=="pointer"*/) { return; // ignore for now } if(symbol->name=="c::__ESBMC_alloc" || symbol->name=="c::__ESBMC_alloc_size" || symbol->name=="c::stdin" || symbol->name=="c::stdout" || symbol->name=="c::stderr" || symbol->name=="c::sys_nerr") { return; // ignore for now } } irep_idt object=id2string(symbol_expr.get_identifier())+suffix; entryt &entry=entries[object]; entry.object=object; entry.r=entry.r || r; entry.w=entry.w || w; entry.guard = migrate_expr_back(guard.as_expr()); } else if(expr.id()=="member") { assert(expr.operands().size()==1); const std::string &component_name=expr.component_name().as_string(); read_write_rec(expr.op0(), r, w, "."+component_name+suffix, guard); } else if(expr.id()=="index") { // we don't distinguish the array elements for now assert(expr.operands().size()==2); std::string tmp; tmp = integer2string(binary2integer(expr.op1().value().as_string(), true),10); read_write_rec(expr.op0(), r, w, "["+suffix+tmp+"]", guard); read(expr.op1(), guard); } else if(expr.id()=="dereference") { assert(expr.operands().size()==1); read(expr.op0(), guard); exprt tmp(expr.op0()); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); dereference(target, tmp_expr, ns, value_sets); tmp = migrate_expr_back(tmp_expr); read_write_rec(tmp, r, w, suffix, guard); } else if(expr.is_address_of() || expr.id()=="implicit_address_of") { assert(expr.operands().size()==1); } else if(expr.id()=="if") { assert(expr.operands().size()==3); read(expr.op0(), guard); guardt true_guard(guard); expr2tc tmp_expr; migrate_expr(expr.op0(), tmp_expr); true_guard.add(tmp_expr); read_write_rec(expr.op1(), r, w, suffix, true_guard); guardt false_guard(guard); migrate_expr(gen_not(expr.op0()), tmp_expr); false_guard.add(tmp_expr); read_write_rec(expr.op2(), r, w, suffix, false_guard); } else { forall_operands(it, expr) read_write_rec(*it, r, w, suffix, guard); } }