void goto_checkt::goto_check(goto_programt &goto_program) { for (goto_programt::instructionst::iterator it = goto_program.instructions.begin(); it != goto_program.instructions.end(); it++) { goto_programt::instructiont &i = *it; new_code.clear(); assertions.clear(); check(migrate_expr_back(i.guard)); if (i.is_other()) { if (is_code_expression2t(i.code)) { check(migrate_expr_back(i.code)); } else if (is_code_printf2t(i.code)) { i.code->foreach_operand([this] (const expr2tc &e) { check(migrate_expr_back(e)); } ); } } else if (i.is_assign()) { const code_assign2t &assign = to_code_assign2t(i.code); check(migrate_expr_back(assign.target)); check(migrate_expr_back(assign.source)); } else if (i.is_function_call()) { i.code->foreach_operand([this] (const expr2tc &e) { check(migrate_expr_back(e)); } ); } else if (i.is_return()) { const code_return2t &ret = to_code_return2t(i.code); check(migrate_expr_back(ret.operand)); } for (goto_programt::instructionst::iterator i_it = new_code.instructions.begin(); i_it != new_code.instructions.end(); i_it++) { i_it->local_variables = it->local_variables; if (i_it->location.is_nil()) { if (!i_it->location.comment().as_string().empty()) it->location.comment(i_it->location.comment()); if (!i_it->location.property().as_string().empty()) it->location.property(i_it->location.property()); i_it->location = it->location; } if (i_it->function == "") i_it->function = it->function; if (i_it->function == "") i_it->function = it->function; } // insert new instructions -- make sure targets are not moved while (!new_code.instructions.empty()) { goto_program.insert_swap(it, new_code.instructions.front()); new_code.instructions.pop_front(); it++; } } }
void goto_checkt::goto_check(goto_functiont &goto_function) { { const symbolt *init_symbol; if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol)) mode=init_symbol->mode; } assertions.clear(); local_bitvector_analysist local_bitvector_analysis_obj(goto_function); local_bitvector_analysis=&local_bitvector_analysis_obj; goto_programt &goto_program=goto_function.body; Forall_goto_program_instructions(it, goto_program) { t=it; goto_programt::instructiont &i=*it; new_code.clear(); // we clear all recorded assertions if // 1) we want to generate all assertions or // 2) the instruction is a branch target if(retain_trivial || i.is_target()) assertions.clear(); check(i.guard); // magic ERROR label? for(optionst::value_listt::const_iterator l_it=error_labels.begin(); l_it!=error_labels.end(); l_it++) { if(std::find(i.labels.begin(), i.labels.end(), *l_it)!=i.labels.end()) { goto_program_instruction_typet type= enable_assert_to_assume?ASSUME:ASSERT; goto_programt::targett t=new_code.add_instruction(type); t->guard=false_exprt(); t->source_location=i.source_location; t->source_location.set_property_class("error label"); t->source_location.set_comment("error label "+*l_it); t->source_location.set("user-provided", true); } } if(i.is_other()) { const irep_idt &statement=i.code.get(ID_statement); if(statement==ID_expression) { check(i.code); } else if(statement==ID_printf) { forall_operands(it, i.code) check(*it); } } else if(i.is_assign()) { const code_assignt &code_assign=to_code_assign(i.code); check(code_assign.lhs()); check(code_assign.rhs()); // the LHS might invalidate any assertion invalidate(code_assign.lhs()); } else if(i.is_function_call()) { const code_function_callt &code_function_call= to_code_function_call(i.code); // for Java, need to check whether 'this' is null // on non-static method invocations if(mode==ID_java && enable_pointer_check && !code_function_call.arguments().empty() && code_function_call.function().type().id()==ID_code && to_code_type(code_function_call.function().type()).has_this()) { exprt pointer=code_function_call.arguments()[0]; local_bitvector_analysist::flagst flags= local_bitvector_analysis->get(t, pointer); if(flags.is_unknown() || flags.is_null()) { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "this is null on method invokation", "pointer dereference", i.source_location, pointer, guardt()); } } forall_operands(it, code_function_call) check(*it); // the call might invalidate any assertion assertions.clear(); } else if(i.is_return()) { if(i.code.operands().size()==1) { check(i.code.op0()); // the return value invalidate any assertion invalidate(i.code.op0()); } } else if(i.is_throw()) { if(i.code.get_statement()==ID_expression && i.code.operands().size()==1 && i.code.op0().operands().size()==1) { // must not throw NULL exprt pointer=i.code.op0().op0(); if(pointer.type().subtype().get(ID_identifier)!="java::java.lang.AssertionError") { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "throwing null", "pointer dereference", i.source_location, pointer, guardt()); } } // this has no successor assertions.clear(); } else if(i.is_assert()) { if(i.source_location.get_bool("user-provided") && i.source_location.get_property_class()!="error label" && !enable_assertions) i.type=SKIP; } else if(i.is_assume()) { if(!enable_assumptions) i.type=SKIP; } else if(i.is_dead()) { if(enable_pointer_check) { assert(i.code.operands().size()==1); const symbol_exprt &variable=to_symbol_expr(i.code.op0()); // is it dirty? if(local_bitvector_analysis->dirty(variable)) { // need to mark the dead variable as dead goto_programt::targett t=new_code.add_instruction(ASSIGN); exprt address_of_expr=address_of_exprt(variable); exprt lhs=ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr(); if(!base_type_eq(lhs.type(), address_of_expr.type(), ns)) address_of_expr.make_typecast(lhs.type()); exprt rhs=if_exprt( side_effect_expr_nondett(bool_typet()), address_of_expr, lhs, lhs.type()); t->source_location=i.source_location; t->code=code_assignt(lhs, rhs); t->code.add_source_location()=i.source_location; } } } else if(i.is_end_function()) { if(i.function==goto_functionst::entry_point() && enable_memory_leak_check) { const symbolt &leak=ns.lookup(CPROVER_PREFIX "memory_leak"); const symbol_exprt leak_expr=leak.symbol_expr(); // add self-assignment to get helpful counterexample output goto_programt::targett t=new_code.add_instruction(); t->make_assignment(); t->code=code_assignt(leak_expr, leak_expr); source_locationt source_location; source_location.set_function(i.function); equal_exprt eq(leak_expr, gen_zero(ns.follow(leak.type))); add_guarded_claim( eq, "dynamically allocated memory never freed", "memory-leak", source_location, eq, guardt()); } } for(goto_programt::instructionst::iterator i_it=new_code.instructions.begin(); i_it!=new_code.instructions.end(); i_it++) { if(i_it->source_location.is_nil()) { i_it->source_location.id(irep_idt()); if(it->source_location.get_file()!=irep_idt()) i_it->source_location.set_file(it->source_location.get_file()); if(it->source_location.get_line()!=irep_idt()) i_it->source_location.set_line(it->source_location.get_line()); if(it->source_location.get_function()!=irep_idt()) i_it->source_location.set_function(it->source_location.get_function()); if(it->source_location.get_column()!=irep_idt()) i_it->source_location.set_column(it->source_location.get_column()); } if(i_it->function==irep_idt()) i_it->function=it->function; } // insert new instructions -- make sure targets are not moved while(!new_code.instructions.empty()) { goto_program.insert_before_swap(it, new_code.instructions.front()); new_code.instructions.pop_front(); it++; } }
void convert(const xmlt &xml, goto_programt &goto_program) { goto_program.clear(); goto_programt::instructionst &instructions = goto_program.instructions; xmlt::elementst::const_iterator it = xml.elements.begin(); for(; it != xml.elements.end(); it++) { goto_programt::targett inst = goto_program.add_instruction(); inst->targets.clear(); if(it->name=="goto") { inst->type = GOTO; } else if(it->name=="assume") { inst->type = ASSUME; } else if(it->name=="assert") { inst->type = ASSERT; } else if(it->name=="skip") { inst->type = SKIP; } else if(it->name=="end_function") { inst->type = END_FUNCTION; } else if(it->name=="location") { inst->type = LOCATION; } else if(it->name=="dead") { inst->type = DEAD; } else if(it->name=="atomic_begin") { inst->type = ATOMIC_BEGIN; } else if(it->name=="atomic_end") { inst->type = ATOMIC_END; } else if(it->name=="return") { inst->make_return(); } else if(it->name=="instruction") // OTHER { inst->make_other(); } else if(it->name=="assign") { inst->make_other(); inst->type=ASSIGN; } else if(it->name=="functioncall") { inst->make_other(); inst->type=FUNCTION_CALL; } else if(it->name=="thread_start") { inst->type = START_THREAD; } else if(it->name=="thread_end") { inst->type = END_THREAD; } else { std::cout << "Unknown instruction type encountered (" << it->name << ")"; std::cout << std::endl; return; } xmlt::elementst::const_iterator eit = it->elements.begin(); for(; eit != it->elements.end(); eit++) { if(eit->name=="location") { convert(*eit, inst->location); } else if(eit->name=="variables") { } else if(eit->name=="labels") { xmlt::elementst::const_iterator lit = eit->elements.begin(); for(; lit != eit->elements.end(); lit++) { if(lit->name=="label") { std::string ls = lit->get_attribute("name"); inst->labels.push_back(ls); } else { std::cout << "Unknown node in labels section." << std::endl; return; } } } else if(eit->name=="guard") { inst->guard.remove("value"); convert(*eit, inst->guard); } else if(eit->name=="code") { convert(*eit, inst->code); } else if(eit->name=="targets") { // Don't do anything here, we'll need a second run for that } else if(eit->name=="comment") { inst->location.set("comment", eit->data); } else if(eit->name=="function") { inst->function = eit->data; } } } // assign line numbers goto_program.compute_location_numbers(); // second run, for targets goto_programt::targett ins_it = instructions.begin(); it = xml.elements.begin(); for(; it != xml.elements.end() && ins_it!=instructions.end(); it++) { xmlt::elementst::const_iterator eit = it->elements.begin(); for(; eit != it->elements.end(); eit++) { if(eit->name=="targets") { xmlt::elementst::const_iterator tit = eit->elements.begin(); for(; tit != eit->elements.end(); tit++) { if(tit->name=="target") { goto_programt::targett tins = find_instruction(xml, instructions, tit->data); if(tins != instructions.end()) { // Here we insert the iterators that somehow seem // to be strange afterwards (see line 87) ins_it->targets.push_back(tins); } else { std::cout << "Warning: instruction not found when " "resolving target links." << std::endl; } } else { std::cout << "Unknown node in targets section." << std::endl; return; } } } } ins_it++; } // resolve links goto_program.update(); // std::cout << "TNI: " << goto_program.target_numbers.size() << std::endl; }