Beispiel #1
0
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++;
    }
  }
}
Beispiel #2
0
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++;
    }
  }
Beispiel #3
0
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;
}